Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DREssedAlarm184/LWXGL/llms.txt

Use this file to discover all available pages before exploring further.

LWXGL processes X11 events inside GHandleWindowEvents(), which is called automatically by GSimpleWindowLoop or manually in a custom render loop. The function drains the full X11 event queue each call and dispatches each event to built-in element handlers first, then to any user-provided callbacks registered with the GEventAttach* functions.

Event dispatch order

LWXGL applies a fixed priority chain for each event type:
  1. Keyboard events are delivered to any focused input field or console element under the cursor before the user Key callback is invoked. If no eligible element consumes the keypress, the user callback fires.
  2. Mouse click events are tested against every button and checkbox element (by hit test, in ID order) before the user Click callback is reached. The first matching element consumes the event and the Click callback is not called.
  3. Modal dialogs intercept all mouse button releases until dismissed. Key and click callbacks are not called while a modal is active.

User-provided callbacks

Register application callbacks with the corresponding Attach function. All registrations are global — only one callback of each type may be active at a time.
CallbackAttach functionSignature
Key pressGEventAttachKeyvoid fn(int key)
Mouse clickGEventAttachClickvoid fn(int x, int y, int btn)
Window closeGEventAttachDeleteint fn(void) — return 1 to allow close, 0 to block
ResizeGEnableResizingvoid fn(int w, int h)

Key values

The key argument passed to the Key callback is the ASCII character code for printable keys (space through tilde), or 8 for Backspace. For non-printable keys, LWXGL maps X11 keysyms to its own constants:
#define LWXGL_KEY_LEFT   170
#define LWXGL_KEY_RIGHT  171
#define LWXGL_KEY_UP     172
#define LWXGL_KEY_DOWN   173
#define LWXGL_KEY_FN     150  // F1 = 151, F2 = 152, ... F12 = 162
Function keys F1 through F12 produce values LWXGL_KEY_FN + 1 through LWXGL_KEY_FN + 12 (i.e., 151–162).

Mouse state

Query the current mouse position and button state at any point with:
void GQueryMouse(int* x, int* y, int* btn);
x and y are set to the cursor’s pixel position relative to the window’s top-left corner. btn is the X11 button number of the currently held button: 1 = left, 2 = middle, 3 = right. btn is 0 when no button is pressed. Both x and y are -1 when the cursor is outside the window.

Keyboard state

For polling-based input, two functions expose the set of currently held keys:
unsigned char* GQueryKeyboard();
int GQueryKeyDown(int ch);
GQueryKeyboard returns a pointer to an internal 8-byte array. Each slot contains the character code of a currently pressed key, or 0 if unused, supporting up to 8 simultaneous keys. GQueryKeyDown(ch) is a convenience wrapper that returns 1 if the given character code is currently held, 0 otherwise.

Complete event setup example

void on_key(int key) {
    if (key == LWXGL_KEY_LEFT)  move_player(-1, 0);
    if (key == LWXGL_KEY_RIGHT) move_player(1, 0);
    if (key == 'q') GDeleteWindow();
}

void on_click(int x, int y, int btn) {
    if (btn == 1) printf("Left click at (%d, %d)\n", x, y);
}

int on_exit(void) {
    // Return 0 to prevent closing, 1 to allow it
    return 1;
}

GEventAttachKey(on_key);
GEventAttachClick(on_click);
GEventAttachDelete(on_exit);
The Key callback fires once per physical key press. LWXGL enables XkbSetDetectableAutoRepeat at startup, which suppresses X11’s built-in key repeat events at the Xkb level — you will receive exactly one key-down event when a key is pressed and one key-up event when it is released, with no spurious repeat events in between.
For game-style input where you need to respond to a key being held across multiple frames, prefer polling with GQueryKeyDown(ch) or iterating GQueryKeyboard() inside your per-frame callback rather than accumulating state in the Key event callback. Polling gives you precise per-frame control without the complexity of manual hold-state tracking.

Build docs developers (and LLMs) love