Skip to content

Move to custom window chrome - #107

Open
huntharo wants to merge 3 commits into
tobi:mainfrom
huntharo:codex/custom-window-chrome
Open

huntharo wants to merge 3 commits into
tobi:mainfrom
huntharo:codex/custom-window-chrome

Conversation

@huntharo

Copy link
Copy Markdown
Contributor

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.
mtul0729 pushed a commit to mtul0729/nixpkgs that referenced this pull request Oct 22, 2026
disktree draws its own title strip, window buttons included, in
crates/disktree-app/src/chrome.rs, but only when GPUI reports
Decorations::Client. GPUI otherwise asks the compositor for server-side
decorations, and COSMIC grants that, so the window shows two bars:
cosmic-comp's above the app's own strip.

The patch sets WindowOptions::window_decorations to Client. It is a
throwaway probe for the head of tobi/disktree#107 (the container of the
upstream patch is the PR's src, not a tag, so this stays a local patch
file), and it is unconditional: a version worth sending upstream would
ask only where the compositor would otherwise decorate the window.
mtul0729 pushed a commit to mtul0729/nixpkgs that referenced this pull request Oct 22, 2026
disktree draws its own title strip, window buttons included, in
crates/disktree-app/src/chrome.rs, but only when GPUI reports
Decorations::Client. GPUI otherwise asks the compositor for server-side
decorations, and COSMIC grants that, so the window shows two bars:
cosmic-comp's above the app's own strip.

The patch sets WindowOptions::window_decorations to Client. It is a
throwaway probe for the head of tobi/disktree#107 (the container of the
upstream patch is the PR's src, not a tag, so this stays a local patch
file), and it is unconditional: a version worth sending upstream would
ask only where the compositor would otherwise decorate the window.
mtul0729 pushed a commit to mtul0729/nixpkgs that referenced this pull request Oct 22, 2026
disktree draws its own title strip, window buttons included, in
crates/disktree-app/src/chrome.rs, but only when GPUI reports
Decorations::Client. GPUI otherwise asks the compositor for server-side
decorations, and COSMIC grants that, so the window shows two bars:
cosmic-comp's above the app's own strip.

The patch sets WindowOptions::window_decorations to Client. It is a
throwaway probe for the head of tobi/disktree#107 (the container of the
upstream patch is the PR's src, not a tag, so this stays a local patch
file), and it is unconditional: a version worth sending upstream would
ask only where the compositor would otherwise decorate the window.
mtul0729 pushed a commit to mtul0729/nixpkgs that referenced this pull request Oct 22, 2026
disktree draws its own title strip, window buttons included, in
crates/disktree-app/src/chrome.rs, but only when GPUI reports
Decorations::Client. GPUI otherwise asks the compositor for server-side
decorations, and COSMIC grants that, so the window shows two bars:
cosmic-comp's above the app's own strip.

The patch sets WindowOptions::window_decorations to Client. It is a
throwaway probe for the head of tobi/disktree#107 (the container of the
upstream patch is the PR's src, not a tag, so this stays a local patch
file), and it is unconditional: a version worth sending upstream would
ask only where the compositor would otherwise decorate the window.
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