02_basic_window

Example 02: Basic Window

An introduction to libui and creating graphical apps.


This example demonstrates how to create an empty window that stays active on the screen until the user explicitly closes it by clicking the 'X' button.

Concepts Introduced

  • Including libui.h and the event structure.
  • Creating a ui_window_t handle.
  • Creating an infinite event loop using ui_get_event().
  • Yielding CPU time via sleep(ms).
  • Declaring app metadata via source annotations.

The Code (src/userland/gui/basic_window.c)

// BOREDOS_APP_DESC: Basic Window — a minimal graphical window demo.
#include <stdlib.h>
#include <libui.h>
#include <syscall.h>

int main(void) {
    // 1. Ask the Window Manager to create a new window
    // Arguments are: Title, X Position, Y Position, Width, Height
    ui_window_t wid = ui_window_create("My First GUI", 100, 100, 400, 300);
    
    if (wid < 0) {
        printf("Failed to create the window!\n");
        return 1;
    }

    // 2. Define our event object
    gui_event_t event;

    // 3. Enter the main event loop
    while (1) {
        // ui_get_event is non-blocking. It returns true if an event was waiting.
        if (ui_get_event(wid, &event)) {
            
            // Check what type of event occurred
            if (event.type == GUI_EVENT_CLOSE) {
                // The user clicked the 'X' button in the titlebar!
                printf("Window closed cleanly by user.\n");
                break; // Break the infinite loop
            }
        }
        
        // 4. CRITICAL: Throttle our loop to save CPU
        // If we don't do this, the while(1) loop will consume 100% of the CPU
        // and starve the rest of the OS! A 10ms sleep allows for ~100 FPS
        // event polling while letting the CPU actually idle.
        sys_system(SYSTEM_CMD_SLEEP, 10, 0, 0, 0);
    }

    // Returning from main will automatically destroy the window and exit the process.
    return 0;
}

🛠️ How it Works

  1. Window Handle (wid): ui_window_create sends a request to the kernel. The kernel allocates the memory for the window and returns a numerical ID (the handle) that we use for all future interactions with that specific window.
  2. The Event Loop: Graphical programs run forever until closed. The while (1) loop serves this purpose.
  3. Polling: ui_get_event asks the kernel, "Hey, did the user click my window or press a key since the last time I asked?". It is non-blocking, so it immediately returns false if nothing happened.
  4. CPU Throttling: Since we are constantly polling in a loop, we call sys_system(SYSTEM_CMD_SLEEP, 10, ...) at the end of the loop frame. This tells the OS scheduler, "I'm done checking for events, don't run me again for at least 10ms." This allows the CPU to actually enter a low-power state and makes the system much smoother.
  5. BOREDOS_APP_DESC / BOREDOS_APP_ICONS: Embedded into the .elf by the build system as a BoredOS NOTE section. The Window Manager reads this at runtime to render the app's icon on the Desktop and in the File Explorer. See elf_metadata.md for full details.

Running It

Launch the Terminal and type basic_window. You'll see an empty window appear that you can move around the screen!