1 /* Public domain */
2
3 #ifndef _AGAR_GUI_WIDGET_H_
4 #define _AGAR_GUI_WIDGET_H_
5
6 #include <agar/config/have_sdl.h>
7 #include <agar/config/have_opengl.h>
8
9 #include <agar/gui/gui.h>
10 #include <agar/gui/geometry.h>
11 #include <agar/gui/colors.h>
12 #include <agar/gui/surface.h>
13 #include <agar/gui/anim.h>
14 #include <agar/gui/stylesheet.h>
15 #include <agar/gui/mouse.h>
16 #include <agar/gui/keyboard.h>
17 #include <agar/gui/drv.h>
18
19 #include <agar/gui/begin.h>
20
21 struct ag_widget;
22 struct ag_cursor;
23 struct ag_font;
24
25 /* Widget size requisition and allocation. */
26 typedef struct ag_size_req {
27 int w, h; /* Requested geometry in pixels */
28 } AG_SizeReq;
29 typedef struct ag_size_alloc {
30 int w, h; /* Allocated geometry in pixels */
31 int x, y; /* Allocated position in pixels */
32 } AG_SizeAlloc;
33
34 /* Widget class description. */
35 typedef struct ag_widget_class {
36 struct ag_object_class _inherit;
37 void (*draw)(void *);
38 void (*size_request)(void *, AG_SizeReq *);
39 int (*size_allocate)(void *, const AG_SizeAlloc *);
40 } AG_WidgetClass;
41
42 /* Relative size specification of visual element. */
43 typedef enum ag_widget_sizespec {
44 AG_WIDGET_BAD_SPEC, /* Parser error */
45 AG_WIDGET_PIXELS, /* Pixel count */
46 AG_WIDGET_PERCENT, /* % of available space */
47 AG_WIDGET_STRINGLEN, /* Width of given string */
48 AG_WIDGET_FILL /* Fill remaining space */
49 } AG_SizeSpec;
50
51 /* Packing mode (i.e., for container widgets). */
52 enum ag_widget_packing {
53 AG_PACK_HORIZ,
54 AG_PACK_VERT
55 };
56
57 /* Flag description (i.e., for AG_Checkbox(3)) */
58 typedef struct ag_flag_descr {
59 Uint bitmask; /* Bitmask */
60 const char *descr; /* Bit(s) description */
61 int writeable; /* User-editable */
62 } AG_FlagDescr;
63
64 /*
65 * Widget Actions
66 */
67 typedef enum ag_action_type {
68 AG_ACTION_FN, /* Execute function */
69 AG_ACTION_SET_INT, /* Set an integer */
70 AG_ACTION_TOGGLE_INT, /* Toggle an integer */
71 AG_ACTION_SET_FLAG, /* Set specified bits in a word */
72 AG_ACTION_TOGGLE_FLAG /* Toggle specified bits in a word */
73 } AG_ActionType;
74
75 typedef struct ag_action {
76 AG_ActionType type;
77 struct ag_widget *widget; /* Back pointer to widget */
78 AG_Event *fn; /* Callback function */
79 void *p; /* Target (for SET_*) */
80 int val; /* Value (for SET_*) */
81 Uint bitmask; /* Bitmask (for SET_FLAG) */
82 } AG_Action;
83
84 typedef enum ag_action_event_type {
85 AG_ACTION_ON_BUTTONDOWN, /* On mouse-button-down */
86 AG_ACTION_ON_BUTTONUP, /* On mouse-button-up */
87 AG_ACTION_ON_KEYDOWN, /* On key-down */
88 AG_ACTION_ON_KEYUP, /* On key-up */
89 AG_ACTION_ON_KEYREPEAT /* On key-down, with key repeat */
90 #define AG_ACTION_ON_BUTTON \
91 AG_ACTION_ON_BUTTONDOWN /* For mousewheel events */
92 } AG_ActionEventType;
93
94 typedef struct ag_action_tie {
95 AG_ActionEventType type; /* Trigger event type */
96 union {
97 AG_MouseButton button; /* Button index */
98 struct {
99 AG_KeySym sym; /* Matching symbol */
100 AG_KeyMod mod; /* Matching modifier */
101 AG_Timer toRepeat; /* Key repeat timer */
102 } key;
103 } data;
104 char action[64]; /* Action name */
105 AG_TAILQ_ENTRY(ag_action_tie) ties;
106 } AG_ActionTie;
107
108 /* Redraw tie (for AG_RedrawOn*() feature). */
109 enum ag_redraw_tie_type {
110 AG_REDRAW_ON_CHANGE,
111 AG_REDRAW_ON_TICK
112 };
113 typedef struct ag_redraw_tie {
114 enum ag_redraw_tie_type type;
115 char name[AG_VARIABLE_NAME_MAX]; /* Polled variable */
116 AG_Variable Vlast; /* Last accessed data */
117 int VlastInited;
118 AG_Timer to; /* Polling timer */
119 Uint ival; /* Polling interval */
120 AG_TAILQ_ENTRY(ag_redraw_tie) redrawTies; /* In widget */
121 } AG_RedrawTie;
122
123 /* Cursor-change area */
124 typedef struct ag_cursor_area {
125 AG_Rect r; /* Area in window */
126 struct ag_cursor *c; /* Associated cursor */
127 struct ag_widget *wid; /* Associated widget */
128 int stock; /* Stock cursor? */
129 AG_TAILQ_ENTRY(ag_cursor_area) cursorAreas;
130 } AG_CursorArea;
131
132 /*
133 * Standard widget colors (CSS-defined, state-dependent, globally-inheritable).
134 *
135 * SYNC: agWidgetStateNames[], agWidgetColorNames[], agDefaultPalette[].
136 */
137 #define AG_WIDGET_NSTATES 5
138 #define AG_WIDGET_NCOLORS 5
139 enum ag_widget_color_state {
140 AG_DEFAULT_STATE, /* Unfocused state */
141 AG_DISABLED_STATE, /* Inactive state (#disabled) */
142 AG_FOCUSED_STATE, /* Active / focused state (#focused) */
143 AG_HOVER_STATE, /* "Mouse over" state (#hover) */
144 AG_SELECTED_STATE /* "Selected" state (#selected) */
145 };
146 enum ag_widget_color {
147 AG_COLOR = 0, /* Background ("color") */
148 AG_TEXT_COLOR, /* Rendered text ("text-color") */
149 AG_LINE_COLOR, /* Line drawing ("line-color") */
150 AG_SHAPE_COLOR, /* Filled shapes ("shape-color") */
151 AG_BORDER_COLOR /* Decorative borders ("border-color") */
152 };
153 typedef struct {
154 AG_Color c[AG_WIDGET_NSTATES][AG_WIDGET_NCOLORS];
155 } AG_WidgetPalette;
156 #define AG_WCOLOR(wid,which) AGWIDGET(wid)->pal.c[AGWIDGET(wid)->cState][which]
157 #define AG_WCOLOR_DEF(wid,which) AGWIDGET(wid)->pal.c[AG_DEFAULT_STATE][which]
158 #define AG_WCOLOR_DIS(wid,which) AGWIDGET(wid)->pal.c[AG_DISABLED_STATE][which]
159 #define AG_WCOLOR_HOV(wid,which) AGWIDGET(wid)->pal.c[AG_HOVER_STATE][which]
160 #define AG_WCOLOR_SEL(wid,which) AGWIDGET(wid)->pal.c[AG_SELECTED_STATE][which]
161
162 /* Base Agar widget */
163 typedef struct ag_widget {
164 struct ag_object obj;
165
166 Uint flags;
167 #define AG_WIDGET_FOCUSABLE 0x000001 /* Can grab focus */
168 #define AG_WIDGET_FOCUSED 0x000002 /* Holds focus (computed) */
169 #define AG_WIDGET_UNFOCUSED_MOTION 0x000004 /* All mousemotion events */
170 #define AG_WIDGET_UNFOCUSED_BUTTONUP 0x000008 /* All mousebuttonup events */
171 #define AG_WIDGET_UNFOCUSED_BUTTONDOWN 0x000010 /* All mousebuttondown events */
172 #define AG_WIDGET_VISIBLE 0x000020 /* Widget is visible (computed) */
173 #define AG_WIDGET_HFILL 0x000040 /* Expand to fill width */
174 #define AG_WIDGET_VFILL 0x000080 /* Expand to fill height */
175 #define AG_WIDGET_USE_OPENGL 0x000100 /* Set up separate GL context */
176 #define AG_WIDGET_HIDE 0x000200 /* Don't draw this widget */
177 #define AG_WIDGET_DISABLED 0x000400 /* Don't respond to input */
178 #define AG_WIDGET_MOUSEOVER 0x000800 /* Mouseover state (computed) */
179 #define AG_WIDGET_CATCH_TAB 0x001000 /* Catch tab key events */
180 #define AG_WIDGET_GL_RESHAPE 0x002000 /* Pending GL view reshape */
181 #define AG_WIDGET_UNDERSIZE 0x004000 /* Size alloc failed (computed) */
182 #define AG_WIDGET_NOSPACING 0x008000 /* No box model (container-specific) */
183 #define AG_WIDGET_UNFOCUSED_KEYDOWN 0x010000 /* All mousebuttondown events */
184 #define AG_WIDGET_UNFOCUSED_KEYUP 0x020000 /* All mousebuttondown events */
185 #define AG_WIDGET_TABLE_EMBEDDABLE 0x080000 /* Usable in polled tables */
186 #define AG_WIDGET_UPDATE_WINDOW 0x100000 /* Request an AG_WindowUpdate() as soon as possible */
187 #define AG_WIDGET_QUEUE_SURFACE_BACKUP 0x200000 /* Must backup surfaces ASAP */
188 #define AG_WIDGET_USE_TEXT 0x400000 /* Use Agar's font engine */
189 #define AG_WIDGET_USE_MOUSEOVER 0x800000 /* Update MOUSEOVER flag and generate mouseover events */
190 #define AG_WIDGET_EXPAND (AG_WIDGET_HFILL|AG_WIDGET_VFILL)
191
192 int x, y; /* Coordinates in container */
193 int w, h; /* Allocated geometry */
194 AG_Rect2 rView; /* Computed view coordinates */
195 AG_Rect2 rSens; /* Cursor notification area */
196 AG_Surface **surfaces; /* Registered surfaces */
197 Uint *surfaceFlags; /* Surface flags */
198 #define AG_WIDGET_SURFACE_NODUP 0x01 /* Don't free on destroy */
199 #define AG_WIDGET_SURFACE_REGEN 0x02 /* Texture needs to be regenerated */
200 Uint nsurfaces;
201 Uint *textures; /* Cached textures (driver-specific) */
202 AG_TexCoord *texcoords; /* Cached texture coordinates */
203
204 struct ag_widget *focusFwd; /* For ForwardFocus() */
205 struct ag_window *window; /* Back ptr to parent window */
206 struct ag_driver *drv; /* Back ptr to driver */
207 struct ag_driver_class *drvOps; /* Back ptr to driver class */
208
209 AG_Tbl actions; /* Registered actions */
210 AG_TAILQ_HEAD_(ag_action_tie) mouseActions; /* Mouse action ties */
211 AG_TAILQ_HEAD_(ag_action_tie) keyActions; /* Kbd action ties */
212 AG_TAILQ_HEAD_(ag_redraw_tie) redrawTies; /* For AG_RedrawOn*() */
213 AG_TAILQ_HEAD_(ag_cursor_area) cursorAreas; /* Cursor-change areas
214 (not yet attached) */
215
216 AG_StyleSheet *css; /* Alternate style sheet */
217 enum ag_widget_color_state cState; /* Current CSS color state */
218 struct ag_font *font; /* Computed font reference */
219 AG_WidgetPalette pal; /* Computed color palette */
220
221 struct {
222 float mProjection[16]; /* Projection matrix */
223 float mModelview[16]; /* Modelview matrix */
224 } gl;
225 } AG_Widget;
226
227 #define AGWIDGET(wi) ((AG_Widget *)(wi))
228 #define AGWIDGET_OPS(wi) ((AG_WidgetClass *)AGOBJECT(wi)->cls)
229 #define AGWIDGET_SUPER_OPS(wi) ((AG_WidgetClass *)AGOBJECT(wi)->cls->super)
230
231 #define AGWIDGET_SURFACE(wi, ind) AGWIDGET(wi)->surfaces[ind]
232 #define AGWIDGET_TEXTURE(wi, ind) AGWIDGET(wi)->textures[ind]
233 #define AGWIDGET_SURFACE_NODUP(wi, ind) (AGWIDGET(wi)->surfaceFlags[ind] & \
234 AG_WIDGET_SURFACE_NODUP)
235 #define AGSTYLE(p) AGWIDGET(p)->theme
236
237 #define AGWIDGET_KEYBOARD(obj) \
238 (((obj) != NULL) ? AGWIDGET(obj)->drv->kbd : \
239 (agDriverSw != NULL) ? AGDRIVER(agDriverSw)->kbd: \
240 NULL)
241
242 #if defined(_AGAR_INTERNAL) || defined(_USE_AGAR_GUI)
243 # define WIDGET(wi) AGWIDGET(wi)
244 # define WIDGET_OPS(wi) AGWIDGET_OPS(wi)
245 # define WIDGET_SUPER_OPS(wi) AGWIDGET_SUPER_OPS(wi)
246 # define WSURFACE(wi,ind) AGWIDGET_SURFACE((wi),(ind))
247 # define WTEXTURE(wi,ind) AGWIDGET_TEXTURE((wi),(ind))
248 # define WSURFACE_NODUP(wi,ind) AGWIDGET_SURFACE_NODUP((wi),(ind))
249 # define STYLE(p) AGSTYLE(p)
250 # define WIDTH(p) AGWIDGET(p)->w
251 # define HEIGHT(p) AGWIDGET(p)->h
252 # define WCOLOR(wid,which) AG_WCOLOR((wid),(which))
253 # define WCOLOR_DEF(wid,which) AG_WCOLOR_DEF((wid),(which))
254 # define WCOLOR_DIS(wid,which) AG_WCOLOR_DIS((wid),(which))
255 # define WCOLOR_HOV(wid,which) AG_WCOLOR_HOV((wid),(which))
256 # define WCOLOR_SEL(wid,which) AG_WCOLOR_SEL((wid),(which))
257 # define TEXT_COLOR AG_TEXT_COLOR
258 # define LINE_COLOR AG_LINE_COLOR
259 # define SHAPE_COLOR AG_SHAPE_COLOR
260 # define BORDER_COLOR AG_BORDER_COLOR
261 #endif /* _AGAR_INTERNAL or _USE_AGAR_GUI */
262
263 struct ag_window;
264 struct ag_font;
265 AG_TAILQ_HEAD(ag_widgetq, ag_widget);
266
267 __BEGIN_DECLS
268 extern AG_WidgetClass agWidgetClass;
269 extern const char *agWidgetPropNames[];
270 extern const char *agWidgetStateNames[];
271 extern const char *agWidgetColorNames[];
272 extern AG_WidgetPalette agDefaultPalette;
273
274 void AG_WidgetDraw(void *);
275 void AG_WidgetSizeReq(void *, AG_SizeReq *);
276 void AG_WidgetSizeAlloc(void *, AG_SizeAlloc *);
277 void AG_WidgetSetFocusable(void *, int);
278 void AG_WidgetForwardFocus(void *, void *);
279
280 int AG_WidgetFocus(void *);
281 void AG_WidgetUnfocus(void *);
282 AG_Widget *AG_WidgetFindFocused(void *);
283 void *AG_WidgetFindPoint(const char *, int, int);
284 void *AG_WidgetFindRect(const char *, int, int, int, int);
285 void AG_WidgetUpdateCoords(void *, int, int);
286
287 int AG_WidgetMapSurface(void *, AG_Surface *);
288 void AG_WidgetReplaceSurface(void *, int, AG_Surface *);
289 #define AG_WidgetUnmapSurface(w, n) \
290 AG_WidgetReplaceSurface((w),(n),NULL)
291 #define AG_WidgetBlitSurface(p,n,x,y) \
292 AG_WidgetBlitFrom((p),(p),(n),NULL,(x),(y))
293 #ifdef HAVE_OPENGL
294 void AG_WidgetBlitGL(void *, AG_Surface *, float, float);
295 void AG_WidgetBlitSurfaceGL(void *, int, float, float);
296 void AG_WidgetBlitSurfaceFlippedGL(void *, int, float, float);
297 void AG_WidgetFreeResourcesGL(void *);
298 void AG_WidgetRegenResourcesGL(void *);
299 #endif
300
301 int AG_WidgetSensitive(void *, int, int);
302 AG_SizeSpec AG_WidgetParseSizeSpec(const char *, int *);
303 int AG_WidgetScrollDelta(Uint32 *);
304 void *AG_WidgetFind(void *, const char *);
305
306 void AG_WidgetShow(void *);
307 void AG_WidgetHide(void *);
308 void AG_WidgetShowAll(void *);
309 void AG_WidgetHideAll(void *);
310 void AG_WidgetEnableAll(void *);
311 void AG_WidgetDisabledAll(void *);
312
313 void AG_WidgetInheritDraw(void *);
314 void AG_WidgetInheritSizeRequest(void *, AG_SizeReq *);
315 int AG_WidgetInheritSizeAllocate(void *, const AG_SizeAlloc *);
316 AG_Surface *AG_WidgetSurface(void *);
317
318 void AG_RedrawOnChange(void *, int, const char *);
319 void AG_RedrawOnTick(void *, int);
320
321 void AG_WidgetStdKeyDown(AG_Event *);
322 void AG_WidgetStdKeyUp(AG_Event *);
323 void AG_WidgetStdMouseButtonDown(AG_Event *);
324 void AG_WidgetStdMouseButtonUp(AG_Event *);
325
326 AG_Action *AG_ActionFn(void *, const char *, AG_EventFn, const char *, ...);
327 AG_Action *AG_ActionSetInt(void *, const char *, int *, int);
328 AG_Action *AG_ActionToggleInt(void *, const char *, int *);
329 AG_Action *AG_ActionSetFlag(void *, const char *, Uint *, Uint, int);
330 AG_Action *AG_ActionToggleFlag(void *, const char *, Uint *, Uint);
331
332 void AG_ActionOnButtonDown(void *, int, const char *);
333 void AG_ActionOnButtonUp(void *, int, const char *);
334 #define AG_ActionOnButton(w,b,a) \
335 AG_ActionOnButtonDown((w),(b),(a))
336
337 void AG_ActionOnKey(void *, AG_KeySym, AG_KeyMod, const char *);
338 void AG_ActionOnKeyDown(void *, AG_KeySym, AG_KeyMod, const char *);
339 void AG_ActionOnKeyUp(void *, AG_KeySym, AG_KeyMod, const char *);
340
341 int AG_ExecMouseAction(void *, AG_ActionEventType, int, int, int);
342 int AG_ExecKeyAction(void *, AG_ActionEventType, AG_KeySym, AG_KeyMod);
343 int AG_ExecAction(void *, AG_Action *);
344
345 void AG_WidgetEnable(void *);
346 void AG_WidgetDisable(void *);
347
348 void AG_WidgetCompileStyle(void *);
349 void AG_WidgetCopyStyle(void *, void *);
350 void AG_WidgetFreeStyle(void *);
351
352 void AG_SetFont(void *, const struct ag_font *);
353 void AG_SetStyle(void *, const char *, const char *);
354
355 /* Return the widget state. The Widget object must be locked. */
356 static __inline__ int
AG_WidgetEnabled(void * p)357 AG_WidgetEnabled(void *p)
358 {
359 return !(AGWIDGET(p)->flags & AG_WIDGET_DISABLED);
360 }
361 static __inline__ int
AG_WidgetDisabled(void * p)362 AG_WidgetDisabled(void *p)
363 {
364 return (AGWIDGET(p)->flags & AG_WIDGET_DISABLED);
365 }
366
367 /* Return the widget's visibility state. The Widget object must be locked. */
368 static __inline__ int
AG_WidgetVisible(void * p)369 AG_WidgetVisible(void *p)
370 {
371 return (AGWIDGET(p)->flags & AG_WIDGET_VISIBLE);
372 }
373
374 /*
375 * Return the focus state of the widget inside of its parent window (not
376 * necessarily the effective focus). The Widget object must be locked.
377 */
378 static __inline__ int
AG_WidgetIsFocusedInWindow(void * p)379 AG_WidgetIsFocusedInWindow(void *p)
380 {
381 return (AGWIDGET(p)->flags & AG_WIDGET_FOCUSED);
382 }
383
384 /* Test whether view coordinates x,y lie in widget's allocated space. */
385 static __inline__ int
AG_WidgetArea(void * p,int x,int y)386 AG_WidgetArea(void *p, int x, int y)
387 {
388 AG_Widget *wid = AGWIDGET(p);
389
390 return (x > wid->rView.x1 && y > wid->rView.y1 &&
391 x < wid->rView.x2 && y < wid->rView.y2);
392 }
393
394 /* Test whether widget coordinates x,y lie in widget's allocated space. */
395 static __inline__ int
AG_WidgetRelativeArea(void * p,int x,int y)396 AG_WidgetRelativeArea(void *p, int x, int y)
397 {
398 AG_Widget *wid = AGWIDGET(p);
399
400 return (x >= 0 &&
401 y >= 0 &&
402 x < wid->w &&
403 y < wid->h);
404 }
405
406 /* Expand widget to fill available space in parent container. */
407 static __inline__ void
AG_Expand(void * wid)408 AG_Expand(void *wid)
409 {
410 AG_ObjectLock(wid);
411 AGWIDGET(wid)->flags |= AG_WIDGET_EXPAND;
412 AG_ObjectUnlock(wid);
413 }
414 static __inline__ void
AG_ExpandHoriz(void * wid)415 AG_ExpandHoriz(void *wid)
416 {
417 AG_ObjectLock(wid);
418 AGWIDGET(wid)->flags |= AG_WIDGET_HFILL;
419 AG_ObjectUnlock(wid);
420 }
421 static __inline__ void
AG_ExpandVert(void * wid)422 AG_ExpandVert(void *wid)
423 {
424 AG_ObjectLock(wid);
425 AGWIDGET(wid)->flags |= AG_WIDGET_VFILL;
426 AG_ObjectUnlock(wid);
427 }
428
429 /* Signal a change in a widget surface. */
430 #ifdef HAVE_OPENGL
431 # define AG_WidgetUpdateSurface(wid,name) do { \
432 AGWIDGET(wid)->surfaceFlags[(name)] |= AG_WIDGET_SURFACE_REGEN; \
433 } while (0)
434 #else
435 # define AG_WidgetUpdateSurface(wid,name)
436 #endif
437
438 /*
439 * Request that all computed widget coordinates and geometries in the widget's
440 * current window be updated as soon as possible. The widget may or may not
441 * be currently attached to a window at the time the call is made.
442 */
443 static __inline__ void
AG_WidgetUpdate(void * obj)444 AG_WidgetUpdate(void *obj)
445 {
446 AG_Widget *wid = (AG_Widget *)obj;
447
448 AG_ObjectLock(wid);
449 wid->flags |= AG_WIDGET_UPDATE_WINDOW;
450 AG_ObjectUnlock(wid);
451 }
452
453 /*
454 * Push a clipping rectangle onto the stack, by widget-relative coordinates.
455 * Must be invoked from GUI rendering context.
456 */
457 static __inline__ void
AG_PushClipRect(void * obj,AG_Rect pr)458 AG_PushClipRect(void *obj, AG_Rect pr)
459 {
460 AG_Widget *wid = (AG_Widget *)obj;
461 AG_Rect r;
462
463 r.x = wid->rView.x1 + pr.x;
464 r.y = wid->rView.y1 + pr.y;
465 r.w = pr.w;
466 r.h = pr.h;
467 wid->drvOps->pushClipRect(wid->drv, r);
468 }
469
470 /*
471 * Pop a clipping rectangle off the clipping rectangle stack.
472 * Must be invoked from GUI rendering context.
473 */
474 static __inline__ void
AG_PopClipRect(void * obj)475 AG_PopClipRect(void *obj)
476 {
477 AG_Widget *wid = (AG_Widget *)obj;
478
479 wid->drvOps->popClipRect(wid->drv);
480 }
481
482 /* Set the blending mode, pushing the current mode on a stack. */
483 static __inline__ void
AG_PushBlendingMode(void * obj,AG_BlendFn fnSrc,AG_BlendFn fnDst)484 AG_PushBlendingMode(void *obj, AG_BlendFn fnSrc, AG_BlendFn fnDst)
485 {
486 AG_Widget *wid = (AG_Widget *)obj;
487
488 wid->drvOps->pushBlendingMode(wid->drv, fnSrc, fnDst);
489 }
490
491 /* Restore the last blending mode. */
492 static __inline__ void
AG_PopBlendingMode(void * obj)493 AG_PopBlendingMode(void *obj)
494 {
495 AG_Widget *wid = (AG_Widget *)obj;
496
497 wid->drvOps->popBlendingMode(wid->drv);
498 }
499
500 /* Offset the coordinates of an AG_Rect per widget coordinates. */
501 static __inline__ void
AG_WidgetOffsetRect(void * obj,AG_Rect * r)502 AG_WidgetOffsetRect(void *obj, AG_Rect *r)
503 {
504 AG_Widget *wid = (AG_Widget *)obj;
505
506 r->x += wid->rView.x1;
507 r->y += wid->rView.y1;
508 }
509
510 /*
511 * Variant of AG_WidgetMapSurface() that sets the NODUP flag such that
512 * the surface is not freed by the widget.
513 */
514 static __inline__ int
AG_WidgetMapSurfaceNODUP(void * obj,AG_Surface * su)515 AG_WidgetMapSurfaceNODUP(void *obj, AG_Surface *su)
516 {
517 AG_Widget *wid = (AG_Widget *)obj;
518 int name;
519
520 AG_ObjectLock(wid);
521 if ((name = AG_WidgetMapSurface(wid, su)) != -1) {
522 wid->surfaceFlags[name] |= AG_WIDGET_SURFACE_NODUP;
523 }
524 AG_ObjectUnlock(wid);
525 return (name);
526 }
527
528 /* Variant of WidgetReplaceSurface() that sets the NODUP flag. */
529 static __inline__ void
AG_WidgetReplaceSurfaceNODUP(void * obj,int name,AG_Surface * su)530 AG_WidgetReplaceSurfaceNODUP(void *obj, int name, AG_Surface *su)
531 {
532 AG_Widget *wid = (AG_Widget *)obj;
533
534 AG_ObjectLock(wid);
535 #ifdef AG_DEBUG
536 if (name < 0 || name >= (int)wid->nsurfaces)
537 AG_FatalError("Bad surface handle");
538 #endif
539 AG_WidgetReplaceSurface(wid, name, su);
540 wid->surfaceFlags[name] |= AG_WIDGET_SURFACE_NODUP;
541 AG_ObjectUnlock(wid);
542 }
543
544 /*
545 * Draw an unmapped surface at given coordinates in the widget's coordinate
546 * system. With hardware-accelerated drivers, this operation is slow compared
547 * to drawing of mapped surfaces, since a software->hardware copy is done.
548 */
549 static __inline__ void
AG_WidgetBlit(void * obj,AG_Surface * s,int x,int y)550 AG_WidgetBlit(void *obj, AG_Surface *s, int x, int y)
551 {
552 AG_Widget *wid = (AG_Widget *)obj;
553
554 wid->drvOps->blitSurface(wid->drv, wid, s,
555 wid->rView.x1 + x,
556 wid->rView.y1 + y);
557 }
558
559 /*
560 * Perform a hardware or software blit from a mapped surface to the display
561 * at coordinates relative to the widget, using clipping.
562 */
563 static __inline__ void
AG_WidgetBlitFrom(void * obj,void * objSrc,int s,AG_Rect * r,int x,int y)564 AG_WidgetBlitFrom(void *obj, void *objSrc, int s, AG_Rect *r, int x, int y)
565 {
566 AG_Widget *wid = (AG_Widget *)obj;
567 AG_Widget *widSrc = (AG_Widget *)objSrc;
568
569 if (s == -1 || widSrc->surfaces[s] == NULL)
570 return;
571
572 wid->drvOps->blitSurfaceFrom(wid->drv, wid, widSrc, s, r,
573 wid->rView.x1 + x,
574 wid->rView.y1 + y);
575 }
576
577 /*
578 * Routines for direct access to keyboard key and modifier state
579 * from widget code.
580 */
581 static __inline__ int *
AG_GetKeyState(void * obj)582 AG_GetKeyState(void *obj)
583 {
584 AG_Keyboard *kbd = AGWIDGET_KEYBOARD(obj);
585 return (kbd->keyState);
586 }
587 static __inline__ void
AG_SetKeyState(void * obj,int * ks)588 AG_SetKeyState(void *obj, int *ks)
589 {
590 AG_Keyboard *kbd = AGWIDGET_KEYBOARD(obj);
591 memcpy(kbd->keyState, ks, kbd->keyCount*sizeof(int));
592 }
593 static __inline__ int
AG_GetKeyCount(void * obj)594 AG_GetKeyCount(void *obj)
595 {
596 AG_Keyboard *kbd = AGWIDGET_KEYBOARD(obj);
597 return (kbd->keyCount);
598 }
599 static __inline__ Uint
AG_GetModState(void * obj)600 AG_GetModState(void *obj)
601 {
602 AG_Keyboard *kbd = AGWIDGET_KEYBOARD(obj);
603 return (kbd->modState);
604 }
605 static __inline__ void
AG_SetModState(void * obj,Uint ms)606 AG_SetModState(void *obj, Uint ms)
607 {
608 AG_Keyboard *kbd = AGWIDGET_KEYBOARD(obj);
609 kbd->modState = ms;
610 }
611 __END_DECLS
612
613 #ifdef AG_LEGACY
614 # include <agar/gui/widget_legacy.h>
615 #endif /* AG_LEGACY */
616
617 #include <agar/gui/close.h>
618 #endif /* _AGAR_GUI_WIDGET_H_ */
619