Title band layout

Status: accepted. Mark, 2026-10-27.

The menu group, title, Action Bar and window controls each align left, centre or right. CSD and SSD use design::title_band::layout. The app mark belongs to the menu group. MixOS titles centre by default; mac centres and win11 starts at the left.

Appearance keyNamesDefault
menu_sideleft, center, rightleft
title_alignauto, left, center, rightauto
actions_alignleft, center, rightright
actions_placerow, titlebarrow
caption_sideauto, left, center, rightauto

These are named registries in libs/design. Unknown plain names survive storage and resolve as defaults. Defaults are omitted in full and compact settings, preserving existing profile seals. Caption auto resolves to right in CSD and the preset's cluster side in SSD. Previously omitted captions were right in CSD; SSD did not read them. Explicit right remains explicit right. The appearance portal keeps its older effective right default and omission rule independently of the stored request. An omitted effective caption request now reads as auto; older projection readers cannot parse center.

layout(width: f32, groups: &[Group]) -> Vec<Rect> uses logical coordinates. Each group supplies preferred width, minimum width, alignment, optional shrink priority and centre reading order. Rectangles contain x and width; the caller supplies the common band's y and height. Input order is controls, menu, actions, title, so groups stack from either edge in that order. Centre reading order is menu, title, actions, controls. The centre pack uses the whole band's centre if free, otherwise the gap between the side stacks. Title shrink priority is 0, Action Bar priority 1. Controls and menus are fixed. Action Bars drop app actions from the left and retain the standard tail. SSD retains enough frame width for fixed groups and that tail. The CSD edge groups include the existing inner margins. Its default centred title retains the previous half-margin offset; an explicit centre uses the full band's centre. Only this frame's gaps outside all four groups drag. SSD auto reads the preset's title alignment; the client registry records the same default and a consistency test checks the presets against it.

Action Bar hosting shares the compact-menu registration agreement: drive::set_service must match the app's own drive, and decorations must be SSD. The compositor uses the same scene-host registry snapshot and exact dev.mixos.NAME to registered NAME mapping. Disconnection removes hosting data. CSD or an unregistered drive keeps the app's bar.

Apps expose a revisioned bar in <app>.ui.titlebar.form only while hosting is possible. Toolkit coalesces item changes for 100 ms and schedules the trailing update. Through the drive, each app's existing Bus publisher emits <app>.ui.titlebar.changed {revision} only on change. The scene-host worker subscribes before reading once at hosting start, then reads on notifications stamped by the local broker as that registered service. Changes arriving during a read coalesce into one follow-up read. A 30-second resync recovers lost notifications or failed initial reads. It retains the last good bar on read failure, fences replies by connection generation and reader epoch, cancels obsolete work and removes departed services' bars. The topic uses the existing connection and registry.

Pointer actions carry the bar revision and index; revisions are seeded from the app's startup timestamp so a new process cannot restart the click fence at zero. Stale presses are refused. Layouts are cached on each window by geometry revision, size and theme generation; hover changes reuse their geometry. comp.window.action {id, generation, command} uses the same enabled-item check and scene-host event sink to send <app>.execute {id}. Calls are non-blocking and failures are logged. comp.props exposes decoration.actions and each surface's action_count. ui.titlebar.form reports requested and effective placement, alignments, the matched service and hosted items.

Tooltips use the existing compositor tooltip delay and card renderer, with the session tokens and output clamping. Lucide names and SVGs belong to libs/icons; toolkit loads them through egui and decor rasterises them with the workspace resvg.

A future group adds an input in each renderer and its rendering and hit targets; the generic layout function stays unchanged. A future alignment extends Alignment, the named registries and their conversions, placement logic, Prefs labels and combination tests. Per-app overrides and new styles are outside this decision.

This page as Markdown · This page describes the current main branch of MixOS.