Desktop Services and Apps
/bin/init.elf starts the desktop session and supervises it. All windows register through the shared registry described in Window manager.
init
Startup order:
- Spawn the window manager.
- Wait for the shared registry to become valid (magic + menubar/dock block ids), up to 500 attempts at 10 ms.
- Spawn the menubar, then the dock.
- Read
launch_terminal_on_bootfromSYSTEM.CFGand optionally spawn the terminal. - Supervision loop on
waitpid(-1):- WM exits → menubar and dock are terminated and the whole desktop restarts (retries with backoff, killing partial children on failure).
- Menubar or dock exit → respawned individually.
- Other children are logged.
Menubar
Occupies window slot 0. Renders a canvas taller than the visible strip (for dropdown menus) into a shared block and pushes damage. Strip order: uniOS logo menu, focused window title (the app name), the focused app's menus, and a clock/date button (Mon D HH:MM, seconds optional) that toggles the control center (cp_toggle_requested; the WM also toggles it for clicks in the rightmost 120 px). Hover damage tracks the logo and date buttons independently. The system menu offers Settings, Close/Minimize/Maximize of the focused window, Restart, and Shut Down. Launchers focus an existing window by app title (gui_window_title_matches) or fork+exec the app.
App menus. The focused app publishes a menu model into the registry (MenuModel: owner pid + seq-stability protocol, up to 8 menus x 16 items with labels, accelerators, disabled/checked flags). The menubar renders the model only while owner_pid == focused_owner_pid, and appends a composed Window menu for every app (Minimize / Maximize-Restore / Close, then a live list of open windows, checked = focused). Clicking a menu name opens its dropdown; hovering another name switches; item clicks dispatch the item ID back through the window's menu_command_id/menu_command_seq fields, which the app polls with gui_menu_take_command. IDs at or above MENU_CMD_RESERVED_BASE are handled menubar-side (About uniOS focuses or launches the Settings window on its About section). Dropdowns draw accelerators right-aligned, vector checkmarks for checked items, and dimmed disabled items.
Dock
Occupies window slot 1: Files, Image Viewer, Music, Latitude, Terminal, Calculator, Calendar, Clock, Settings. Icons come from .uoic packages (the calendar composes day/number assets over its base icon). Running windows get indicator dots; clicks cycle matching windows starting after the focused one, or launch. Window-to-app matching uses gui_window_title_matches (exact title or detail - App suffix), so dynamically retitled windows like data - Files still count as running. Launching shows a hollow pending indicator and suppresses duplicate launches until the window registers (8 s timeout); clicks flash a brief pressed state. The dock renders a glass panel over a blurred backdrop and publishes its width in the registry.
Applications
Every graphical app is built on the libapp runtime (on_draw/on_event/on_menu/on_menus/on_settings/on_idle callbacks over a managed window and canvas — see Userspace runtime); window registration, the event loop, resize/theme/menu plumbing, and damage publishing are shared infrastructure, not per-app code. The terminal additionally drives its own loop in manual mode around the shell pipe; threadtest is a plain-C self-test with no GUI stack.
All graphical apps share one seamless headerbar: none paints its own title strip or a divider under the band. The WM overlays the traffic lights at the top-left; apps either place toolbar controls inside the band (publishing them as header input so they stay clickable) or start their content below it. See Window manager — Window Chrome and Unified Headerbar.
| App | Description |
|---|---|
| terminal | Terminal emulator hosting the shell over pipes; epoll on shell output plus GUI events (~16 ms idle poll); per-cell colors with an ANSI CSI subset (clear, cursor home/move, erase line, SGR foreground colors). The I/O field (cells, frame, caret, selection, scrollbar) is pinned to the dark palette regardless of the active theme, so output stays legible; only the WM-supplied window chrome follows the theme. The cell grid starts below the unified headerbar, which shows a dimmed centered window title and is fully draggable (no interactive header controls). 2048-line scrollback that holds its position while output streams; blinking caret while focused; starts 80x25. Mouse drag selects output (tinted with the accent color; the selection is in viewport coordinates and clears on scroll, resize, new output, or Clear Screen); copy goes to the system clipboard with Ctrl+X or Edit > Copy (Ctrl+C stays SIGINT), and paste writes the clipboard into the shell with Ctrl+V or right-click. Tabs in shell output expand to 8-column stops. The scrollbar is fully interactive: thumb drag, track paging (half a viewport) and a brighter hovered thumb; when the shell exits it is reaped immediately after the EOF banner. Publishes app menus: Edit (Copy/Paste/Select All/Clear Screen), View (Zoom In / Zoom Out / Actual Size — a font-step offset persisted as terminal_zoom, menu-driven because Ctrl+=/- collapse to plain '='/'-' at the PS/2 layer), and Help (tips overlay, About). |
| files | File manager: places sidebar (Home /data, Desktop, Documents, Downloads, Music, Pictures) + volumes; listing via SYS_GETDENTS sorted into display order (directories first, then files, each by name); new folder, rename, copy, move; context menus clamped to the viewport; storage-mode aware; empty directories show a muted placeholder row. Hover feedback on all rows/places/volumes (icon view highlights only the item's label, matching its selection capsule) with the hover rebased when the view scrolls under a stationary pointer; pointer moves repaint only when the hovered region changes; arrow-key navigation, dialogs centered on the viewport with a dimmed scrim, release-to-apply buttons and outside-click dismiss; the window title tracks the browsed location, using friendly labels at storage roots (Home / the volume name) instead of raw path segments. The sticky toolbar in the headerbar always shows the path bar (breadcrumb) on the left (clear of the traffic lights when the sidebar is hidden) with transient status beside it, and the List/Icons view switcher (with per-segment hover) on the right, published as header input so it stays clickable. Icon view is the default and lays out a centered, gap-aware grid; list columns collapse gracefully on narrow rows. Image files (PNG/JPEG/GIF/BMP/QOI by extension, case-insensitive) get lazy libmedia thumbnails in icon view (decoded once per entry per directory, capped at 8 MiB source files, deferred until the cell scrolls into view), a file-type glyph in list view, and activating them (double-click, Enter, Open) submits a registry open request and launches imageviewer. Audio files (WAV by extension, case-insensitive) get an "Audio" type label, the music-note glyph in list view and the file-music type icon in icon view, and activating them submits a registry open request and launches musicplayer. Entries without a decoded thumbnail show per-type .uoic icons from /usr/share/appicons (folder / file / file-image / file-music), falling back to procedural shape glyphs if the asset fails to load. A View menu toggles the Places/Storage sidebar and switches between the list and icon layouts, both persisted as files_sidebar / files_view_mode. Publishes app menus: File (New Folder, Rename, Delete), Edit (Cut/Copy/Paste through the system clipboard with copy:/cut: path payloads), View (Show Sidebar, Show as Icons, Refresh), Go (Up, places, mounted volumes with checked states), Help (tips dialog, About); accelerators Ctrl+N/X/C/V. |
| preferences | Settings app: Appearance (theme, wallpaper, transparency, animations), Desktop (grid, clock seconds, volume), Network (read-only live status rows — interface, link, IP, netmask, gateway, DNS from SYS_NET_STATUS, refreshed on section entry — plus a "Renew DHCP Lease" button over SYS_NET_RENEW), System (launch terminal, storage mode), Devices (pointer-speed and key-repeat sliders — pointer speed persists as the kernel's Q8 multiplier and reloads across the full 16..1024 range; per-device enable toggles over the SYS_INPUT_ENUM_DEVICES list), and About (kernel commit, bootloader, CPU, timer, memory, uptime, and display capabilities refreshed at 1 Hz). The left rail is a glyph sidebar of pill rows; the detail pane lays settings out as libadwaita-style boxed groups (one rounded card per group, inset hairline dividers). The active section title sits in the headerbar over the detail pane, so the band is viewport content that stays draggable around the title. Widget events are gated by the active section so stale rects can't steal a click; config writes are atomic (write-temp-then-rename). Writes registry fields and persists SYSTEM.CFG/wallpaper config. Wallpaper Apply/Default use release-to-apply with pressed feedback, the volume slider drags past the window via the WM pointer grab, Esc leaves the wallpaper field, and sticky panels redraw on scroll. The reserved About uniOS command (and a about open request) switches the window to the About section. Publishes app menus: Help (tips overlay, About). |
| latitude | Text/code editor: 2048 x 512 buffer, 512 KiB open limit with binary sniffing, syntax highlighting (text, C++, JS, Python, Rust, HTML, CSS, JSON, Markdown, shell) with a theme-aware palette — pastel hues on the dark editor well, deeper GitHub-light hues on the white light-mode editor, project browser, outline, search panes. New/Reload require a confirming second click while changes are unsaved, saves post a system toast, and hover clears on pointer exit. The headerbar carries the New/Save/Reload buttons (clear of the traffic lights), the buffer tab pill (or the path field while editing it) centered, and the search field on the right — all published as header input so they stay clickable; the window title tracks the open file. Mouse drag and Shift+arrows select text; Cut/Copy/Paste go through the system clipboard and a bounded line-snapshot undo/redo stack (typing bursts coalesce); accelerators Ctrl+Z/Y/A/X/C/V. Publishes app menus: File (New/Open/Save/Reload), Edit (Undo/Redo/Cut/Copy/Paste/Delete/Select All), View (Word Wrap, Line Numbers, Syntax Highlight — persisted as latitude_wrap / latitude_gutter / latitude_highlight; wrap reflows long lines into visual segments with the gutter number on a buffer line's first visual line), Help (tips overlay, About). |
| clock | Analog clock with continuous-sweep hands driven by a free-running monotonic counter (TSC when available, otherwise scheduler ticks); an RTC phase servo trims it once per second through a bounded-rate correction (hand speed kept within 0.7x-1.3x) so the hands never snap, freeze, or reverse — only a genuine wall-clock step (>2 s) produces a single visible jump, and a non-+1 RTC reading is accepted only after two consecutive matching reads. The tick rate is self-calibrated from observed RTC boundaries (with re-lock confirmation) and also paces the frame loop. The face is centered in the content area below the unified headerbar; digital time and date sit below it. Per-frame damage is limited to the face and text regions. Publishes app menus: Help (tips overlay, About). |
| calendar | Compact month grid (320x300 window) with circular day cells: today is a filled accent circle, the selected day an outlined circle, adjacent-month days dimmed. The headerbar carries the prev/next arrows and month/year title (clear of the traffic lights) plus a small Today jump button, published as header input so they stay clickable; Sakamoto weekday computation and leap-year-aware month lengths. Wheel and Page Up/Down change the month, arrow keys move the selection across month boundaries, T jumps to today, and hover clears on pointer exit. Publishes app menus: Help (tips overlay, About). |
| calculator | Keypad calculator with pending-op accumulator, percent, sign toggle (flips the whole entry in progress; right after an operator or = it pre-negates the next entry, so 5 + +/- 3 enters -3), and a 15-place decimal cap. The display and keypad fill the content area below the unified headerbar (the band is fully draggable). Full keyboard input (digits, operators, Enter/=, Backspace clears entry, Esc clears all), release-to-apply button semantics with drag-away cancel, an armed-operator highlight, divide-by-zero Error state, and a display that keeps the newest digits visible on overflow. Publishes app menus: Edit (Copy Result to the clipboard with Ctrl+C, Clear Entry, Clear All), Help (tips overlay, About). |
| imageviewer | Image viewer over libmedia (PNG, baseline JPEG, GIF, BMP, QOI). At startup it takes a pending open request from the registry (open_generation/open_path, consumed and cleared once); without one it shows an empty-state placeholder. The decoded image is fit to the content area below the unified headerbar preserving aspect ratio through a cached bilinear-scaled copy, blended over a checkerboard so alpha stays visible, and the window title carries name - WxH - Image Viewer (the - Image Viewer suffix keeps the window matched to its dock item while retitled). Load/decode failures show an error state. Publishes app menus: Help (About). |
| musicplayer | Music player. Launches from the dock, or from Files by activating a .wav entry, which submits a registry open request first; at startup the player takes the pending request and starts playback. Plays PCM 16-bit mono/stereo WAV (8-48 kHz) via the libmedia probe media_audio_probe; the empty state offers a Play Demo button for the build-time demo track at /usr/share/music/demo.wav (a system asset staged like the wallpaper, not user data). Threading: one feeder pthread owns the stream syscalls (sound_stream_open/write/end) and reads the file in 64 KiB chunks, blocking in the kernel while the 2 MiB stream ring is full; the UI thread only touches transport syscalls (pause/resume/stop/volume/status) and shared state under a pthread mutex + condvar, so the window never blocks. Transport actions decide their transition under the lock at action time (never from a snapshot taken at event entry), and the stream's owned status flag decides whether the card may be touched — only the player's own stream is stopped or polled for position, so another app taking the single kernel stream displaces this feeder cleanly (phase STOPPED, foreign stream untouched). Layout (top to bottom): the track title, a muted format line (44100 Hz, stereo, 16-bit), the seek slider with a live m:ss / m:ss position readout in place of the percent, the Play/Pause + Stop transport row, the volume slider (card master volume, initialized from the registry volume_level), and a muted status line (Opening/Buffering/Playing/Paused/Finished/Stopped or the load/stream error) - an idle poll repaints while the owned stream's position advances, and the end position is kept on DONE. The seek slider works in payload bytes floored to whole PCM frames (hidden with a serial log for tracks above 4 GiB); dragging it scrubs live - the position is applied every 200 ms while dragging and once more on release, the readout follows the dragged position, and the final release persists it. Pause parks the feeder on the condvar; a pause arriving before the kernel starts DMA is latched stream-side (see Audio) and honored at the restart, so pause-during-buffering is never lost. Seek stops the owned stream to break a full-ring-blocked write and the feeder reopens at the new offset (frame-aligned); seeking while STOPPED, DONE or after an error restarts playback at that offset instead of being a dead control, and the position display holds the target through the restart. Stop resets the position display to the track start. A seek that races the end-of-drain completion is re-checked under the lock before the feeder declares DONE, so it cannot be lost. The demo button exists only in the empty state (its rect is not fed events once a track is loaded, so clicks in that area cannot silently restart the demo). Because the 2 MiB kernel ring can hold an entire track, the feeder parks in a drain poll at EOF instead of exiting: the phase stays PLAYING (transport, timer and seek stay live) until the kernel auto-closes the ended, drained stream (a never-started empty stream closes immediately at sound_stream_end). Resizable 520x420 window. Publishes app menus: Help (About). |
| threadtest | Userspace pthread self-test: plain C linking crt0 + libc plus a lazily-linked libmedia (only the WAV probe object is pulled in), no window, not dock-launchable. Debug builds boot-launch it from the deferred boot-services task (kernel_exec of /bin/threadtest.elf after the net self-test spawn); release builds never launch it, and it is runnable from the shell. Seven scenarios — create (a thread-opened fd stays usable in the leader: the thread opens /etc/system.conf, the leader fsizes it and pthread_join collects the return value), mutex stress (four threads × 2500 iterations around one counter), condvar (timedwait timeout and wake cycles anchored to the consumer's park, plus a broadcast phase), join (per-worker return values over pthread_once and the rwlock), detach (waitpid on the detached tid fails), tls (per-thread __thread blocks and the TCB self-identity contract), and wavprobe (media_audio_probe over hand-packed WAV byte streams). Prints one serial summary line and exits nonzero when any scenario fails — see Testing. |
All user windows are resizable (WIN_FLAG_RESIZABLE) and follow the resize protocol in Window manager.