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.

Every LWXGL application follows the same fundamental lifecycle: create a window, populate it with elements, drive a render loop, and tear everything down cleanly on exit. Understanding this sequence is the foundation for building any LWXGL application.

Creating a window

int GCreateWindow(int w, int h, const char* name, int bgcol);
GCreateWindow opens a connection to the X server via $DISPLAY, allocates the 16-color palette, creates a backing pixmap for double-buffered rendering, and maps the window on screen. The bgcol argument is a palette index (0–15) that sets the background fill color drawn each frame before any elements are rendered. The function returns an integer status code:
Return valueMeaning
0Success
1$DISPLAY not set or XOpenDisplay failed
2The 9x15 bitmap font could not be loaded
3A window is already open
By default the window is fixed size: LWXGL sets PMinSize and PMaxSize hints to the same dimensions, preventing the window manager from resizing it. See Resizable windows below if you need a resizable window.

The render loop

LWXGL offers two approaches to driving the render loop.

High-level: GSimpleWindowLoop

void GSimpleWindowLoop(int target_fps, void (*on_every)(int tick, float delta_time));
GSimpleWindowLoop is a fully managed, blocking loop. Each iteration it:
  1. Calls GHandleWindowEvents() to process any pending X11 events.
  2. Calls GRenderWindow() to paint the current frame to the window.
  3. Calls your on_every callback with the current tick counter and the elapsed time in seconds since the last frame.
  4. Sleeps with microsecond precision to maintain the requested frame rate, yielding the thread when 2 ms or less remains.
Pass NULL as on_every if you have no per-frame work outside of event callbacks. The loop exits when GWindowShouldClose() returns non-zero.

Manual loop

For more control, drive the loop yourself with the three core functions:
while (!GWindowShouldClose()) {
    GHandleWindowEvents();
    GRenderWindow();
    // your per-frame logic
}
GHandleWindowEvents drains the X11 event queue, dispatching keyboard, mouse, and window-manager messages. GRenderWindow fills the backing pixmap with the background color, renders all visible elements for the active screen, and blits the pixmap to the window.

Window title and background

Update the title bar text at any time with:
void GSetWindowTitle(const char* title);
Change the background palette index with:
void GSetWindowColor(int palette_index);
The new background color takes effect on the next GRenderWindow call.

Resizable windows

void GEnableResizing(void (*Resize)(int w, int h));
GEnableResizing clears the fixed-size WM hints, allowing the user to resize the window. Whenever a ConfigureNotify event reports a new size, LWXGL recreates the backing pixmap at the new dimensions and calls your Resize callback with the new width and height. Use the callback to reposition or rescale elements to fit the new window dimensions.

Closing the window

GDeleteWindow() sets the internal closing flag, which causes GWindowShouldClose() to return 1 and the loop to exit on the next iteration. If a delete handler has been registered with GEventAttachDelete, it is called first; returning 0 from that handler blocks the close. After the loop exits, call GTerminateWindow() to release all resources:
while (!GWindowShouldClose()) {
    GHandleWindowEvents();
    GRenderWindow();
}
GTerminateWindow();
GTerminateWindow iterates over every allocated element and calls GDeleteElement on it, frees all allocated TGA images, releases the X11 font, GC, backing pixmap, palette colors, and finally destroys the window and closes the display connection.
GTerminateWindow must be called exactly once, after the loop has exited. Calling it a second time is undefined behavior — the display pointer and window handle will already be invalid, and the function will likely crash or corrupt memory.

Debug overlay

Press F12 at any time in a running LWXGL application to toggle a debug overlay in the top-left corner. It displays:
  • FT — average frame work time in microseconds (rolling 60-frame window).
  • FPS — current frames per second.
The overlay is only available when using GSimpleWindowLoop (which activates the metrics collection). It does not appear in manual loops unless you enable debug_metrics yourself. Press Ctrl+Escape to force-close the window immediately, bypassing any registered delete handler.

Build docs developers (and LLMs) love