feat(chrome): make the title bar's line whole off macOS

macOS fills the window's leading corner with the traffic lights and
`TITLE_BAR_LEAD` reserves them 80px. Everywhere else that corner held
nothing: the caption row's only contents are the rail's "+" and collapse
at the rail's right edge and the corner chrome at the window's, so the
left third of the row read as unfinished rather than restrained — while
Windows treats the top-left as the app's identity slot.

Three parts, all of them about that row:

- `window_mark()` draws the "duo" mark (the app icon's own art) at the
  head of the rail on `CONTENT_INSET`, the line the search box and every
  row label below it start on, and follows the rail's controls into the
  title strip when the sidebar collapses. It is drawn, never clicked: no
  hover capsule, and deliberately no `occlude()`, so the drag region
  underneath still takes the press and the strip stays grabbable.

- The rail's stand-in row now reserves the same hairline the real
  `TitleBar` draws inside its own height. Without it the bar centred
  content on 19.5 and the rail on 20, and the mark hopped half a pixel
  as collapsing the rail handed it from one to the other.

- With the detail panel open off macOS the bar is hoisted above
  `[terminal | panel]` so the window controls can reach the corner, which
  left the code and diff overlays — anchored to the terminal column —
  starting 40px down, with headers drawn to *be* the title bar landing a
  row low. They now hang on the row that owns the bar, inset by the
  panel's width. Covering the caption row that way needs the headers to
  carry its gestures, which neither ever did with the panel open or
  closed: `title_bar_drag()` gives both (and the rail's row, which grew
  the same wiring by hand) drag-to-move and double-click-to-zoom, and
  their controls are `occlude()`d so HTCAPTION stops eating the clicks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WCb8ZDmvdA5xbVtvs647tD
This commit is contained in:
thomas
2026-07-26 23:08:18 +08:00
co-authored by Claude Opus 5
parent 313c1c3c8b
commit a67cf2b2ad
6 changed files with 280 additions and 101 deletions
+26 -18
View File
@@ -801,7 +801,7 @@ impl Tty7App {
/// every buffer that was ever opened. Sits on the title bar's line and matches
/// its height, so the editor's top edge lines up with the panel's tab row and
/// the rail's controls across the window.
fn render_editor_header(&self, cx: &mut Context<Self>) -> gpui::Div {
fn render_editor_header(&self, cx: &mut Context<Self>) -> gpui::Stateful<gpui::Div> {
let active = self.tab_code().and_then(|c| c.active_file());
let name = active.map(|f| f.label());
let dirty = active.is_some_and(|f| f.dirty);
@@ -816,7 +816,10 @@ impl Tty7App {
} else {
crate::ui::app::TITLE_BAR_LEAD
};
h_flex()
// The overlay covers the real title bar, so this row inherits its drag and
// zoom gestures — otherwise opening a file turns the top of the window into
// a strip that looks like the caption and can't move it.
crate::ui::app::title_bar_drag(h_flex().id("editor-header"))
.flex_none()
.h(px(crate::ui::app::TITLE_BAR_HEIGHT))
.items_center()
@@ -847,22 +850,27 @@ impl Tty7App {
)
})
.child(
crate::ui::tab_strip::chrome_tile_sized(
// This header is the title bar's own height and sits flush
// with it, so its one control is a full chrome tile — not the
// half-size one it used to be, which read as a different
// class of button on the same line.
Button::new("editor-panel-close").icon(Icon::new(IconName::Close)),
crate::ui::app::TILE_SIZE,
crate::ui::app::TILE_GLYPH_LINE,
false,
cx,
)
.rounded_lg()
.tooltip("Back to Terminal (Esc)")
.on_click(cx.listener(|this, _, window, cx| {
this.toggle_code_panel(window, cx);
})),
// `occlude()` for the same reason the title bar's own tiles carry
// it: this row is a `WindowControlArea::Drag`, which on Windows is
// HTCAPTION, and the OS takes the press before gpui hit-tests.
div().occlude().flex_shrink_0().child(
crate::ui::tab_strip::chrome_tile_sized(
// This header is the title bar's own height and sits flush
// with it, so its one control is a full chrome tile — not the
// half-size one it used to be, which read as a different
// class of button on the same line.
Button::new("editor-panel-close").icon(Icon::new(IconName::Close)),
crate::ui::app::TILE_SIZE,
crate::ui::app::TILE_GLYPH_LINE,
false,
cx,
)
.rounded_lg()
.tooltip("Back to Terminal (Esc)")
.on_click(cx.listener(|this, _, window, cx| {
this.toggle_code_panel(window, cx);
})),
),
)
}