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 provides two models for handling user input:
- Event callbacks — functions you register that are called once per individual key press or mouse click.
- Polled state — functions you call yourself (typically inside the per-frame callback) to read which keys or mouse buttons are currently held down.
Use callbacks for one-shot reactions (submit a form, fire a weapon) and polling for continuous movement or held-button logic.
Keyboard Callback
void GEventAttachKey(void (*Key)(int key));
Registers a function that is called once each time a key-press event is received. The key argument is the ASCII character code for printable keys, or one of the LWXGL key constants for special keys:
| Constant | Value | Key |
|---|
LWXGL_KEY_LEFT | 170 | Left arrow |
LWXGL_KEY_RIGHT | 171 | Right arrow |
LWXGL_KEY_UP | 172 | Up arrow |
LWXGL_KEY_DOWN | 173 | Down arrow |
LWXGL_KEY_FN + 1 | 151 | F1 |
LWXGL_KEY_FN + 2 | 152 | F2 |
| … | … | … |
LWXGL_KEY_FN + 12 | 162 | F12 |
LWXGL_KEY_FN (150) is the base offset; Fn = LWXGL_KEY_FN + n.
The callback is not invoked when:
- A modal dialog is currently open (
GQueryModalOpen() returns 1).
- The cursor is hovering over a focused input field or console widget — those widgets capture the keystroke directly.
void on_key(int key) {
if (key == LWXGL_KEY_LEFT) printf("Left arrow\n");
if (key == LWXGL_KEY_RIGHT) printf("Right arrow\n");
if (key == 'q' || key == 'Q') GDeleteWindow();
// F1–F12
if (key >= LWXGL_KEY_FN + 1 && key <= LWXGL_KEY_FN + 12) {
printf("F%d pressed\n", key - LWXGL_KEY_FN);
}
}
// Register before starting the loop
GEventAttachKey(on_key);
Mouse-Click Callback
void GEventAttachClick(void (*Click)(int x, int y, int btn));
Registers a function called on every button release event. x and y are the cursor coordinates at the time of release. btn is the X11 button number:
btn | Button |
|---|
| 1 | Left |
| 2 | Middle |
| 3 | Right |
| 4 | Scroll up |
| 5 | Scroll down |
The callback is not invoked when:
- The release falls inside a button or checkbox widget (those widgets handle the click themselves).
- A modal dialog is currently open.
void on_click(int x, int y, int btn) {
if (btn == 1) {
printf("Left click at (%d, %d)\n", x, y);
} else if (btn == 3) {
printf("Right click at (%d, %d)\n", x, y);
}
}
GEventAttachClick(on_click);
Window-Close Callback
void GEventAttachDelete(int (*on_exit)());
Registers a function called when the user clicks the window’s close button (the X button in the title bar). Return 1 to allow the window to close, or 0 to cancel the close and keep the window open. If no callback is attached, clicking the close button always sets closing = 1 and the loop exits.
int on_close(void) {
// Spawn a confirmation modal before allowing close
GSpawnModal(1, "Quit the application?\nUnsaved changes will be lost.", NULL);
return 0; // cancel the close for now; modal handles it
}
GEventAttachDelete(on_close);
A simpler example that always allows closing:
int on_close(void) {
printf("Goodbye!\n");
return 1; // allow close
}
Polled Keyboard State
unsigned char* GQueryKeyboard(void);
int GQueryKeyDown(int ch);
GQueryKeyboard() returns a pointer to an internal unsigned char[8] array containing the character codes of up to eight currently held keys (0 = empty slot). GQueryKeyDown(ch) scans that array and returns 1 if ch is currently held, 0 otherwise.
Use these inside the per-frame callback passed to GSimpleWindowLoop to implement smooth continuous movement.
void on_frame(int tick) {
if (GQueryKeyDown(LWXGL_KEY_LEFT)) player_x -= 2;
if (GQueryKeyDown(LWXGL_KEY_RIGHT)) player_x += 2;
if (GQueryKeyDown(LWXGL_KEY_UP)) player_y -= 2;
if (GQueryKeyDown(LWXGL_KEY_DOWN)) player_y += 2;
// You can also iterate the full array directly:
unsigned char* keys = GQueryKeyboard();
for (int i = 0; i < 8; i++) {
if (keys[i] != 0)
printf("Held key: %d\n", keys[i]);
}
}
Polled Mouse State
void GQueryMouse(int* x, int* y, int* btn);
Fills in the current cursor position and the currently pressed mouse button. x and y are set to -1 when the cursor is outside the window. btn is the X11 button number of the button currently held (1/2/3), or 0 if no button is pressed.
void on_frame(int tick) {
int mx, my, mbtn;
GQueryMouse(&mx, &my, &mbtn);
if (mx == -1) {
// cursor is outside the window
return;
}
if (mbtn == 1) {
// left button is held — paint a pixel on the canvas
unsigned char* pixels = GGetImageData(0);
if (mx < 200 && my < 150)
pixels[my * 200 + mx] = 15; // white
GUpdateImage(0);
}
}
Combine both models for the best experience: use callbacks (GEventAttachKey, GEventAttachClick) to react to discrete events such as opening menus or confirming actions, and use polling (GQueryKeyDown, GQueryMouse) inside your per-frame callback for anything that needs to respond every frame, like moving a character or drawing with the mouse.