.\" Copyright (c) 2002-2023 Julien Nadeau Carriere .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, .\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES .\" (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR .\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" .Dd December 21, 2022 .Dt AG_WIDGET 3 .Os Agar 1.7 .Sh NAME .Nm AG_Widget .Nd agar user interface element .Sh SYNOPSIS .Bd -literal #include #include .Ed .Sh DESCRIPTION .Nm is the base class for user interface elements in Agar. Widgets are organized in an ordered virtual filesystem of .Xr AG_Object 3 elements. The parent of a widget is referred to as its .Em Container . Container widgets include: .Xr AG_Box 3 , .Xr AG_Fixed 3 , .Xr AG_Pane 3 , .Xr AG_Scrollview 3 , .Xr AG_Titlebar 3 and .Xr AG_Window 3 itself. .Pp Widgets are attached to their containers with .Xr AG_ObjectAttach 3 and detached with .Xr AG_ObjectDetach 3 . Unattached widgets can be freed using .Xr AG_ObjectDestroy 3 . Agar handles garbage collection of windows (and attached widgets) internally. Attempting to destroy an active .Xr AG_Window 3 or a widget which is still attached to a parent is an error (which would trigger a fatal assertion in debug mode). .Pp Unless renamed with .Xr AG_ObjectSetName 3 , widget instances are given a generic name (e.g., "button0"). .Xr AG_ObjectFind 3 can be used to get a pointer to a widget by pathname (e.g., "box0/button0"). .Pp The .Xr AG_Variable 3 table of .Ft AG_Object is used to store bindings data, style properties and general user data. The .Xr AG_Event 3 table of .Ft AG_Object maps widget events (such as "button-pushed") to one or more event handlers (as registered by .Xr AG_SetEvent 3 or .Xr AG_AddEvent 3 ) . .Sh INHERITANCE HIERARCHY .Xr AG_Object 3 -> .Nm . .\" MANLINK(AG_WidgetClass) .Sh CLASS OPERATIONS Agar widget classes are described by the following structure: .Bd -literal .\" SYNTAX(c) typedef struct ag_widget_class { struct ag_object_class _inherit; void (*draw)(void *obj); void (*size_request)(void *obj, AG_SizeReq *req); int (*size_allocate)(void *obj, const AG_SizeAlloc *alloc); void (*mouse_button_down)(void *obj, AG_MouseButton btn, int x, int y); void (*mouse_button_up)(void *obj, AG_MouseButton btn, int x, int y); void (*mouse_motion)(void *obj, int x, int y, int dx, int dy); void (*key_down)(void *obj, AG_KeySym ksym, AG_KeyMod kmod, AG_Char ch); void (*key_up)(void *obj, AG_KeySym ksym, AG_KeyMod kmod, AG_Char ch); void (*touch)(void *obj, void *inputDevice, const AG_DriverEvent *event); void (*ctrl)(void *obj, void *inputDevice, const AG_DriverEvent *event); void (*joy)(void *obj, void *inputDevice, const AG_DriverEvent *event); } AG_WidgetClass; .Ed .Pp The .Fn draw method renders the widget to the graphics display (using GL, .Xr AG_WidgetPrimitives 3 or other methods). The code under .Fn draw is referred to as .Em rendering context . Widget primitives and operations such as .Fn AG_WidgetBlitSurface must be called only from rendering context. .Pp .Fn size_request should return an initial, preferred geometry in pixels (without any guarantee that the request will be satisfied). For example, an .Xr AG_Label 3 , might return the expected size of a rendered text label. .Pp .Fn size_allocate is called once the widget has been successfully allocated a new size or position within its parent (as described by the .Va w , .Va h , .Va x and .Va y members of the .Ft AG_SizeAlloc argument). Container widgets allocate the position and size of their children in .Fn size_allocate . .Pp .Fn size_allocate should return 0 on success and -1 if the allocation is not satisfactory for .Fn draw to work at all (in which case the .Dv UNDERSIZE flag will be set and .Fn draw will not run). .Pp The .Fn mouse_button_down method is invoked if the user presses a button while the cursor is located at coordinates .Fa x , .Fa y inside the widget's local coordinates system. .Pp The .Fn mouse_button_up method is invoked if the user releases a mouse button while the cursor is located at coordinates .Fa x , .Fa y relative to the widget's local coordinates system. The cursor must intersect the widget (or the widget hold an .Dv AG_WIDGET_UNFOCUSED_BUTTONUP grab). .Pp The .Fn mouse_motion method is invoked if the user moves the cursor to coordinates .Fa x , .Fa y in the widget's local coordinate system. The widget must hold focus (or hold an .Dv AG_WIDGET_UNFOCUSED_MOTION grab). The .Fa dx and .Fa dy arguments provide the displacement (in px) relative to the last mouse motion event. .Pp The .Fn key_down and .Fn key_up methods are invoked whenever the user presses or releases a key on the keyboard. The widget must hold focus (or a .Dv AG_WIDGET_UNFOCUSED_KEYDOWN / .Dv AG_WIDGET_UNFOCUSED_KEYUP grab). .Pp .\" MANLINK(AG_SizeReq) .\" MANLINK(AG_SizeAlloc) .Sh SIZING .nr nS 1 .Ft "void" .Fn AG_ExpandHoriz "AG_Widget *obj" .Pp .Ft "void" .Fn AG_ExpandVert "AG_Widget *obj" .Pp .Ft "void" .Fn AG_Expand "AG_Widget *obj" .Pp .Ft "void" .Fn AG_WidgetSizeReq "AG_Widget *obj" "AG_SizeReq *req" .Pp .Ft "void" .Fn AG_WidgetSizeAlloc "AG_Widget *obj" "AG_SizeAlloc *alloc" .Pp .Ft void .Fn AG_WidgetSetPosition "AG_Widget *obj" "int x" "int y" .Pp .Ft void .Fn AG_WidgetSetSize "AG_Widget *obj" "int w" "int h" .Pp .Ft void .Fn AG_WidgetSetGeometry "AG_Widget *obj" "AG_Rect rect" .Pp .Ft void .Fn AG_WidgetUpdate "AG_Widget *obj" .Pp .Ft void .Fn AG_WidgetUpdateCoords "AG_Widget *obj" "int x" "int y" .Pp .nr nS 0 The .Dv AG_WIDGET_HFILL flag hints to vertically-packing containers that this widget wants to fill any remaining space along the horizontal axis. .Dv AG_WIDGET_VFILL flag hints to horizontally-packing containers that this widget wants to fill any remaining space along the horizontal axis. .Pp The .Fn AG_ExpandHoriz and .Fn AG_ExpandVert functions set .Dv AG_WIDGET_HFILL and .Dv AG_WIDGET_VFILL , respectively. .Fn AG_Expand is equivalent to calling both .Fn AG_ExpandHoriz and .Fn AG_ExpandVert . .Pp .Fn AG_WidgetSizeReq invokes the .Fn size_request operation of the widget and returns its size requisition into .Fa req . .Fn AG_WidgetSizeAlloc allocates the given position and geometry of the widget. If the .Va w or .Va h argument is <= 0, the .Dv AG_WIDGET_UNDERSIZE flag is set, preventing the widget from subsequent rendering. .Pp .Fn AG_WidgetSizeReq and .Fn AG_WidgetSizeAlloc are meant to be called only from within the .Fn size_request and .Fn size_allocate functions of a container widget implementation, in order to size and position the child widgets attached to the container. .Pp The .Ft AG_SizeReq and .Ft AG_SizeAlloc structures are defined as follows: .Bd -literal .\" SYNTAX(c) typedef struct ag_size_req { int w, h; /* Requested geometry in pixels */ } AG_SizeReq; typedef struct ag_size_alloc { int w, h; /* Allocated geometry in pixels */ int x, y; /* Allocated position in pixels */ } AG_SizeAlloc; .Ed .Pp .Fn AG_WidgetSetPosition sets the effective position of the widget relative to its parent container. .Fn AG_WidgetSetSize sets the size of the widget in pixels. .Fn AG_WidgetSetGeometry sets both position and size of a widget from the specified .Ft AG_Rect . These functions are typically only used in the context of the .Fn size_request and .Fn size_allocate routines of container widgets. .Pp .Fn AG_WidgetUpdate requests an update of the computed coordinates and geometries of all widgets attached to the widget's current window. The widget may or may not be attached to a parent window (the actual update will be performed later, before rendering starts in .Fn AG_WindowDraw ) . .Fn AG_WidgetUpdate should be called following .Xr AG_ObjectAttach 3 or .Xr AG_ObjectDetach 3 calls made in event context, or external modifications to the .Va x , .Va y , .Va w , .Va h fields of the .Nm structure. .Pp .Fn AG_WidgetUpdateCoords is called internally to update the cached absolute display coordinates (the .Va rView rectangle) of .Fa wid and its descendents based on their current relative coordinates (the .Va x , .Va y , .Va w , .Va h members). The widget and its parent VFS must be locked. .Sh STYLE ATTRIBUTES .nr nS 1 .Ft "void" .Fn AG_SetStyle "AG_Widget *obj" "const char *attr" "const char *value" .Pp .Ft "void" .Fn AG_SetStyleF "AG_Widget *obj" "const char *attr" "const char *fmt" "..." .Pp .Ft "void" .Fn AG_SetFontFamily "AG_Widget *obj" "const char *family" .Pp .Ft "void" .Fn AG_SetFontSize "AG_Widget *obj" "const char *size" .Pp .Ft "void" .Fn AG_SetFontWeight "AG_Widget *obj" "const char *weight" .Pp .Ft "void" .Fn AG_SetFontStyle "AG_Widget *obj" "const char *style" .Pp .Ft "void" .Fn AG_SetFontStretch "AG_Widget *obj" "const char *stretch" .Pp .Ft "void" .Fn AG_SetFont "AG_Widget *obj" "const AG_Font *font" .Pp .Ft "void" .Fn AG_SetMargin "AG_Widget *obj" "const char *margin" .Pp .Ft "void" .Fn AG_SetPadding "AG_Widget *obj" "const char *padding" .Pp .\" MANLINK(AG_SetColor) .\" MANLINK(AG_SetColorDisabled) .\" MANLINK(AG_SetColorFocused) .\" MANLINK(AG_SetColorHover) .\" MANLINK(AG_SetBgColor) .\" MANLINK(AG_SetBgColorDisabled) .\" MANLINK(AG_SetBgColorFocused) .\" MANLINK(AG_SetBgColorHover) .\" MANLINK(AG_SetTextColor) .\" MANLINK(AG_SetTextColorDisabled) .\" MANLINK(AG_SetTextColorFocused) .\" MANLINK(AG_SetTextColorHover) .\" MANLINK(AG_SetLineColor) .\" MANLINK(AG_SetLineColorDisabled) .\" MANLINK(AG_SetLineColorFocused) .\" MANLINK(AG_SetLineColorHover) .\" MANLINK(AG_SetHighColor) .\" MANLINK(AG_SetHighColorDisabled) .\" MANLINK(AG_SetHighColorFocused) .\" MANLINK(AG_SetHighColorHover) .\" MANLINK(AG_SetSelColor) .\" MANLINK(AG_SetSelColorDisabled) .\" MANLINK(AG_SetSelColorFocused) .\" MANLINK(AG_SetSelColorHover) .Ft "void" .Fn AG_Set "AG_Widget *obj" "const char *color" .Pp .Ft "void" .Fn AG_SetDisabled "AG_Widget *obj" "const char *color" .Pp .Ft "void" .Fn AG_SetFocused "AG_Widget *obj" "const char *color" .Pp .Ft "void" .Fn AG_SetHover "AG_Widget *obj" "const char *color" .Pp .nr nS 0 .Fn AG_SetStyle sets the style attribute .Fa attr to the given .Fa value . .Pp See .Xr AG_StyleSheet 3 for the list of available attributes. .Pp The following routines are shorthand forms for .Fn AG_SetStyle . .Pp .Fn AG_SetFontFamily sets the "font-family" attribute, which can be either a font name or the name of a file located in one of the directories in the .Dv PATH_FONTS of .Xr AG_Config 3 . .Pp .Fn AG_SetFontSize sets the "font-size" attribute, which may contain the suffix "%" (relative size to the parent widget's font), the suffix "pt" (explicit size in vector-font points) or the suffix "px" (explicit size in bitmap-font pixels). .Pp Font sizes should normally be given in "%" so that the zoom function can work as expected (Agar's zoom works simply by increasing or decreasing the "font-size" of the target window). .Pp .Fn AG_SetFontWeight sets the "font-weight" attribute, which can be one of "Thin", "ExtraLight", "Light", "Regular" (default), "SemiBold", "Bold", "ExtraBold", "Black" or "!parent". .Pp .Fn AG_SetFontStyle sets the "font-style" attribute, which be one of "Normal" / "Regular", "Oblique", "Italic" or "!parent". .Pp .Fn AG_SetFontStretch sets the "font-stretch" attribute, which can be one of "Normal" / "Regular", "UltraCondensed", "Condensed", "SemiCondensed", "SemiExpanded", "Expanded" or "UltraExpanded". .Pp .Fn AG_SetFont sets (inherits) font style attributes "font-family", "font-weight" and "font-stretch" from those of the given .Fa font . .Pp .Fn AG_SetMargin sets the margin area around the widget. The argument can be of the form " " to set horizontal and vertical spacing in pixels, respectively. A single argument sets both horizontal and vertical spacings to the same value. .Pp .Fn AG_SetPadding sets the padding inside the widget area. The argument can be of the form " " to set each padding in pixels. A single argument sets all paddings to the same value. .Pp The following routines set color attributes. For the list of accepted formats for specifying colors, see .Xr AG_Color 3 . .Pp .Fn AG_SetColor sets the foreground primary ("color"). .Fn AG_SetBgColor sets the background primary ("background-color"). .Fn AG_SetTextColor sets the color for text and vector icons ("text-color"). .Fn AG_SetLineColor sets the color for lines and filled shapes ("line-color"). .Fn AG_SetHighColor sets the shading color for top and left 3D-style edges ("high-color"). .Fn AG_SetLowColor sets the shading color for bottom and right 3D-style edges ("low-color"). .Fn AG_SetSelColor sets the primary for indicating active selections ("selection-color"). .Pp The following routines set state-dependent color attributes .Fn AG_SetDisabled sets the given color for the widget "#disabled" state. .Fn AG_SetFocused sets the given color for the "#focused" state. .Fn AG_SetHover sets the given color for the "#hover" state. .Sh INPUT STATE .nr nS 1 .Ft "void" .Fn AG_WidgetEnable "AG_Widget *obj" .Pp .Ft "void" .Fn AG_WidgetDisable "AG_Widget *obj" .Pp .Ft "int" .Fn AG_WidgetEnabled "AG_Widget *obj" .Pp .Ft "int" .Fn AG_WidgetDisabled "AG_Widget *obj" .Pp .Ft "void" .Fn AG_PushDisabledState "AG_Widget *obj" .Pp .Ft "void" .Fn AG_PopDisabledState "AG_Widget *obj" .Pp .nr nS 0 A widget in DISABLED state will not accept user input other than that required for navigation (i.e., scrolling). .Fn AG_WidgetEnable clears the DISABLED state and .Fn AG_WidgetDisable sets it. These functions will raise the .Sq widget-enabled and .Sq widget-disabled events accordingly. .Pp .Fn AG_WidgetEnabled and .Fn AG_WidgetDisabled return the current state. .Pp .Fn AG_PushDisabledState arranges for widgets subsequently attached to a container widget .Fa obj to start in DISABLED state. The .Fa AG_WIDGET_DISABLED flag will be set on attach (without raising "widget-disabled"). .Sh FOCUS STATE Focus enables reception of input events that would be filtered out by default. The focused widget (in the currently focused window) will receive "mouse-motion", "mouse-button-up", "key-up" and "key-down" events. .Pp .nr nS 1 .Ft "int" .Fn AG_WidgetSetFocusable "AG_Widget *obj" "int enable" .Pp .Ft "int" .Fn AG_WidgetFocus "AG_Widget *obj" .Pp .Ft "void" .Fn AG_WidgetUnfocus "AG_Widget *obj" .Pp .Ft "int" .Fn AG_WidgetIsFocused "const AG_Widget *obj" .Pp .Ft "int" .Fn AG_WidgetIsFocusedInWindow "const AG_Widget *obj" .Pp .Ft "void" .Fn AG_WidgetForwardFocus "AG_Widget *obj" "AG_Widget *widgetToFocus" .Pp .nr nS 0 .Fn AG_WidgetSetFocusable clears or sets the .Dv AG_WIDGET_FOCUSABLE flag and returns the previous setting (0 = Not focusable, 1 = Focusable). .Pp .Fn AG_WidgetFocus focuses the specified widget and all of its parent widgets including the parent .Xr AG_Window 3 . Returns 1 on success and 0 if the widget is not accepting focus. .Pp .Fn AG_WidgetUnfocus removes the focus state from the given widget and its children, recursively. .Pp .Fn AG_WidgetIsFocused returns 1 if the widget is both focused in relation to its parent window, and the parent window itself is focused. .Fn AG_WidgetIsFocusedInWindow returns 1 if the widget is focused regardless of the focus state of its parent. .Pp .Fn AG_WidgetForwardFocus arranges automatic forwarding of the focus to a specified widget. Whenever .Fa obj gains focus, Agar will arrange for the focus to be transferred automatically to .Fa widgetToFocus . .Sh COORDINATES .nr nS 1 .Ft int .Fn AG_WidgetArea "AG_Widget *obj" "int x" "int y" .Pp .Ft int .Fn AG_WidgetRelativeArea "AG_Widget *obj" "int x" "int y" .Pp .nr nS 0 The .Fn AG_WidgetArea routine tests whether view coordinates .Fa x and .Fa y lie inside of the widget's allocated space. The .Fn AG_WidgetRelativeArea variant accepts widget coordinates. .Sh GRAPHICAL SURFACES These routines allow graphical surfaces to be managed (mapped in hardware or software) and transferred efficiently. They must be called from rendering context (i.e., the .Fn draw operation of .Nm ) only. .Pp .nr nS 1 .Ft void .Fn AG_WidgetBlit "AG_Widget *obj" "AG_Surface *src" "int x" "int y" .Pp .Ft int .Fn AG_WidgetMapSurface "AG_Widget *obj" "AG_Surface *su" .Pp .Ft int .Fn AG_WidgetMapSurfaceNODUP "AG_Widget *obj" "AG_Surface *su" .Pp .Ft void .Fn AG_WidgetReplaceSurface "AG_Widget *obj" "int surface_id" "AG_Surface *newSurface" .Pp .Ft void .Fn AG_WidgetReplaceSurfaceNODUP "AG_Widget *obj" "int surface_id" "AG_Surface *newSurface" .Pp .Ft void .Fn AG_WidgetUnmapSurface "AG_Widget *obj" "int surface_id" .Pp .Ft void .Fn AG_WidgetUpdateSurface "AG_Widget *obj" "int surface_id" .Pp .Ft void .Fn AG_WidgetBlitFrom "AG_Widget *obj" "AG_Widget *srcWidget" "int surface_id" "AG_Rect *rs" "int x" "int y" .Pp .Ft void .Fn AG_WidgetBlitSurface "AG_Widget *obj" "int surface_id" "int x" "int y" .Pp .nr nS 0 The .Fn AG_WidgetBlit function performs a software->hardware block image transfer ("blit") from the surface .Fa src to the video display at the given widget coordinates. .Fn AG_WidgetBlit must invoked in rendering context. See .Xr AG_Surface 3 for more information on the Agar surface structure. .Pp Software to hardware blits are slow, so the .Nm system provides a way to manage hardware surfaces (i.e., textures) and take advantage the texture capabilities of graphics hardware where it is available. .Pp .Fn AG_WidgetMapSurface registers the specified .Xr AG_Surface 3 with the widget, returning an integer handle to that surface. The surface can be subsequently rendered by calling .Fn AG_WidgetBlitSurface or .Fn AG_WidgetBlitFrom using this handle. The exact manner in which the surface is rendered depends on the Agar driver in use. For OpenGL-based drivers, a matching hardware texture is typically generated on the initial call to .Fn AG_WidgetBlitSurface and kept in cache for later use. .Pp By default, mapped surfaces are freed when the widget is destroyed. .Fn AG_WidgetMapSurfaceNODUP sets the "NODUP" flag on the given surface such that the widget system will never attempt to free the surface. .Pp Note that .Fn AG_WidgetMapSurface will not duplicate the surface. Instead, it will register the given surface pointer to be managed by the .Nm system. The surface pointer must remain valid for the lifetime of the widget (if in doubt, you can always use .Xr AG_SurfaceDup 3 to map a duplicate of the surface instead). .Pp .Fn AG_WidgetReplaceSurface replaces the contents of a previously-mapped surface with .Fa newSurface . The .Fn AG_WidgetReplaceSurfaceNODUP variant avoids duplicating the surface and sets the "NODUP" flag. .Pp .Fn AG_WidgetUnmapSurface destroys the given surface mapping. It is equivalent to invoking .Fn AG_WidgetReplaceSurface with a NULL surface. .Pp In OpenGL mode, .Fn AG_WidgetReplaceSurface and .Fn AG_WidgetUnmapSurface do not operate on textures immediately. GL texture delete operations are queued to be performed at the end of the current event-processing cycle. .Pp The .Fn AG_WidgetUpdateSurface function should be invoked whenever a mapped surface is changed. If hardware surfaces are supported, it will cause an upload of the software surface to the hardware (otherwise it is a no-op). .Pp The .Fn AG_WidgetBlitFrom function renders a previously mapped (possibly hardware) surface from the source widget .Fa srcWidget (using source rectangle .Fa rs ) onto the destination widget .Fa obj , at coordinates .Fa x , .Fa y . This function must be invoked in rendering context. .Pp The .Fn AG_WidgetBlitSurface variant invokes .Fn AG_WidgetBlitFrom with the same argument for both .Fa srcWidget and .Fa obj (and .Fa rs set to NULL). .Sh USING BINDINGS Widget states can be bound to memory locations containing data in a supported format. For example, the "state" binding of .Xr AG_Button 3 can be tied to an integer (or bits in an integer), such that the user pressing the button directly manipulates the integer value in memory. .Pp Bindings are documented under the heading .Dq BINDINGS section of the widget's manual page. For instance, .Xr AG_Slider 3 mentions "value" bindings to integers. Therefore, to control a byte of memory, one might use: .Bd -literal .\" SYNTAX(c) static Uint8 myByte = 0; AG_Slider *slider = AG_SliderNew(window, AG_SLIDER_HORIZ, 0); AG_BindUint8(slider, "value", &myByte); .Ed .Pp Or alternatively, using a shorthand constructor: .Bd -literal .\" SYNTAX(c) AG_SliderNewUint8(window, AG_SLIDER_HORIZ, 0, &myByte, NULL, NULL); .Ed .Pp This method is not limited to primitive data types. For example, .Xr AG_Textbox 3 can bind to a fixed-size memory buffer containing a C string in ASCII, UTF-8 or other supported encoding. .Pp The .Fn AG_Bind family of functions bind widget states to memory data. The .Fn AG_BindMp variants accept a pointer to a mutex which will be acquired prior to accessing the data. .Pp Since the state of a widget can influence its appearance (e.g., .Xr AG_Button 3 is drawn as a pressed button if its "state" is 1), it may be necessary to monitor the value and redraw when it changes. .Fn AG_RedrawOnChange arranges for this to occur automatically (see below). .Sh REDRAWING .nr nS 1 .Ft "void" .Fn AG_Redraw "AG_Widget *obj" .Pp .Ft "void" .Fn AG_RedrawOnChange "AG_Widget *obj" "int refresh_ms" "const char *binding_name" .Pp .Ft "int" .Fn AG_RedrawOnTick "AG_Widget *obj" "int refresh_ms" .Pp .nr nS 0 The .Fn AG_Redraw call signals that the widget must be redrawn to the display. It is equivalent to setting the .Va dirty flag on the parent window. If called from rendering context, .Fn AG_Redraw is a no-op. .Pp .Fn AG_RedrawOnChange arranges for the widget to be automatically redrawn whenever the value associated with the existing binding .Fa binding_name changes. The value of the binding will be checked at the specified interval .Fa refresh_ms in milliseconds. If a .Fa refresh_ms argument of -1 is passed, the effect of any previous .Fn AG_RedrawOnChange call with the specified binding is disabled. .Pp .Fn AG_RedrawOnTick enables or disables auto-refresh. Auto-refresh forces the widget to be redrawn unconditionally every .Fa refresh_ms milliseconds. If the .Fa refresh_ms argument is -1, auto-refresh is disabled. The .Fn AG_RedrawOnTick function returns the previous setting in ms (or -1 if auto-refresh was not set). .Sh WIDGET QUERIES .nr nS 1 .Ft "AG_Window *" .Fn AG_ParentWindow "AG_Widget *widget" .Pp .Ft "AG_Widget *" .Fn AG_WidgetFindFocused "AG_Window *win" .Pp .Ft "AG_Widget *" .Fn AG_WidgetFindPoint "const char *className" "int x" "int y" .Pp .Ft "AG_Widget *" .Fn AG_WidgetFindRect "const char *className" "int x" "int y" "int w" "int h" .Pp .nr nS 0 .Fn AG_ParentWindow returns a pointer to the parent .Xr AG_Window 3 for the given widget instance. The pointer is valid only as long as the parent VFS remains locked. If the widget is not attached, NULL is returned. .Pp .Fn AG_WidgetFindFocused returns the top-most focused widget under .Fa win . .Pp .Fn AG_WidgetFindPoint searches for the top-most widget which contains the point at display coordinates .Fa x , .Fa y . .Pp .Fn AG_WidgetFindRect searches for the top-most widget which encloses the rectangle described by display coordinates .Fa x , .Fa y , .Fa w , .Fa h completely. .Pp Both .Fn AG_WidgetFindPoint and .Fn AG_WidgetFindRect will only match widgets that are instances of .Fa className . The pattern "AG_Widget:*" would match any class. For details on the class-membership test, see: .Xr AG_OfClass 3 . .Pp Under threads, the object pointer returned by .Fn AG_WidgetFindFocused , .Fn AG_WidgetFindPoint and .Fn AG_WidgetFindRect is valid only for as long as the parent VFS is locked. .Sh RENDERING CONTROL .nr nS 1 .Ft void .Fn AG_PushClipRect "AG_Widget *obj" "const AG_Rect *r" .Pp .Ft void .Fn AG_PushClipRectInner "AG_Widget *obj" "const AG_Rect *r" .Pp .Ft void .Fn AG_PopClipRect "AG_Widget *obj" .Pp .Ft void .Fn AG_PushBlendingMode "AG_Widget *obj" "AG_AlphaFn src" "AG_AlphaFn dst" .Pp .Ft void .Fn AG_PopBlendingMode "AG_Widget *obj" .Pp .Ft "void" .Fn AG_WidgetDraw "AG_Widget *obj" .Pp .Ft "void" .Fn AG_BeginRendering "AG_Driver *drv" .Pp .Ft "void" .Fn AG_EndRendering "AG_Driver *drv" .Pp .Ft "void" .Fn AG_WidgetHide "AG_Widget *obj" .Pp .Ft "void" .Fn AG_WidgetShow "AG_Widget *obj" .Pp .Ft "void" .Fn AG_WidgetHideAll "AG_Widget *obj" .Pp .Ft "void" .Fn AG_WidgetShowAll "AG_Widget *obj" .Pp .Ft "int" .Fn AG_WidgetVisible "AG_Widget *obj" .Pp .Ft "AG_Surface *" .Fn AG_WidgetSurface "AG_Widget *obj" .Pp .nr nS 0 The .Fn AG_PushClipRect function pushes a rectangle (in widget-relative coordinates) onto the stack of clipping rectangles, and .Fn AG_PopClipRect pops the last entry from the clipping rectangle stack. The effective clipping rectangle will be the intersection of all rectangles on this stack. Both functions must be invoked in rendering context. .Pp The .Fn AG_PushClipRectInner variant of .Fn AG_PushClipRect offsets the width and height of the rectangle by -2px. .Pp .Fn AG_PushBlendingMode selects the source and destination functions for further pixel blending operations. It also pushes the current state onto the stack of alpha blending modes. Setting .Fa src to .Dv AG_ALPHA_ZERO and .Fa dst to .Dv AG_ALPHA_ONE (the default) effectively disables blending. Setting .Fa src to .Dv AG_ALPHA_SRC and .Fa dst to .Dv AG_ALPHA_ONE_MINUS_SRC is the most common case. See .Xr AG_AlphaFn 3 for the list of possible alpha blending modes. .Fn AG_PopBlendingMode pops the the last entry off of the stack of alpha blending modes. Both functions must be invoked from rendering context. .Pp The .Fn AG_WidgetDraw routine renders a widget to the display. It is invoked from either the event loop routine (such as .Xr AG_EventLoop 3 ) or from the .Fn draw operation of a widget. Container widgets must call .Fn AG_WidgetDraw explicitely in order to render their children. .Pp In an event loop, .Fn AG_WidgetDraw invocations must be enclosed between calls to .Fn AG_BeginRendering and .Fn AG_EndRendering . .Pp The .Fn AG_WidgetHide and .Fn AG_WidgetShow functions toggle the visibility of the specified widget (setting the .Dv AG_WIDGET_HIDE flag as appropriate). .Pp The .Fn AG_WidgetHideAll and .Fn AG_WidgetShowAll routines toggle the visibility of the specified widget and its children by setting the .Dv AG_WIDGET_VISIBLE flag (which works independently of .Dv AG_WIDGET_HIDE ) . These routines are intended to be used by container widgets (for example, .Xr AG_Notebook 3 which needs to show or hide tabbed containers). .Pp .Fn AG_WidgetVisible returns 1 if the widget is currently visible (equivalent to checking the .Dv AG_WIDGET_VISIBLE flag). .Pp The .Fn AG_WidgetSurface routine renders the widget to a newly-allocated .Xr AG_Surface 3 . This surface should be freed after use. .Sh WIDGET ACTIONS User-generated events such as key presses or mouse button events can be connected to .Em high-level actions such as executing a specified routine or controlling a boolean. The high-level actions of a widget are described by an array of .Fa AG_Action structures. .Pp Where the conditions for execution of an Action are fixed (e.g., a specific mouse button was clicked, or a specific key was pressed), use of .Fn AG_ActionOn* is preferred over low-level event handlers (such as "key-down" or "mouse-button-down") because it allows keyboard and mouse bindings to be configured by the end-user in a standard way. .Xr AG_Menu 3 also provides interfaces for working with widget actions. .Pp .\" MANLINK(AG_Action) .nr nS 1 .Ft "AG_Action *" .Fn AG_ActionFn "AG_Widget *obj" "const char *action" "void (*fn)(AG_Event *)" "const char *fnArgs" "..." .Pp .Ft "AG_Action *" .Fn AG_ActionSetInt "AG_Widget *obj" "const char *action" "int *variable" "int value" .Pp .Ft "AG_Action *" .Fn AG_ActionSetFlag "AG_Widget *obj" "const char *action" "Uint *variable" "Uint bitmask" "int value" .Pp .Ft "AG_Action *" .Fn AG_ActionToggleInt "AG_Widget *obj" "const char *action" "int *variable" .Pp .Ft "AG_Action *" .Fn AG_ActionToggleFlag "AG_Widget *obj" "const char *action" "Uint *variable" "Uint bitmask" .Pp .Ft void .Fn AG_ActionOnButtonDown "AG_Widget *obj" "int button" "const char *action" .Pp .Ft void .Fn AG_ActionOnButtonUp "AG_Widget *obj" "int button" "const char *action" .Pp .Ft void .Fn AG_ActionOnKeyDown "AG_Widget *obj" "AG_KeySym sym" "AG_KeyMod mod" "const char *action" .Pp .Ft void .Fn AG_ActionOnKeyUp "AG_Widget *obj" "AG_KeySym sym" "AG_KeyMod mod" "const char *action" .Pp .Ft void .Fn AG_ActionOnKey "AG_Widget *obj" "AG_KeySym sym" "AG_KeyMod mod" "const char *action" .Pp .Ft int .Fn AG_ExecMouseAction "AG_Widget *obj" "AG_ActionEventType type" "int button" "int x" "int y" .Pp .Ft int .Fn AG_ExecKeyAction "AG_Widget *obj" "AG_ActionEventType type" "AG_KeySym sym" "AG_KeyMod mod" .Pp .Ft int .Fn AG_ExecAction "AG_Widget *obj" "AG_Action *a" .Pp .nr nS 0 .Fn AG_ActionFn registers a new widget action which is to invoke a callback function .Fa fn , with arguments .Fa fnArgs . See .Xr AG_Event 3 for a description of the .Fa fnArgs format. .Pp .Fn AG_ActionSetInt registers a new action which is to set an integer .Fa variable to a specified .Fa value . Instead of an integer variable, .Fn AG_ActionSetFlag sets the bits specified by .Fa bitmask to the specified .Fa value (of 1 or 0). The .Fn AG_ActionToggleInt and .Fn AG_ActionToggleFlag variants do not take an explicit .Fa value argument, and toggle the current value instead. .Pp .Fn AG_ActionOnButtonDown and .Fn AG_ActionOnButtonUp tie an action to a button press and a button release event, respectively. The .Fa button argument specifies the button index (see .Xr AG_MouseButton 3 ) . .Fn AG_ActionOnKeyDown and .Fn AG_ActionOnKeyUp tie an action to a key press and key release event, respectively. The .Fa sym argument specifies the key (see .Xr AG_KeySym 3 ) , and .Fa mod specifies the modifier keys which must be in effect. To match any key or any modifier state, .Dv AG_KEY_ANY or .Dv AG_KEYMOD_ANY can be used. .Pp With .Fn AG_ActionOnKeyDown and .Fn AG_ActionOnKeyUp , the action is triggered once immediately on key press or key release. The .Fn AG_ActionOnKey variant ties an action to a key press, but with "key repeat" behavior. The action is triggered immediately once after an initial key press. If the key combination is held longer than the "key delay" (by default 250ms), the event is repeated with the "key repeat" interval (by default 30ms). .Pp If there are currently no event handlers registered for "key-up", "key-down", "mouse-button-up" and "mouse-button-down", the .Fn AG_ActionOn* functions automatically register event handlers which will invoke .Fn AG_ExecMouseAction or .Fn AG_ExecKeyAction as appropriate (see below). .Pp .Fn AG_ExecMouseAction executes any action associated with mouse button events. It is typically invoked from the "mouse-button-down" and "mouse-button-up" event handlers of the widget. Accepted .Fa type values are .Dv AG_ACTION_ON_BUTTONDOWN and .Dv AG_ACTION_ON_BUTTONUP . .Fa button is the pressed button index (see .Xr AG_MouseButton 3 ) . .Fa x and .Fa y is the position of the cursor in the widget's coordinate system. .Pp .Fn AG_ExecKeyAction executes any action associated with keyboard events. It is typically invoked from the "key-down" and "key-up" event handlers of the widget. Accepted .Fa type values are .Dv AG_ACTION_ON_KEYDOWN and .Dv AG_ACTION_ON_KEYUP . .Fa sym and .Fa mod specify the key index and modifier state (see .Xr AG_KeySym 3 and .Xr AG_KeyMod 3 ) . .Pp .Fn AG_ExecAction executes the specified action. .Fn AG_ExecAction is rarely used directly, but it is invoked internally by the .Fn AG_ExecFooAction functions. .Sh EVENTS The GUI system may send .Nm objects the following events: .Pp .Bl -tag -compact -width 2n .It Fn font-changed "void" The active font family, size or style attributes have changed. The new font may be accessed by the .Va font pointer of .Nm . .It Fn padding-changed "void" The padding attribute has changed. .It Fn palette-changed "void" At least one entry in the color palette of the widget has changed. .It Fn widget-shown "void" The widget is now visible. User-defined handlers must be appended with .Xr AG_AddEvent 3 (as opposed to replaced by .Xr AG_SetEvent 3 ) since the base class needs its own "widget-shown" handler. .It Fn widget-hidden "void" The widget is no longer visible. User-defined handlers must be appended with .Xr AG_AddEvent 3 (as opposed to replaced by .Xr AG_SetEvent 3 ) since the base class needs its own "widget-hidden" handler. .It Fn widget-enabled "void" Input state has been enabled with .Xr AG_WidgetEnable 3 . .It Fn widget-disabled "void" Input state has been disabled with .Xr AG_WidgetDisable 3 . .It Fn widget-gainfocus "void" The widget now holds focus inside its parent container. .It Fn widget-lostfocus "void" The widget no longer holds focus. .It Fn widget-reshape "void" The widget was resized and .Dv USE_OPENGL is set. The handler is expected to update the .Dv GL_PROJECTION or .Dv GL_MODELVIEW matrices. .It Fn widget-overlay "void" Invoked following the .Fn draw operation; requires .Dv USE_OPENGL . .It Fn widget-underlay "void" Invoked prior to the .Fn draw operation; requires .Dv USE_OPENGL . .El .Pp The following events are usually generated by input devices. .Pp DEPRECATED: As of Agar 1.7.0 the events described below have been superceded by the input device methods of .Ft AG_WidgetClass . If a method is defined then the method is called and no event is generated. .Pp .Bl -tag -compact -width 2n .It Fn mouse-motion "int x" "int y" "int xRel" "int yRel" "int buttons" The widget is receiving mouse motion events, and the cursor has been moved. .Fa x and .Fa y are the coordinates of the cursor in the widget's local coordinate system (these coordinates may be negative or exceed the widget's dimensions if the cursor is not in the widget's area). .Fa xRel and .Fa yRel represent the displacement relative to the last position of the mouse cursor. The .Fa buttons argument is a bitmask representing the state of mouse buttons (see .Xr AG_MouseButton 3 ) . .It Fn mouse-button-up "int button" "int x" "int y" The widget is receiving mouse button release events, and .Fa button has been released. .Fa x and .Fa y are the cursor coordinates in the widget's local coordinate system. .It Fn mouse-button-down "int button" "int x" "int y" The widget is receiving mouse button events, and .Fa button has been pressed. .Fa x and .Fa y are the cursor coordinates in the widget's local coordinate system. .It Fn mouse-over "void" The cursor has entered or is leaving the widget's allocated area and the .Dv AG_WIDGET_USE_MOUSEOVER option is set. .It Fn key-down "int key" "int mod" "Ulong ch" The widget is receiving keyboard events and .Fa key has been pressed. .Fa mod is a bitmask representing the state of the current key modifiers. If non-zero, .Fa ch is the matching UCS-4 (or ASCII) character. .It Fn key-up "int key" "int mod" "Ulong ch" The widget is receiving keyboard events and .Fa key has been released. .Fa mod is a bitmask representing the state of the current key modifiers. If non-zero, .Fa ch is the matching UCS-4 (or ASCII) character. .El .Sh STRUCTURE DATA For the .Ft AG_Widget object: .Bl -tag -width "AG_ActionVec *actions " .It Ft Uint flags Option flags (see .Sx FLAGS section below). .It Ft int x, y Location of the upper-left pixel (relative to the parent widget). Read-only (set by container). .It Ft int w, h Size in pixels. Read-only (set by container). .It Ft AG_Rect r Cached rectangle at 0,0. Read-only. .It Ft AG_Rect2 rView Cached position & size in display coordinates. Read-only with one exception: before calling .Xr AG_WidgetDraw 3 to render a child widget, a container widget may temporarily override its .Va rView in order to render it at a given offset. .It Ft AG_Rect2 rSens Rectangle of sensitivity to mouse events (in display coordinates). Scrolling containers such as .Xr AG_Scrollview 3 may adjust this rectangle for partially-visible widgets along its edges. .It Ft AG_WidgetPalette pal Color palette: a 4 x 8 (or .Dv AG_WIDGET_NSTATES by .Dv AG_WIDGET_NCOLORS ) array of .Xr AG_Color 3 . Entries are set by the current .Xr AG_StyleSheet 3 . Read-only (use .Fn AG_SetStyle to modify) with one exception: before calling .Xr AG_WidgetDraw 3 to render a child widget, a container widget may temporarily override and restore its palette entries. .It Ft AG_Font *font Current font associated with the widget (see .Xr AG_Font 3 ) . Read-only (use .Fn AG_SetStyle or the .Fn AG_SetFont* family of functions to modify). .It Ft AG_ActionVec *actions Dynamic array of .Ft AG_Action structures describing high-level actions (see .Sx WIDGET ACTIONS ) . .El .Sh FLAGS The .Va flags member of the .Nm structure accepts the following flags: .Bl -tag -width "AG_WIDGET_UNFOCUSED_BUTTONDOWN " .It AG_WIDGET_HFILL Fill any remaining (horizontal) space (hint to vertically-packing containers). .It AG_WIDGET_VFILL Fill any remaining (vertical) space (hint to horizontal-packing containers). .It AG_WIDGET_EXPAND Shorthand for both .Dv AG_WIDGET_HFILL and .Dv AG_WIDGET_VFILL . .It AG_WIDGET_HIDE Disable rendering of this widget. .It AG_WIDGET_VISIBLE This widget and its parent window are both currently visible (read-only). .It AG_WIDGET_UNDERSIZE Disable rendering of this widget because it is too small to draw (read-only). .It AG_WIDGET_DISABLE_ON_ATTACH Make attached widgets start in DISABLED state (without raising "widget-disabled"). .It AG_WIDGET_DISABLED Advise that widget is not accepting user input. This state influences color and styling. The effect of this option is widget-dependent (read-only; see .Sx INPUT STATE section). .It AG_WIDGET_MOUSEOVER A mouse cursor currently intersects the widget's area (read-only; updated internally if the .Dv AG_WIDGET_USE_MOUSEOVER flag is set). This state influences color and styling. .It AG_WIDGET_FOCUSABLE The widget is allowed to grab the focus. .It AG_WIDGET_UNFOCUSED_MOTION Receive "mouse-motion" events unconditionally (focus is required by default). .It AG_WIDGET_UNFOCUSED_BUTTONUP Receive all .Fn mouse-button-up (mouse button release) events unconditionally. .It AG_WIDGET_UNFOCUSED_BUTTONDOWN Receive all .Fn mouse-button-up (mouse button press) events unconditionally. .It AG_WIDGET_UNFOCUSED_KEYDOWN Receive .Fn key-down (key press) events unconditionally (focus is required by default). .It AG_WIDGET_UNFOCUSED_KEYUP Receive .Fn key-up (key release) events unconditionally (focus is required by default). .It AG_WIDGET_CATCH_TAB When the user presses the .Dv TAB key, generate normal .Fn key-down and .Fn key-up events. Without this flag, .Dv TAB is used to change the focus to the next widget. .It AG_WIDGET_NOSPACING Advise parent container to disable spacing and padding (per standard box model), for this widget. .It AG_WIDGET_USE_TEXT Allow .Fn draw , .Fn size_request and .Fn size_allocate to use .Xr AG_TextRender 3 and .Xr AG_TextSize 3 . Agar will automatically save/restore the font engine state according to the widget's computed style settings. Enables reception of the "font-changed" event. .It AG_WIDGET_USE_OPENGL Establish a separate OpenGL context for the widget. Before the .Fn draw routine is invoked, Agar will automatically save/restore the .Dv GL_PROJECTION , .Dv GL_MODELVIEW and .Dv GL_TEXTURE matrices along with GL attributes .Dv GL_TRANSFORM_BIT , .Dv GL_VIEWPORT_BIT and .Dv GL_TEXTURE_BIT . Enables reception of "widget-reshape", "widget-overlay" and "widget-underlay" events. .It AG_WIDGET_USE_MOUSEOVER Detect cursor motion over the widget's area; update the .Dv AG_WIDGET_MOUSEOVER flag and generate "mouse-over" events accordingly. .El .Sh SEE ALSO .Xr AG_Cursor 3 , .Xr AG_KeyMod 3 , .Xr AG_KeySym 3 , .Xr AG_Rect 3 , .Xr AG_StyleSheet 3 , .Xr AG_Surface 3 , .Xr AG_Variable 3 , .Xr AG_WidgetPrimitives 3 , .Xr AG_Window 3 .Sh HISTORY The .Nm interface first appeared in Agar 1.0. Widget-level variable bindings have been replaced by generic .Xr AG_Variable 3 pointers in Agar 1.3.4. Actions were introduced in Agar 1.4.0. .Dv AG_WIDGET_USE_OPENGL first appeared in Agar 1.5, replacing .Xr AG_GLView 3 . Agar 1.6.0 first made the .Va actions , .Va pal and .Va rSens structure members public. The .Fn AG_SetStyleF , .Fn AG_PushBlendingMode and .Fn AG_PopBlendingMode functions appeared in Agar 1.6.0. The "font-changed" and "palette-changed" events appeared in Agar 1.6.0. .Fn AG_PushDisabledState , .Fn AG_PopDisabledState , the .Dv AG_WIDGET_DISABLE_ON_ATTACH flag and the "padding-changed" event appeared in Agar 1.7.0.