Every LWXGL application follows a strict three-phase lifecycle: create a window withDocumentation 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.
CreateWindow, drive it with MainWindowLoop, and clean up with TerminateWindow. Understanding what happens at each phase — especially how the window flags change behavior — is essential before writing any application code.
The Three Phases
Create
Call
CreateWindow to open a connection to the X display, allocate the 16-color palette, create the backing pixmap, load the font, and map the window to the screen. This is the only phase where the display and graphics context (GC) are initialized.Loop
Call
MainWindowLoop immediately after CreateWindow. The loop runs at the requested frame rate, dispatching X events, rendering each frame, and flushing the queued-task list. The loop exits when DeleteWindow is called (or when the WM close button is clicked).CreateWindow
w × h pixels with title name and background fill color bgcolor (a palette index, e.g. CLR_BLACK). The flags bitmask controls rendering behavior (see Window Flags below).
Return Codes
| Code | Meaning |
|---|---|
0 | Success |
1 | XOpenDisplay failed — no $DISPLAY or X server unavailable |
2 | Font 9x15 could not be loaded |
3 | A window is already open (call TerminateWindow first) |
127 + N | XAllocColor failed while allocating palette entry N |
Window Flags
Flags are passed as the fifth argument toCreateWindow and can be combined with bitwise OR.
| Constant | Value | Effect |
|---|---|---|
FLAG_NONE | 0 | Default double-buffered rendering — LWXGL manages all drawing |
FLAG_BYPASS | 1 << 0 | Skips all LWXGL drawing; on_every is called directly and is responsible for all rendering |
FLAG_CANVAS | 1 << 1 | Creates a full-window ImageElement at element ID 0 for pixel-level drawing |
FLAG_RESIZE | 1 << 2 | Allows window resizing; without it, WM size hints lock min and max to w × h |
FLAG_NONE — Default Double-Buffered Mode
When no flag is set, LWXGL clears the back-buffer pixmap (bb) each frame, draws all visible elements in order, runs the on_every callback, and then blits the result to the window with XCopyArea. Your code never draws directly to the window.
FLAG_BYPASS — Custom Xlib Drawing
FLAG_BYPASS hands full rendering control to the application. LWXGL calls on_every(tick, dt) and then calls XSync, but performs no element rendering, no background clear, and no XCopyArea. Use this when you want to drive Xlib directly or integrate a third-party renderer.
FLAG_CANVAS — Pixel-Level Drawing Surface
When FLAG_CANVAS is set, CreateWindow calls CreateImage(0, 0, 0, 0, 0) internally, registering a full-window ImageElement at ID 0. You can then use GetImageData(0) to obtain a pointer to the raw pixel buffer — a flat array of unsigned char where each byte is a palette index (0–15) — and UpdateImage(0) to push your changes to the screen.
ID
0 is reserved by the canvas image when FLAG_CANVAS is active. Do not create another element at ID 0 while this flag is in use.FLAG_RESIZE — Resizable Window
By default, LWXGL sets both PMinSize and PMaxSize WM hints to the dimensions passed to CreateWindow, preventing resizing. Setting FLAG_RESIZE omits those hints, allowing the user to resize the window. Attach EventAttachResize to respond to resize events.
MainWindowLoop
target_fps frames per second. Frame timing is implemented with std::chrono::steady_clock; each iteration measures the elapsed time since the last frame and skips rendering if insufficient time has passed (sleeping when there is more than 2 ms to spare, yielding otherwise).
The on_every callback receives:
tick— a monotonically increasing frame counter starting at0dt— the delta time in seconds since the previous frame (actual elapsed, not the target)
- Check
std::chronoelapsed time; skip if less than1 / target_fpsseconds - Call
_handle_window_events()to process all pending X events - Call
_render_window(on_every, tick, dt)to draw the frame (see Rendering Model) - Flush the task queue — execute any
NewQueuedTaskcallbacks whosetarget_time ≤ elapsed_time - Update the rolling 60-frame work-time average for the debug overlay
- Advance
tickand recordlast_time
TerminateWindow
- All elements in the
elementsvector (type-specific data +Elementstruct) - All allocated TGA image entries from
allocated_TGAs - The active modal state message string (if any)
- X resources: font, GC, back-buffer pixmap, 16 palette colors, window, display
MainWindowLoop returns.
DeleteWindow
closing flag. If EventAttachDelete has been called with a callback, that callback’s return value controls whether closing proceeds: returning 1 allows it, returning 0 cancels it.
DeleteWindow internally, so the same callback governs both programmatic and user-initiated closes.
Window Utility Functions
SetWindowTitle
XStoreName.
SetWindowColor
color is a palette index (CLR_* constant or 0–15).
ChangeCursor
68 for the default arrow, which is set automatically by CreateWindow). Passing 255 creates an invisible cursor using a blank 1×1 XCreateBitmapFromData pixmap rather than a glyph from the cursor font — the cursor becomes completely invisible.
SetGlobalBold
9x15) and bold (9x15bold). Pass 1 to enable bold, 0 to return to normal. Returns 1 on success; returns 0 if the new font could not be loaded (the previous font remains active in that case). This affects all subsequent text rendering, including CreateText, CreateCopiedText, ImmediateText, and button labels.
ReserveScroll
height is the total document height in pixels (must be greater than the window height to allow scrolling). scrollbar_color is a packed color int (fill | (border << 4)); pass CLR_NONE (-1) to suppress the scrollbar. Scroll is an optional callback invoked whenever the scroll position changes.
QueryScroll() at any time to read the current scroll offset, and call ResolveAnchors() each frame to keep anchored elements pinned to the viewport.