DOCS: Refine and add documentation for libwidget.c

This commit is contained in:
boreddevnl 2026-04-03 11:52:06 +02:00
parent f402e5e4f0
commit 69847adee6
9 changed files with 141 additions and 24 deletions

View file

@ -27,6 +27,7 @@ Instructions for compiling the OS from source.
The SDK and toolchain guides for creating your own `.elf` userland binaries.
- [`SDK Reference`](appdev/sdk_reference.md): Explanation of the custom `libc` wrappers (`stdlib.h`, `string.h`) and system calls.
- [`UI API`](appdev/ui_api.md): Drawing on the screen, creating windows, and polling the event loop using `libui.h`.
- [`Widget API`](appdev/widget_api.md): High-level UI components like buttons, textboxes, and scrollbars using `libwidget.h`.
- [`Custom Apps`](appdev/custom_apps.md): A step-by-step tutorial on writing a new graphical C application, editing the Makefile, and bundling it into the ISO.
- [`Example Apps`](appdev/examples/README.md): A collection of sample C applications ranging from basic terminal output to advanced TCP networking.

View file

@ -10,7 +10,7 @@ This guide explains how to write a new "Hello World" application locally, compil
> [!TIP]
> **Looking for working code?** Check out the [Examples Directory](examples/README.md) for full source code demonstrating basic CLI, Windows, Animations, and TCP Networking.
## 📝 Step 1: Write the C Source
## Step 1: Write the C Source
Applications reside entirely in the `src/userland/` directory. Create a new file, for example, `src/userland/gui/hello.c`.
@ -52,7 +52,7 @@ int main(void) {
}
```
## ⚙️ Step 2: Edit the Makefile
## Step 2: Edit the Makefile
Now you need to tell the build system to compile `hello.c`. Fortunately, the `src/userland/Makefile` is designed to detect new C files largely automatically!
@ -64,7 +64,7 @@ Now you need to tell the build system to compile `hello.c`. Fortunately, the `sr
Since you placed the file in `gui/hello.c`, the wildcard logic will pick it up automatically.
3. The Makefile will generate `bin/hello.elf` during the build phase.
## 📦 Step 3: Bundle it into the OS
## Step 3: Bundle it into the OS
The main overarching `Makefile` (in the project root) takes binaries from `src/userland/bin/*.elf` and places them into the `iso_root/bin/` directory, while also adding them to `limine.conf` as loadable boot modules.
@ -77,7 +77,7 @@ The main overarching `Makefile` (in the project root) takes binaries from `src/u
make clean && make run
```
## 🚀 Step 4: Run it inside BoredOS
## Step 4: Run it inside BoredOS
1. When BoredOS boots, launch the **Terminal** application.
2. The OS automatically maps built applications to standard shell commands. Simply type your application's filename (without the `.elf` extension).

View file

@ -7,9 +7,11 @@
BoredOS provides a custom `libc` implementation necessary for writing userland applications (`.elf` binaries). By avoiding a full-blown standard library like `glibc`, the OS ensures a minimal executable footprint tailored strictly to the existing kernel features.
All headers are located in `src/userland/libc/`.
All headers are located in `src/userland/libc/` (standard functions) and `src/wm/` (UI and widgets).
- `libui.h`: Core window and drawing API.
- `libwidget.h`: High-level UI components.
## 📚 Standard Library (`stdlib.h` & `string.h`)
## Standard Library (`stdlib.h` & `string.h`)
The standard library wrappers provide memory management, string manipulation, and basic IO formatting without needing direct syscalls.
@ -45,7 +47,7 @@ The standard library wrappers provide memory management, string manipulation, an
---
## ⚙️ System Calls (`syscall.h`)
## System Calls (`syscall.h`)
For advanced operations, `syscall.h` provides direct wrappers into the kernel.
@ -108,7 +110,7 @@ BoredOS includes lwIP for hardware TCP/UDP networking.
---
## 📑 Core Data Structures
## Core Data Structures
### `os_info_t`
Contains detailed build and version information about the OS.

View file

@ -7,7 +7,7 @@
The UI library (`libui.h`) is the sole mechanism for Graphical Userland Applications to draw to the screen and receive input events in BoredOS. It wraps `SYS_GUI` kernel calls.
## 🪟 Window Management
## Window Management
A "Window" is a reserved drawing canvas managed by the compositor.
@ -21,7 +21,7 @@ A "Window" is a reserved drawing canvas managed by the compositor.
* `void ui_get_screen_size(uint64_t *out_w, uint64_t *out_h);`
Query the global screen resolution of the display.
## 🎨 Drawing Primitives
## Drawing Primitives
All drawing functions write to an off-screen buffer associated with the window. **You must call `ui_mark_dirty()` to instruct the compositor to push your changes to the physical screen.**
@ -38,7 +38,7 @@ All drawing functions write to an off-screen buffer associated with the window.
> Colors are defined as 32-bit unsigned integers in **ARGB** format: `0xAARRGGBB`.
> E.g., `0xFF000000` is opaque black, `0xFFFF0000` is opaque red.
## 🔤 Text Rendering
## Text Rendering
BoredOS provides multiple text rendering methodologies, including a default system font and scaled/bitmap alternatives.
@ -60,7 +60,7 @@ Used for calculating layout bounds before drawing:
* `uint32_t ui_get_string_width_scaled(const char *str, float scale);`
* `uint32_t ui_get_font_height_scaled(float scale);`
## 🔄 Event Handling
## Event Handling
Applications must continuously poll for events inside an infinite `$while(1)` loop.
@ -103,3 +103,9 @@ typedef struct {
*(Note: Coordinate arguments (`arg1`, `arg2`) for mouse events are typically relative to the top-left corner of the window's client area).*
---
> [!TIP]
> **Looking for Buttons, TextBoxes, or Scrollbars?**
> While `libui.h` provides the foundation for drawing, most applications should use the higher-level [**Widget API**](widget_api.md) (`libwidget.h`) for standard interactive components.
---

108
docs/appdev/widget_api.md Normal file
View file

@ -0,0 +1,108 @@
<div align="center">
<h1>Widget API (<code>libwidget.h</code>)</h1>
<p><em>High-level UI components for BoredOS applications.</em></p>
</div>
---
The Widget library (`libwidget.h`) provides a set of reusable UI components built on top of `libui.h`. It uses an abstract `widget_context_t` to decouple component logic from specific drawing implementations, making it easier to build complex graphical interfaces.
## Widget Context
To use any widget, you must first define a `widget_context_t`. This structure contains function pointers for basic drawing operations (rects, strings) and theme preferences.
```c
typedef struct {
void *user_data;
void (*draw_rect)(void *user_data, int x, int y, int w, int h, uint32_t color);
void (*draw_rounded_rect_filled)(void *user_data, int x, int y, int w, int h, int r, uint32_t color);
void (*draw_string)(void *user_data, int x, int y, const char *str, uint32_t color);
int (*measure_string_width)(void *user_data, const char *str);
void (*mark_dirty)(void *user_data, int x, int y, int w, int h);
bool use_light_theme;
} widget_context_t;
```
> [!TIP]
> Usually, `user_data` is set to your `ui_window_t` handle, and the functions are simple wrappers around `ui_draw_rect`, `ui_draw_string`, etc.
---
## Button (`widget_button_t`)
Standard interactive button with hover and click states.
* `void widget_button_init(widget_button_t *btn, int x, int y, int w, int h, const char *text);`
* `void widget_button_draw(widget_context_t *ctx, widget_button_t *btn);`
* `bool widget_button_handle_mouse(widget_button_t *btn, int mx, int my, bool mouse_down, bool mouse_clicked, void *user_data);`
### Usage Example:
```c
widget_button_t my_btn;
widget_button_init(&my_btn, 10, 10, 80, 25, "Click Me");
my_btn.on_click = my_callback_func;
// In your event loop:
widget_button_handle_mouse(&my_btn, ev.arg1, ev.arg2, is_down, is_clicked, my_data);
```
---
## Scrollbar (`widget_scrollbar_t`)
Vertical scrollbar supporting dragging and track-paging.
* `void widget_scrollbar_init(widget_scrollbar_t *sb, int x, int y, int w, int h);`
* `void widget_scrollbar_update(widget_scrollbar_t *sb, int content_height, int scroll_y);`
* `void widget_scrollbar_draw(widget_context_t *ctx, widget_scrollbar_t *sb);`
* `bool widget_scrollbar_handle_mouse(widget_scrollbar_t *sb, int mx, int my, bool mouse_down, void *user_data);`
> [!NOTE]
> The scrollbar automatically calculates the "thumb" size based on the ratio of `h` to `content_height`.
---
## TextBox (`widget_textbox_t`)
Editable text field with focus support and keyboard handling.
* `void widget_textbox_init(widget_textbox_t *tb, int x, int y, int w, int h, char *buffer, int max_len);`
* `void widget_textbox_draw(widget_context_t *ctx, widget_textbox_t *tb);`
* `bool widget_textbox_handle_mouse(widget_textbox_t *tb, int mx, int my, bool mouse_clicked, void *user_data);`
* `bool widget_textbox_handle_key(widget_textbox_t *tb, char c, void *user_data);`
---
## Dropdown (`widget_dropdown_t`)
Selection menu for picking one item from a list.
* `void widget_dropdown_init(widget_dropdown_t *dd, int x, int y, int w, int h, const char **items, int count);`
* `void widget_dropdown_draw(widget_context_t *ctx, widget_dropdown_t *dd);`
* `bool widget_dropdown_handle_mouse(widget_dropdown_t *dd, int mx, int my, bool mouse_clicked, void *user_data);`
---
## Checkbox / Radio (`widget_checkbox_t`)
Toggleable options with support for circular "Radio" style or square "Checkbox" style.
* `void widget_checkbox_init(widget_checkbox_t *cb, int x, int y, int w, int h, const char *text, bool is_radio);`
* `void widget_checkbox_draw(widget_context_t *ctx, widget_checkbox_t *cb);`
* `bool widget_checkbox_handle_mouse(widget_checkbox_t *cb, int mx, int my, bool mouse_clicked, void *user_data);`
---
## Event Integration
Widgets are designed to be polled within your `libui` event loop. Most handle-mouse functions return `true` if the event was "consumed" by the widget, allowing you to stop further processing for that event.
```c
if (ui_get_event(win, &ev)) {
bool handled = false;
handled |= widget_button_handle_mouse(&btn, ev.arg1, ev.arg2, is_down, is_clicked, NULL);
if (!handled) {
// Handle global window events...
}
}
```

View file

@ -9,7 +9,7 @@ BoredOS is a 64-bit hobbyist operating system designed for the x86_64 architectu
This document serves as an overview of the core architecture and the layout of the kernel source code.
## 📂 Source Code Layout (`src/`)
## Source Code Layout (`src/`)
The OS heavily relies on module separation. The `src/` directory is logically split into several domains:
@ -23,7 +23,7 @@ The OS heavily relies on module separation. The `src/` directory is logically sp
- **`wm/`**: The graphical subsystem. It handles drawing primitives, window structures, font rendering, and double-buffering.
- **`userland/`**: Out-of-kernel components. This includes the custom SDK/compiler environment (`libc/`) and user applications (`cli/`, `gui/`, `games/`).
## 🚀 Boot Process
## Boot Process
BoredOS uses **Limine** as its primary bootloader.
@ -42,7 +42,7 @@ BoredOS utilizes Symmetric Multi-Processing (SMP) to distribute workloads across
- **Scheduler**: A round-robin scheduler runs on each core. Processes are pinned to specific CPUs (CPU Affinity) to maintain cache locality. The BSP timer interrupt (`60Hz`) broadcasts a scheduling IPI to all core to ensure balanced execution.
- **Spinlocks**: Since multiple cores can access kernel structures (VFS, Process List) simultaneously, the kernel uses **interrupt-safe spinlocks** to prevent race conditions.
## 🛡️ Userland Transition
## Userland Transition
The OS supports privilege separation (Ring 0 vs. Ring 3). When an application is launched, the kernel:

View file

@ -7,7 +7,7 @@
BoredOS implements a rudimentary but functional filesystem layer designed to support reading system assets and user applications during runtime.
## 🗂️ Virtual File System (VFS)
## Virtual File System (VFS)
The Virtual File System acts as an abstraction layer across different underlying storage mechanisms (even if, currently, only one type is fully utilized). System calls targeting files (`SYS_FS`) route through the VFS rather than interacting with the disk directly.
@ -17,11 +17,11 @@ Key VFS functionalities include:
- **Path Parsing**: Resolving absolute and relative paths.
- **SMP Safety**: All VFS and underlying FAT32 operations are protected by a global **Spinlock**. This ensures that multiple cores can safely read from the filesystem simultaneously without corrupting internal file seek pointers or directory cache states.
## 💾 FAT32 Implementation
## FAT32 Implementation
The primary filesystem logic in `fat32.c` handles both in-memory RAM-based filesystem simulation and physical ATA block devices.
### 💿 Storage Support
### Storage Support
BoredOS supports two main types of storage for its FAT32 implementation:
@ -30,7 +30,7 @@ BoredOS supports two main types of storage for its FAT32 implementation:
- **GPT is NOT supported**: Currently, only **MBR (Master Boot Record)** partition tables or **raw (partitionless)** disks are supported.
- **Filesystem**: The partition must be formatted as **FAT32**.
### 🔍 Auto-detection
### Auto-detection
The `Disk Manager` automatically probes primary and secondary IDE channels during initialization. If a valid FAT32 partition is found (either directly at sector 0 or via an MBR partition table), the disk is assigned a drive letter (starting from `B:`) and becomes accessible to the VFS.

View file

@ -7,7 +7,7 @@
Memory management in BoredOS is split into physical and virtual layers, designed to support both kernel operations and userland isolation on the x86_64 architecture.
## 🧠 Physical Memory Management (PMM)
## Physical Memory Management (PMM)
The PMM is responsible for tracking which physical RAM frames (usually 4KB each) are free and which are in use.
@ -19,7 +19,7 @@ The PMM is responsible for tracking which physical RAM frames (usually 4KB each)
> [!NOTE]
> 4KB frame sizes strike a balance between allocation speed and minimal memory fragmentation, fitting directly with the page tables.
## 🗺️ Virtual Memory Management (VMM) and Paging
## Virtual Memory Management (VMM) and Paging
BoredOS uses 4-level paging (PML4), a requirement for x86_64 long mode, dividing the virtual address space between the kernel and userland.
@ -30,7 +30,7 @@ BoredOS uses 4-level paging (PML4), a requirement for x86_64 long mode, dividing
- **User Space**: Userland applications are loaded into lower virtual addresses.
- **Page Faults**: The `mem/` subsystem registers an Interrupt Service Routine (ISR) for page faults (Interrupt 14). If a process accesses unmapped memory, the handler determines whether to allocate a new frame or terminate the process.
## 🏗️ Kernel Heap
## Kernel Heap
Dynamic allocation within the kernel (`kmalloc` and `kfree`) is layered on top of the physical allocator. The kernel maintains its own heap area in virtual memory. When the heap requires more space, it requests physical frames from the PMM and maps them into the kernel's virtual address space.

View file

@ -7,7 +7,7 @@
BoredOS features a fully custom, graphical Window Manager built directly into the kernel, residing in the `src/wm/` directory. It is responsible for compositing the screen, handling window logic, rendering text, and dispatching UI events.
## 🖼️ Framebuffer and Rendering
## Framebuffer and Rendering
1. **Limine Framebuffer**: During boot, the Limine bootloader requests a graphical framebuffer from the hardware (e.g., GOP in UEFI environments) and passes a pointer to this linear memory buffer to the kernel.
2. **Double Buffering**: To prevent screen tearing, the WM does not draw directly to the screen. It allocates a "back buffer" in kernel memory equal to the size of the screen. All drawing operations (lines, rectangles, windows) happen on this back buffer.
@ -24,7 +24,7 @@ The windowing system is built around a linked list of `Window` structures.
- **Window Structures**: Each window object tracks its dimensions (`x`, `y`, `width`, `height`), title, background color, and an internal buffer if it's acting as a canvas for userland apps.
- **Decorations**: The kernel handles drawing window borders, title bars, and close buttons automatically unless a borderless style is specified.
## 🖱️ Input Handling and Events
## Input Handling and Events
The WM acts as the central hub for input routing.