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 a complete LWXGL program from scratch. By the end you will have a 640×480 window containing a text label and a clickable button, running a capped frame loop at 60 FPS. No prior Xlib knowledge is required — LWXGL handles the display connection, colormap, double-buffering, and event dispatch internally.

Complete example

#include <libLWXGL.h>
#include <stdio.h>

/* Click handler — called when the button is clicked */
void on_click(void) {
    printf("Button clicked!\n");
}

/* Per-frame callback — called every frame with tick index and delta time */
void on_frame(int tick, float dt) {
    /* game logic, animations, etc. */
}

int main(void) {
    /* 1. Open a 640x480 window */
    int rc = CreateWindow(640, 480, "Hello LWXGL", CLR_BLACK, FLAG_NONE);
    if (rc != 0) {
        fprintf(stderr, "CreateWindow failed: %d\n", rc);
        return 1;
    }

    /* 2. Place a text label at (20, 20) */
    CreateText(0, 20, 20, "Hello, world!", CLR_WHITE);

    /* 3. Place a button at (20, 60), 120x30 pixels */
    CreateButton(
        1,          /* id */
        20, 60,     /* x, y */
        120, 30,    /* width, height */
        CLR_GRAY  | (CLR_LGRAY << 4),  /* normal:  fill=GRAY,  border=LGRAY */
        CLR_LGRAY | (CLR_WHITE << 4),  /* hover:   fill=LGRAY, border=WHITE */
        CLR_BLUE  | (CLR_LBLUE << 4),  /* pressed: fill=BLUE,  border=LBLUE */
        "Click me",
        on_click
    );

    /* 4. Attach a global click handler (optional) */
    EventAttachClick(NULL);   /* pass a void(*)(int x, int y, int btn) to inspect raw clicks */

    /* 5. Run the event/render loop at 60 FPS */
    MainWindowLoop(60, on_frame);

    /* 6. Clean up */
    TerminateWindow();
    return 0;
}
Compile and run:
gcc -o hello hello.c -lLWXGL
./hello

Walkthrough

1

Create the window

int rc = CreateWindow(640, 480, "Hello LWXGL", CLR_BLACK, FLAG_NONE);
CreateWindow opens a connection to the X server, allocates the 16-color palette, creates the window, loads the system font, and sets up the off-screen back-buffer. It returns an integer status code:
CodeMeaning
0Success
1Cannot connect to X display ($DISPLAY not set or X server unreachable)
2Font 9x15 could not be loaded
3A window is already open (only one window per process is supported)
127 + NXAllocColor failed while allocating palette entry N (display may not support the required colors)
The fourth argument is the background color index (CLR_BLACK = 0x0). The fifth argument is a bitfield of window flags.
Three flags are available for the f argument:
  • FLAG_NONE (0) — fixed-size window, no canvas. The default for most applications.
  • FLAG_CANVAS (1 << 1) — automatically creates a full-window drawable image at element id 0, enabling pixel-level drawing with PrimitiveRect, PrimitiveCircle, PrimitiveLine, and related functions.
  • FLAG_RESIZE (1 << 2) — allows the user to resize the window. Attach a handler with EventAttachResize to respond to size changes.
Flags may be combined: FLAG_CANVAS | FLAG_RESIZE.
2

Add a text label

CreateText(0, 20, 20, "Hello, world!", CLR_WHITE);
CreateText(id, x, y, text, color) places static text at pixel coordinates (x, y) using the global font. The first argument is the element id — an integer you choose. You can later move, hide, or delete this element using that id.CLR_WHITE (0xF) is one of the 16 palette constants defined in libLWXGL.h.
3

Add a button

CreateButton(
    1,
    20, 60,
    120, 30,
    CLR_GRAY  | (CLR_LGRAY << 4),
    CLR_LGRAY | (CLR_WHITE << 4),
    CLR_BLUE  | (CLR_LBLUE << 4),
    "Click me",
    on_click
);
CreateButton(id, x, y, w, h, u, hvr, p, label, onclick) creates an interactive button. The three color arguments (u, hvr, p) each encode two palette indices in a single byte:
  • Low nibble (& 0x0F) — fill (background) color
  • High nibble (>> 4 & 0x0F) — border color
So CLR_GRAY | (CLR_LGRAY << 4) means: fill with CLR_GRAY (0x8), border with CLR_LGRAY (0x7), packed as 0x78.The three states are:
  • u — normal (unpressed, not hovered)
  • hvr — mouse hovering over the button
  • p — mouse button held down
The onclick function pointer is invoked when the button is released after a press. Pass NULL if you only want to style the button without a click action.
Use ElemSetVisible(id, 0) to hide a button without deleting it, and ElemSetVisible(id, 1) to show it again. Use DeleteElement(id) to destroy it permanently and free its resources.
4

Attach a global click handler (optional)

void my_click_handler(int x, int y, int btn) {
    printf("Mouse click at (%d, %d), button %d\n", x, y, btn);
}

EventAttachClick(my_click_handler);
EventAttachClick registers a callback that fires on every mouse button press anywhere in the window, regardless of which element was clicked. The callback receives the pointer coordinates and the button index (1 = left, 2 = middle, 3 = right). This is independent of individual button onclick handlers.Pass NULL to disable the global handler.
5

Run the main loop

MainWindowLoop(60, on_frame);
MainWindowLoop(target_fps, on_every) blocks until the window is closed. Each frame it:
  1. Processes all pending X events (mouse, keyboard, resize, close)
  2. Calls on_every(tick, delta_time) — your per-frame callback — where tick is the frame counter (starts at 0) and delta_time is seconds since the last frame as a float
  3. Renders all visible elements to the back-buffer and presents it
  4. Runs any queued tasks whose scheduled time has elapsed
  5. Sleeps for the remainder of the frame budget
Pass NULL as the second argument if you do not need a per-frame callback.
The frame budget is 1 000 000 / target_fps microseconds. LWXGL uses std::chrono::steady_clock internally — the target FPS is a cap, not a guarantee. Use the delta_time argument to write frame-rate-independent logic.
6

Clean up

TerminateWindow();
TerminateWindow frees all element resources, releases the palette colors, destroys the window, and closes the X display connection. Always call it after MainWindowLoop returns.

Full color palette reference

All 16 palette indices are available as named constants:
ConstantIndexColor
CLR_BLACK0x0Black
CLR_BLUE0x1Dark blue
CLR_GREEN0x2Dark green
CLR_CYAN0x3Dark cyan
CLR_RED0x4Dark red
CLR_MAGENTA0x5Dark magenta
CLR_ORANGE0x6Orange
CLR_LGRAY0x7Light gray
CLR_GRAY0x8Dark gray
CLR_LBLUE0x9Light blue
CLR_LGREEN0xALight green
CLR_LCYAN0xBLight cyan
CLR_LRED0xCLight red
CLR_LMAGENTA0xDLight magenta
CLR_YELLOW0xEYellow
CLR_WHITE0xFWhite
Use CLR_NONE (-1) anywhere a color is optional and should be omitted (e.g., a transparent background).
Element ids must be unique within your application. Calling CreateText and CreateButton with the same id will overwrite the first element’s slot. Choose a consistent numbering scheme (e.g., an enum) to avoid collisions.

Build docs developers (and LLMs) love