All apps are compiled as kernel-mode translation units (same flags, same address space as the kernel) and linked directly into build/quin_kernel.elf. They render into QWM client canvases using the QuinUI widget toolkit and direct canvas drawing.
| App | Directory | Window Position | Key Features |
|---|---|---|---|
| Clock | clock/ |
Top-right (1050, 65) | Analog face, fixed-point sin/cos, digital HH:MM:SS, blinking colon, uptime |
| System Monitor | sysmon/ |
Mid-right (840, 320) | Live PMM stats, FPS counter, thread count, VFS mounts |
| File Manager | filemanager/ |
Bottom-right (660, 390) | VFS readdir, hover rows, type/size columns |
| Calculator | calculator/ |
Bottom-left (30, 390) | 4-function integer calc, 5×4 button grid |
| Notepad | notepad/ |
Bottom-centre (260, 390) | Keyboard input, word wrap, blinking block cursor |
| Terminal | terminal/ |
Centre (120, 120) | qsh built-ins, 64-line scrollback, CRT scanline effect, blinking cursor |
| Image Viewer | imgviewer/ |
Upper-centre (280, 50) | 6 procedural images, Prev/Next navigation |
| Settings | settings/ |
Top-left (40, 50) | 5-tab panel (Display/Sound/Input/About/Theme), sliders, checkboxes |
| Paint | paint/ |
Lower-centre (200, 180) | Mouse canvas, 16-colour palette, adjustable brush, faint grid |
| Music Player | musicplayer/ |
Right edge (600, 90) | 32-bar animated visualizer, 5 tracks, play/pause/prev/next/seek |
Each app follows this standard pattern:
// Initialisation (called once from apps_init()):
void app_xxx_init(void) {
s_win = qwm_create("Title", x, y, w, h, QWM_FLAG_NONE);
qui_button(s_win, ...); // add QuinUI widgets
qui_register_app(app_xxx_frame); // register per-frame callback
qwm_show(s_win);
}
// Per-frame callback (called every compositor tick via qui_update → g_apps[]):
static void app_xxx_frame(void) {
uint32_t *cvs = qwm_get_canvas(s_win);
uint32_t cw = qwm_get_canvas_width(s_win);
uint32_t ch = qwm_get_canvas_height(s_win);
// read input, update state, draw into canvas, call qwm_invalidate()
}Uses a precomputed 60-entry sin/cos table (scaled ×1000) to avoid floating-point (kernel is compiled with -mno-sse -mno-sse2):
tip_x = cx + (sin_t60[angle] * length) / 1000;
tip_y = cy - (cos_t60[angle] * length) / 1000; // Y-flipped for screen coords
Time is derived from scheduler_get_ticks() (100 Hz PIT):
seconds = ticks / 100
minutes = seconds / 60
hours = (seconds / 3600) % 12
Maintains a 64-line scrollback ring buffer (TERM_HIST). Every other pixel row is darkened by 10% to simulate a CRT scanline effect. Built-in commands: help, clear, uname, uptime, mem, echo, ls, ver.
Six images generated entirely in software (no image files required):
- Gradient Spectrum HSV hue rotation across width
- Plasma Wave three overlapping sine-table patterns
- Checkerboard per-square gradients
- Color Bars SMPTE-style 8 bars
- Mandelbrot 28-iteration fixed-point 8.24 arithmetic
- Star Field LCG pseudo-random stars + nebula alpha blend + moon circle
Reads global mouse position via mouse_get_x/y(), converts to canvas-relative coordinates using qwm_get_canvas_screen_x/y(). Draws filled circles into a static uint32_t[300][544] bitmap; the bitmap is blitted into the canvas each frame.
32 frequency bars driven by a 64-entry sine table phased by scheduler_get_ticks() and the current track's BPM. Each bar is rendered with a top-to-bottom gradient (bright blue → dark blue) plus a white glow cap. Progress bar is a QUI_PROGRESSBAR widget updated via qui_set_value() each frame.
Five tabs (Display, Sound, Input, About, Theme) rendered via a per-frame switch(s_tab) dispatch. Tab buttons are transparent QUI_BUTTON widgets overlaid on a manually drawn tab bar. Sliders control demo values (brightness, contrast, volume, mouse speed) via qui_change_fn callbacks.
| Metric | Source |
|---|---|
| CPU Uptime | scheduler_get_ticks() / 100 (seconds) |
| Memory Used/Free | pmm_get_stats() → used_frames × 4 KB |
| Thread Count | scheduler_get_thread_count() |
| VFS Mounts | vfs_get_mount_count() |
| FPS | 100-frame sliding window over PIT ticks |
qds_init(fb_width, fb_height); // Phase 3 Step 1 display server
qwm_init(); // Phase 3 Step 2 window manager
qui_init(); // Phase 3 Step 3 QuinUI + demo windows
apps_init(); // Phase 3 Step 4 + Phase 4 all 10 apps
qwm_run(); // event loop (never returns)apps_init() (in apps/apps.c) registers all 10 apps in Z-order (first = bottommost):
app_sysmon_init(); // Phase 3 behind other windows
app_filemanager_init();
app_calculator_init();
app_notepad_init();
app_clock_init(); // Phase 3 topmost of P3 stack
app_settings_init(); // Phase 4
app_imgviewer_init();
app_musicplayer_init();
app_terminal_init();
app_paint_init(); // Phase 4 topmost (front)The Notepad reads keyboard_has_char() / keyboard_getchar() inside its frame callback, which runs via qui_update() → g_apps[]. This happens before QWM's own keyboard poll:
qwm_run() per tick:
1. qui_update() ← all app frame callbacks run here (notepad reads keys)
2. process_mouse() ← QWM drag / click handling
3. process_keyboard() ← Alt+F4 only (chars already consumed)
4. qwm_composite()
5. hlt
All app .c files are listed in C_SOURCES in the root Makefile and compiled with the same kernel flags:
apps/apps.c
apps/clock/clock.c
apps/calculator/calculator.c
apps/notepad/notepad.c
apps/filemanager/filemanager.c
apps/sysmon/sysmon.c
apps/terminal/terminal.c
apps/imgviewer/imgviewer.c
apps/settings/settings.c
apps/paint/paint.c
apps/musicplayer/musicplayer.cCompile flags: -m64 -ffreestanding -nostdlib -mno-red-zone -mno-sse -mno-sse2 -Wall -Wextra -Werror -O2
Quin OS Team