Skip to content

Move to custom window chrome - #10

Open
huntharo wants to merge 2 commits into
mainfrom
codex/custom-window-chrome
Open

huntharo wants to merge 2 commits into
mainfrom
codex/custom-window-chrome

Conversation

@huntharo

@huntharo huntharo commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Moves disktree to custom window chrome: the title bar and the app's top bar become one 40 pt strip holding the window controls, the real app icon (assets/disktree.svg) and wordmark, the trail and the view settings. The four-square logo is gone.

Before After
Before: a system title bar above the app's own top bar After: one strip, stoplights, icon, wordmark, trail

The whole window on macOS

GNOME (Ubuntu, in a VM)

GNOME asks the client to draw the frame, so the strip draws the buttons on the side GNOME's button layout puts them (right, by Ubuntu's default).

Maximized: restore glyph, no border or ring Floating: maximize glyph, border, resize ring
GNOME, maximized GNOME, floating

Windows 11

Caption buttons on the right at the system's 46 px width, with the hover fill on minimize; the light theme, and the window's own rounded corners and shadow from Windows.

Windows 11, light theme

Per platform

  • macOS: transparent titlebar, stoplights at (16, 13) so they centre in the 40 pt band; the icon and wordmark start clear of them. The strip moves the window itself (app_owns_titlebar_drag), and a double-click does whatever the system's titlebar setting says. In full screen the stoplight gap closes.
  • Windows: minimize, maximize and close on the right, 46 × 40, hit-tested as the system's own caption buttons, so snap layouts and Aero drag still come from Windows.
  • Linux: the window still asks for server-side decorations. Where the compositor draws them (Hyprland/Omarchy, KDE), the strip has no controls and the compositor keeps moving and closing the window. Where it asks the client to (GNOME on Wayland), the strip draws close / minimize / maximize on the side GNOME's button layout says, keeping only the ones the compositor supports. It moves on drag, maximizes on double-click and opens the window menu on right-click, and the window gets a border, a shadow and a resize ring on every side that isn't tiled.

Which side the controls go on is decided in one place, chrome::Frame::new.

Kept as they were: the treemap owns the keyboard from the first frame, the minimum window size, and the Wayland app_id disktree. The window title is still set; the Window menu and window switchers read it.

The wordmark folds to just the icon below 70 rem on the explore screen, so the trail keeps its room. On review and the other screens, the strip carries only the brand and a drag area, because those screens have their own header.

Tests

cargo xtask lint and cargo xtask test are green.

  • chrome.rs unit tests: what each platform and decoration mode puts at each end.
  • Window-harness tests draw the strip on Explore, Review and Done for macOS, macOS full screen, Windows, a server-decorated Linux, GNOME with controls on the right and on the left, and GNOME maximized. They check the strip's height, that the brand stays clear of the controls, and that Windows' buttons sit at the right edge.
  • The client-side frame keeps its ring and grips until it is tiled.
  • The wordmark gives way in a narrow window.
  • A press on the strip arms a move, and a plain click disarms it.

Not run

  • Hyprland/Omarchy and KDE were not run, only built and tested in the window harness here. GNOME (Ubuntu, floating and maximized) and Windows 11 were run in VMs (screenshots above); dragging, double-click, snap layouts, the window menu and the resize grips there can't be judged from screenshots.
  • The move itself can't run in the harness: the test platform leaves start_window_move unimplemented. On macOS the strip was checked by eye in a release build; dragging, double-clicking and the Windows and GNOME buttons were not exercised by hand.
  • Only checked in the default Omarchy theme at the default font size.

The title bar and the app's own top bar become one 40 pt strip: the
window controls, the real app icon and wordmark, then the trail and the
view settings. The four-square logo is gone.

macOS keeps its stoplights, in a transparent titlebar, centred in the
strip. Windows paints its caption buttons on the right and hit-tests them
as the system's own, so snap layouts still work. On Linux the compositor
keeps drawing the frame where it offers one (Hyprland, KDE); where it
asks the client to (GNOME on Wayland), the strip draws close, minimize
and maximize on the side the desktop's button layout says, and the
window gets a resize ring and a border until it is tiled.

The treemap still owns the keyboard from the first frame; the minimum
size and the Wayland app_id are unchanged.
Under a floating GNOME frame the content sits inside the resize ring and
border, so the cursor tooltip and the panel's resize handle, which work in
window coordinates, landed 11 px off the pointer. The frame now says how
far the content is inset and both take it off.

The brand's drag area takes the band's full height and the padding beside
it, and the space between the trail and the settings is one drag area
instead of a spacer with gaps, so nothing in the strip looks like title
bar without moving the window. A press that leaves the strip before its
first motion no longer stays armed for a later drag across it, and a
compositor that takes the frame back gets the whole surface again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant