.\" Copyright (c) 2009-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_DRIVER 3 .Os Agar 1.7 .Sh NAME .Nm AG_Driver .Nd agar low-level driver interface .Sh SYNOPSIS .Bd -literal #include #include .Ed .Sh DESCRIPTION .\" IMAGE(/widgets/AG_DriverGLX.png, "The Xorg/glx driver") Agar implements low-level access to the graphics hardware, event processing and window management using a modular driver interface. The class registration interface allows Agar to be "ported" to new platforms, environments and graphics systems. New drivers can be implemented as part of an application or third-party library, without need for changes in the Agar code itself. .Pp For the list of drivers included in the Agar distribution, see the .Xr AG_InitGraphics 3 manual page under "AVAILABLE DRIVERS". .Pp The interface differs based on whether an underlying window system is available. All drivers are a subclass of .Ft AG_Driver . The .Ft AG_DriverSw subclass (for "single-window") is used by drivers that do not interface (at least not directly) with an underlying window system. For example, the "sdlfb" and "sdlgl" drivers use the SDL 1.x API, and are therefore limited to a single native window. Another example would be a simple framebuffer in an embedded device, which might also use .Ft AG_DriverSw . When a single-window driver is used, Agar provides an internal window manager. .Pp The .Ft AG_DriverMw subclass (for "multiple-window") is used by drivers that talk to some underlying window system. In a multiple-window environment, each .Xr AG_Window 3 is associated with a "native" window on the system. For example, the "glx" driver uses the Xlib API to manage windows and the GLX extension to create accelerated rendering contexts. .Pp The event processing functions of .Nm are important to applications which use custom event loops (see .Xr AG_CustomEventLoop 3 for an example). They make it possible for Agar applications to catch and process low-level events in a driver-independent way (see .Sx EVENTS below). .Sh DRIVER INTERFACE .nr nS 1 .Ft "AG_Driver *" .Fn AG_DriverOpen "AG_DriverClass *dc" "const char *spec" .Pp .Ft "void" .Fn AG_DriverClose "AG_Driver *d" .Pp .Ft "void" .Fn AG_ListDriverNames "char *buf" "AG_Size buf_len" .Pp .Ft int .Fn AG_UsingGL "AG_Driver *d" .Pp .Ft int .Fn AG_UsingSDL "AG_Driver *d" .Pp .Ft int .Fn AG_GetDisplaySize "AG_Driver *d" "Uint *w" "Uint *h" .Pp .nr nS 0 The .Fn AG_DriverOpen function creates a new instance of a driver class, as described by .Fa dc (see section below). .Fn AG_DriverClose destroys a driver instance. These two functions are seldom used directly, since they are called internally from .Xr AG_InitGraphics 3 (or .Xr AG_WindowNew 3 in the case of multiple-window drivers). The optional .Fa spec argument may include a colon-separated list of driver options. .Pp The .Fn AG_ListDriverNames returns a space-separated list of available drivers for the current platform, into the specified buffer .Fa buf of size .Fa buf_len . .Pp The .Fn AG_UsingGL and .Fn AG_UsingSDL functions return 1 if Agar is using OpenGL or SDL, respectively. .Fa d is a pointer to the driver instance (or if NULL, use the default driver instance). .Pp The .Fn AG_GetDisplaySize function obtains the maximum available display area in pixels. On success, the dimensions are returned into the .Fa w and .Fa h arguments, and the function returns 0. .Fa d is a pointer to the driver instance (or if NULL, use the default driver instance). .Sh DRIVER CLASS STRUCTURE The .Ft AG_DriverClass structure inherits from the base .Xr AG_Object 3 class, and is defined as follows: .Bd -literal .\" SYNTAX(c) typedef struct ag_driver_class { struct ag_object_class _inherit; const char *name; /* Short name */ enum ag_driver_type type; /* Driver type */ enum ag_driver_wm_type wm; /* Window manager type */ Uint flags; /* Driver class options */ /* Initialization */ int (*open)(void *d, const char *spec); void (*close)(void *d); int (*getDisplaySize)(Uint *w, Uint *h); /* Event processing */ void (*beginEventProcessing)(void *d); int (*pendingEvents)(void *d); int (*getNextEvent)(void *d, AG_DriverEvent *dev); int (*processEvent)(void *d, AG_DriverEvent *dev); void (*genericEventLoop)(void *d); void (*endEventProcessing)(void *d); void (*terminate)(void); /* Rendering and texture management */ void (*beginRendering)(void *d); void (*renderWindow)(AG_Window *w); void (*endRendering)(void *d); void (*fillRect)(void *d, const AG_Rect *r, const AG_Color *c); void (*updateRegion)(void *d, const AG_Rect *r); void (*uploadTexture)(void *d, Uint *id, AG_Surface *s, AG_TexCoord *c); void (*updateTexture)(void *d, Uint id, AG_Surface *s, AG_TexCoord *c); void (*deleteTexture)(void *d, Uint id); int (*setRefreshRate)(void *d, int fps); /* Clipping and blending controls */ void (*pushClipRect)(void *d, const AG_Rect *r); void (*popClipRect)(void *d); void (*pushBlendingMode)(void *d, AG_AlphaFn s, AG_AlphaFn d); void (*popBlendingMode)(void *d); /* Hardware cursor interface */ AG_Cursor *(*createCursor)(void *d, Uint w, Uint h, const Uint8 *data, const Uint8 *mask, int xHot, int yHot); void (*freeCursor)(void *d, AG_Cursor *curs); int (*setCursor)(void *d, AG_Cursor *curs); void (*unsetCursor)(void *d); int (*getCursorVisibility)(void *d); void (*setCursorVisibility)(void *d, int flag); /* Widget surface operations */ void (*blitSurface)(void *d, AG_Widget *wid, AG_Surface *s, int x, int y); void (*blitSurfaceFrom)(void *d, AG_Widget *wid, int s, const AG_Rect *r, int x, int y); #ifdef HAVE_OPENGL void (*blitSurfaceGL)(void *d, AG_Widget *wid, AG_Surface *s, float w, float h); void (*blitSurfaceFromGL)(void *d, AG_Widget *wid, int surface, float w, float h); void (*blitSurfaceFlippedGL)(void *d, AG_Widget *wid, int surface, float w, float h); #endif void (*backupSurfaces)(void *d, AG_Widget *wid); void (*restoreSurfaces)(void *d, AG_Widget *wid); int (*renderToSurface)(void *d, AG_Widget *wid, AG_Surface **s); /* Rendering operations */ void (*putPixel)(void *d, int x, int y, const AG_Color *c); void (*putPixel32)(void *d, int x, int y, Uint32 px); void (*putPixelRGB8)(void *d, int x, int y, Uint8 r, Uint8 g, Uint8 b); #if AG_MODEL == AG_LARGE void (*putPixel64)(void *d, int x, int y, Uint64 px); void (*putPixelRGB16)(void *d, int x, int y, Uint16 r, Uint16 g, Uint16 b); #endif void (*blendPixel)(void *d, int x, int y, const AG_Color *c, AG_AlphaFn fnSrc, AG_AlphaFn fnDst); void (*drawLine)(void *d, int x1, int y1, int x2, int y2, const AG_Color *c); void (*drawLineH)(void *d, int x1, int x2, int y, const AG_Color *c); void (*drawLineV)(void *d, int x, int y1, int y2, const AG_Color *c); void (*drawLineBlended)(void *d, int x1, int y1, int x2, int y2, const AG_Color *c, AG_AlphaFn fnSrc, AG_AlphaFn fnDst); void (*drawLineW)(void *d, int x1, int y1, int x2, int y2, const AG_Color *c, float width); void (*drawLineW_Sti16)(void *d, int x1, int y1, int x2, int y2, const AG_Color *c, float width, Uint16 mask); void (*drawTriangle)(void *d, const AG_Pt *v1, const AG_Pt *v2, const AG_Pt *v3, const AG_Color *c); void (*drawPolygon)(void *d, const AG_Pt *pts, Uint nPts, const AG_Color *c); void (*drawPolygonSti32)(void *d, const AG_Pt *pts, Uint nPts, const AG_Color *c, const Uint8 *stipple); void (*drawArrow)(void *d, float angle, int x, int y, int h, const AG_Color *c1, const AG_Color *c2); void (*drawBoxRounded)(void *d, const AG_Rect *r, int z, int radius, const AG_Color *c1, const AG_Color *c2); void (*drawBoxRoundedTop)(void *d, const AG_Rect *r, int z, int radius, const AG_Color *c1, const AG_Color *c2, const AG_Color *c3); void (*drawCircle)(void *d, int x, int y, int radius, const AG_Color *c); void (*drawCircleFilled)(void *d, int x, int y, int radius, const AG_Color *c); void (*drawRectFilled)(void *d, const AG_Rect *r, const AG_Color *c); void (*drawRectBlended)(void *d, const AG_Rect *r, const AG_Color *c, AG_AlphaFn fnSrc, AG_AlphaFn fnDst); void (*drawRectDithered)(void *d, const AG_Rect *r, const AG_Color *c); /* Typography */ void (*updateGlyph)(void *d, AG_Glyph *gl); void (*drawGlyph)(void *d, const AG_Glyph *gl, int x, int y); /* Display list management */ void (*deleteList)(void *d, Uint listID); /* Clipboard integration */ char *(*getClipboardText)(void *d); int (*setClipboardText)(void *d, const char *text); /* Mouse auto-capture control */ void (*setMouseAutoCapture)(void *d, int state); } AG_DriverClass; .Ed .Pp The .Va type field should be set to .Dv AG_FRAMEBUFFER if this driver renders directly to video memory or a framebuffer, or .Dv AG_VECTOR if this driver uses OpenGL for rendering. .Pp The .Va wm field may be set to .Dv AG_WM_SINGLE for single-window drivers, or .Dv AG_WM_MULTIPLE for multiple-window drivers. .Pp Acceptable values for the .Va flags field include: .Bl -tag -compact -width "AG_DRIVER_TEXTURES " .It AG_DRIVER_OPENGL OpenGL calls are supported. .It AG_DRIVER_SDL1 SDL 1.x calls are supported. .It AG_DRIVER_SDL2 SDL 2.x calls are supported. .It AG_DRIVER_SDL SDL (1.x or 2.x) calls are supported. .It AG_DRIVER_TEXTURES Texture management operations are supported. .El .Pp The .Fn open method initializes a new driver instance. It is expected to initialize the .Va mouse , .Va kbd and .Va joys members of .Nm (see .Xr AG_MouseNew 3 , .Xr AG_KeyboardNew 3 and .Xr AG_JoystickNew 3 ) . .Fn open should return 0 on success or -1 on failure. .Pp The .Fn close method is invoked to destroy a driver instance. It is expected to destroy all attached input devices. .Pp The .Fn getDisplaySize method writes the total available display size in pixels to .Fa w and .Fa h and returns 0 on success or -1 on failure. For single-window drivers, this is the size of the display available to Agar. For multiple-window drivers, this is the total size of the desktop (if multiple workspaces are supported, it should be the size of one workspace). .Pp The .Fn beginEventProcessing callback is invoked before event processing begins. Most drivers will not need to do anything here. .Pp .Fn pendingEvents returns a non-zero value if there are events waiting to be processed (see .Fn AG_PendingEvents ) . .Pp .Fn getNextEvent retrieves and remove the next event from the queue (see .Fn AG_GetNextEvent ) . .Pp .Fn processEvent processes the event described by .Fa dev (see .Fn AG_ProcessEvent ) . .Pp The .Fn genericEventLoop method is obsolete as of Agar-1.5 (see .Xr AG_EventLoop 3 ) . .Pp The .Fn endEventProcessing callback is invoked after event processing is done. For most drivers, there is nothing to do here. .Pp The .Fn terminate operation is obsolete as of Agar-1.5 (see .Xr AG_Terminate 3 ) . .Pp The .Fn beginRendering and .Fn endRendering operations are invoked by .Xr AG_BeginRendering 3 and .Xr AG_EndRendering 3 to prepare for rendering of GUI elements. .Pp The .Fn renderWindow operation renders an Agar window. Usually, it will simply invoke .Xr AG_WidgetDraw 3 on .Fa win . Framebuffer drivers may also want to update video regions from here. .Pp The .Fn fillRect operation is expected to fill a rectangle .Fa r with color .Fa c . .Pp The .Fn updateRegion operation, usually specific to framebuffer drivers, is expected to update a region of video memory represented by .Fa r . .Pp .Fn uploadTexture , .Fn updateTexture and .Fn deleteTexture are specific to drivers with texture management facilities. .Fn uploadTexture creates a texture from an .Xr AG_Surface 3 , returning the computed texture coordinates. .Fn updateTexture is expected to update an existing texture from a recently modified surface. .Fn deleteTexture arranges for the specified texture to be deleted as soon as possible. .Pp The .Fn setRefreshRate operation is invoked by .Xr AG_SetRefreshRate 3 , to configure a fixed refresh rate, as a driver-specific hint that can be ignored. .Pp .Fn pushClipRect should create a clipping rectangle over .Fa r . If a clipping rectangle is already in effect, it should be saved on a stack. .Fn popClipRect pops the last clipping rectangle off the stack. .Pp .Fn pushBlendingMode should configure an alpha blending mode (see .Xr AG_AlphaFn 3 ) . If a blending mode is already set, it should be saved on a stack. .Fn popBlendingMode pops the last blending mode off the stack. .Pp The following operations are optional and provide Agar with access over hardware cursors. See .Xr AG_Cursor 3 for details on the Agar cursor control interface. .Pp The .Fn createCursor operation creates a hardware cursor from the bitmap data .Fa data and transparency mask .Fa mask . The hotspot coordinates are given in .Fa xHot , .Fa yHot . If a hardware cursor cannot be allocated, the call should return NULL. .Fn freeCursor destroys any hardware cursor corresponding to the given .Ft AG_Cursor structure. .Pp The .Fn setCursor operation changes the current cursor to the specified cursor, returning 0 on success or -1 on failure. .Fn unsetCursor reverts to the default cursor. .Pp The .Fn getCursorVisibility and .Fn setCursorVisibility routines retrieve and set the cursor visibility flag. .Pp The following operations form the backend of the .Xr AG_Widget 3 surface operations such as .Xr AG_WidgetBlitFrom 3 . They all accept a .Ft AG_Widget argument, and coordinate arguments are always with respect to the widget's local coordinate system. .Pp .Fn blitSurface implements .Xr AG_WidgetBlit 3 , which performs an unaccelerated (software) blit from any .Xr AG_Surface 3 , to target coordinates .Fa x , .Fa y . Note: Efficient code should use .Fn blitSurfaceFrom instead. .Pp .Fn blitSurfaceFrom implements .Xr AG_WidgetBlitFrom 3 , which uses a widget-mapped surface as source. If a texture unit is available then the previously uploaded hardware texture is used as source. If texture hardware is not available, a software blit is done. .Pp The .Fn blitSurfaceGL and .Fn blitSurfaceFromGL variants are specific to OpenGL drivers. Instead of accepting an explicit source or destination rectangle parameter, they rely on the current transformation matrix being set accordingly. .Fn blitSurfaceFlippedGL reverses the order of the rows in the image. .Pp The .Fn backupSurfaces operation should create a software backup of all surfaces registered under the given widget. .Fn restoreSurfaces restores a widget's surfaces from backup. These operations are needed with OpenGL on some platforms, where a window resize may result in a loss of OpenGL context data. .Pp The .Fn renderToSurface operation renders a widget to a newly allocated .Xr AG_Surface 3 , returned into the .Fa su argument. The function should return 0 on success or -1 on failure. .Pp .Fn putPixel , .Fn putPixel32 , .Fn putPixel64 , .Fn putPixelRGB8 and .Fn putPixelRGB16 write a packed pixel of specified color at coordinates .Fa x , .Fa y . If the display surface uses 8-bit precision components, .Fn putPixel64 and .Fn putPixelRGB16 should compress component ranges to the best 8-bit approximation. .Pp .Fn blendPixel blends the pixel at .Fa x , .Fa y against the specified .Ft AG_Color using the source and destination blending factors .Fa fnSrc and .Fa fnDst . .Pp .Fn drawLine renders a line of color .Fa C from endpoint .Fa x1 , .Fa y1 to endpoint .Fa x2 , .Fa y2 . The .Fn drawLineH operation renders a horizontal line, and .Fn drawLineV renders a vertical line. .Fn drawLineBlended renders a line with transparency (see .Xr AG_AlphaFn 3 ) . .Pp .Fn drawArrow renders an arrow of length .Fa h at coordinates .Fa x , .Fa y and clockwise rotation .Fa angle (0=up, 90=right, 180=down, 270=left). .Pp .Fn drawBoxRounded renders a 3D-style box of depth .Fa z , with corners rounded to radius .Fa rad . The .Fn drawBoxRoundedTop variant only rounds the two top corners. .Pp The .Fn drawCircle operation renders a circle of radius .Fa r , centered around .Fa x , .Fa y . The .Fn drawCircle2 variant adds a 3D-style effect. .Pp The .Fn drawRectFilled operation fills the target rectangle .Fa r with the given color .Fn drawRectBlended renders a filled rectangle with transparency (see .Xr AG_AlphaFn 3 ) . .Fn drawRectDithered renders a filled rectangle with ditering effect (commonly used to illustrate "disabled" GUI controls). .Pp The .Fn updateGlyph operation ensures that the specified font glyph (see .Xr AG_Text 3 ) is ready to be rendered. OpenGL drivers, for example, can use this operation to upload a rendered version of the glyph to the texture hardware. The .Fn drawGlyph operation renders a given font glyph at target coordinates .Fa x , .Fa y . The target point will correspond to the top left corner of the rendered glyph. .Pp The .Fn deleteList operation arranges for the specified display list to be deleted as soon as possible (typically in the .Fn endRendering routine). .Pp The optional .Fn getClipboardText operation returns a newly-allocated string with the clipboard contents (in UTF-8). The returned string is freeable by the caller. .Pp The optional .Fn setClipboardText operation sets the clipboard contents to a copy of the given UTF-8 string and returns 0 on success or -1 on failure. .Pp The optional .Fn setMouseAutoCapture operation enables (1), disables (0) or resets (-1) mouse auto-capture behavior due to mouse button events. When mouse auto-capture is enabled, the mouse is automatically captured on Mouse Button Down and released on Mouse Button Up. .Sh EVENTS .nr nS 1 .Ft int .Fn AG_PendingEvents "AG_Driver *d" .Pp .Ft int .Fn AG_GetNextEvent "AG_Driver *d" "AG_DriverEvent *dev" .Pp .Ft int .Fn AG_ProcessEvent "AG_Driver *d" "AG_DriverEvent *dev" .Pp .Ft int .Fn AG_SDL_TranslateEvent "AG_Driver *d" "const SDL_Event *ev" "AG_DriverEvent *dev" .Pp .Ft void .Fn AG_WindowProcessQueued "void" .Pp .nr nS 0 Low-level driver events are represented by the .Ft AG_DriverEvent structure, which provides the public members .Va type and .Va win . The .Va win member is a pointer to the corresponding .Xr AG_Window 3 (for single-window drivers, .Va win is always NULL). The .Va type field is an enum that can take on the values: .Pp .Bl -tag -compact -width "AG_DRIVER_MOUSE_BUTTON_DOWN " .It AG_DRIVER_MOUSE_MOTION Cursor has moved to .Va motion.{x,y} . .It AG_DRIVER_MOUSE_BUTTON_DOWN Mouse button .Va button.which has been pressed at coordinates .Va button.{x,y} . .It AG_DRIVER_MOUSE_BUTTON_UP Mouse button has been released. .It AG_DRIVER_MOUSE_ENTER Cursor has entered the window area. .It AG_DRIVER_MOUSE_LEAVE Cursor has left the window area. .It AG_DRIVER_FOCUS_IN Application focus has been gained. .It AG_DRIVER_FOCUS_OUT Application focus has been lost. .It AG_DRIVER_KEY_DOWN A key with keysym .Va key.ks has been pressed. See: .Xr AG_KeySym 3 . .Va key.ucs is the matching Unicode character (if any). .It AG_DRIVER_KEY_UP A key has been released. .It AG_DRIVER_EXPOSE The WM requests the window to be redrawn. .It AG_DRIVER_VIDEORESIZE The video display has been resized to .Va videoresize.w x .Va videoresize.h . .It AG_DRIVER_CLOSE The user is closing the window. The default action is to post a .Sq window-close event to the corresponding Agar window. .It AG_DRIVER_MOVED The window has been moved to desktop coordinates .Va moved.x and .Va moved.y . .It AG_DRIVER_MINIMIZED The window has been minimized. .It AG_DRIVER_MAXIMIZED The window has been maximized. .It AG_DRIVER_RESTORED Window has been restored following a previous minimize or maximize operation. .It AG_DRIVER_SHOWN The window is now visible to the user. .It AG_DRIVER_HIDDEN The window is now hidden from view. .It AG_DRIVER_JOY_DEVICE_ADDED Joystick device has been attached. .It AG_DRIVER_JOY_DEVICE_REMOVED Joystick device has been detached. .It AG_DRIVER_JOY_AXIS_MOTION Joystick axis has moved (continuous). .It AG_DRIVER_JOY_HAT_MOTION Joystick hat has moved (discrete). .It AG_DRIVER_JOY_BALL_MOTION Joystick ball has moved (relative). .It AG_DRIVER_JOY_BUTTON_DOWN Joystick button has been pressed. .It AG_DRIVER_JOY_BUTTON_UP Joystick button has been released. .El .Pp The .Fn AG_PendingEvents function returns 1 if there are events waiting to be processed, or 0 if the event queue is empty. .Pp .Fn AG_GetNextEvent retrieves and removes the next event on the queue, initializing the structure pointed by .Fa dev with its contents. .Fn AG_GetNextEvent returns 1 if the event has been successfully retrieved into .Fa dev . The function returns 0 if the event was dequeued (and no further processing is required), or -1 if an error has occurred. .Pp .Fn AG_ProcessEvent processes the event pointed to by .Fa dev in the default manner. The call returns 1 if the event was successfully, 0 if Agar has ignored the event entirely, or -1 if an error has occurred. .Pp The .Fn AG_SDL_TranslateEvent function translates a .Xr SDL_Event 3 structure to an Agar .Fn AG_DriverEvent . This function is only available if Agar was compiled with SDL support. Agar supports more than one driver instance per application. The .Fa d argument of .Fn AG_PendingEvents , .Fn AG_GetNextEvent , .Fn AG_ProcessEvent and .Fn AG_SDL_TranslateEvent can be set to NULL, in which case the default driver instance will be used. .Sh EXAMPLES .\" MANLINK(AG_CustomEventLoop) The following code fragment implements a basic event loop. It retrieves pending events, examines them, and forwards them to Agar for processing: .Bd -literal -offset indent .\" SYNTAX(c) AG_DriverEvent ev; while (AG_PendingEvents(NULL) > 0) { if (AG_GetNextEvent(NULL, &ev)) { switch (ev.type) { case AG_DRIVER_MOUSE_BUTTON_DOWN: printf("Click at %d,%d\\n", dev.button.x, dev.button.y); break; case AG_DRIVER_KEY_DOWN: printf("Key pressed: %d\\n", (int)dev.key.ks); break; default: break; } if (AG_ProcessEvent(NULL, &ev) == -1) break; } } .Ed .Sh SEE ALSO .Xr AG_DriverSw 3 , .Xr AG_DriverMw 3 , .Xr AG_GL 3 , .Xr AG_InitGraphics 3 , .Xr AG_Intro 3 , .Xr AG_Widget 3 , .Xr AG_Window 3 .Sh HISTORY The .Nm interface first appeared in Agar 1.4.0. Agar 1.6.0 added the driver operations .Fn putPixel64 , .Fn putPixelRGB16 , .Fn drawTriangle , .Fn drawPolygon , .Fn drawPolygonSti32 , .Fn drawLineW , .Fn drawLineW_Sti16 , .Fn getClipboardText and .Fn setClipboardText . Joystick and touch events appeared in Agar 1.7.0. .Fn setMouseAutoCapture appeared in Agar 1.7.0.