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.

This guide walks through creating a minimal LWXGL application with a window, a text label, a button, and a frame loop. By the end you will have a working program that opens a 640×480 window, greets the user, and responds to a button click — all in a single C source file.
1

Include the header

libLWXGL.h is the only LWXGL header you need. It exposes the full public API and is compatible with both C and C++ translation units.
hello.c
#include <libLWXGL.h>
#include <stdio.h>
2

Define a button callback and create the window

Declare any element callbacks before main, then call GCreateWindow to open the X11 window. The function takes a width, height, title string, and a background color as a palette index.
hello.c
void on_click(void) {
    printf("Button clicked!\n");
}

int main(void) {
    // Create a 640x480 window with title "Hello LWXGL"
    // Background color is palette index 0 (Black)
    int result = GCreateWindow(640, 480, "Hello LWXGL", 0);
    if (result != 0) {
        fprintf(stderr, "GCreateWindow failed: %d\n", result);
        return 1;
    }
GCreateWindow return codes:
Return valueMeaning
0Success
1Could not open X display ($DISPLAY not set or X server unavailable)
2Could not load the built-in 9x15 bitmap font
3A window is already open
3

Add UI elements

Elements are created by integer ID. IDs are chosen by your code and used later to read values, reposition, hide, or delete the element. Here we create a text label (ID 0) and a button (ID 1).
hello.c
    // Text label at (20, 30) in palette color 15 (White)
    GCreateText(0, 20, 30, 15, "Hello, LWXGL!");

    // Button at (20, 60), 120x30 pixels
    // Colors encoded as packed nibbles: high nibble=border color, low nibble=fill color
    // 0x70 = border:Light Gray(7), fill:Black(0) unpressed
    // 0x72 = border:Light Gray(7), fill:Dark Gray(2) on hover
    // 0x07 = inverted (border:Black, fill:Light Gray) on press
    GCreateButton(1, 20, 60, 120, 30, 0x70, 0x72, 0x07, "Click Me", on_click);
The three color arguments to GCreateButton (u, hvr, p) each encode two palette indices in a single byte using packed nibbles: the high nibble (bits 7–4) is the border/foreground color and the low nibble (bits 3–0) is the fill/background color. This applies to all three button states — unpressed, hovered, and pressed.
4

Enter the frame loop

GSimpleWindowLoop drives the application. It blocks the calling thread, running event handling and rendering every frame at the requested rate, and optionally invoking a per-frame callback.
hello.c
    // Run at 60 FPS; on_every is called each frame (tick, delta_time)
    GSimpleWindowLoop(60, NULL);

    // Clean up X11 resources
    GTerminateWindow();
    return 0;
}
GSimpleWindowLoop blocks until the window is closed — either by the user clicking the window manager’s close button, by pressing Ctrl+Escape, or by your code calling GDeleteWindow(). Passing NULL as the second argument is valid when you have no per-frame logic; the loop still handles input and redraws every frame.GTerminateWindow frees all elements, releases palette colors, destroys the back-buffer pixmap, and closes the X11 connection. Always call it before your program exits.
5

Compile and run

gcc hello.c -lLWXGL -lX11 -o hello
./hello
A 640×480 black window titled Hello LWXGL should appear with a white label and a clickable button. Each click prints Button clicked! to the terminal.

Adding a per-frame callback

When you need to update state every frame — animate a canvas, poll the keyboard, update a timer — pass a callback as the second argument to GSimpleWindowLoop:
void on_every(int tick, float delta_time) {
    // tick: frame count since loop start (increments by 1 each frame)
    // delta_time: seconds elapsed since the previous frame
}

// Pass to GSimpleWindowLoop:
GSimpleWindowLoop(60, on_every);
delta_time reflects actual elapsed wall-clock time, so it is slightly larger than the nominal frame duration (e.g. ~0.01667 at 60 FPS) whenever a frame runs a little late. Use it to keep motion and animations frame-rate independent.
LWXGL provides many more element types beyond text and buttons, including single-line input fields, checkboxes, scrollable consoles, and writable image canvases with primitive drawing support. See the UI Elements guide for a full walkthrough of each element type.
Two built-in keyboard shortcuts are always active inside GSimpleWindowLoop:
  • F12 — toggles a debug overlay showing the current FPS and a rolling average of per-frame work time.
  • Ctrl+Escape — force-closes the window immediately, equivalent to calling GDeleteWindow() from code.

Build docs developers (and LLMs) love