mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-11-06 00:15:06 +00:00
fix(titlebar): centre the traffic lights on the chrome row (#1085)
`y` in `traffic_light_position()` is the gap between the window's top edge and the top of the button frame, and AppKit draws those buttons 14 points tall, so the lights' centre lands seven points below it. The tiles beside them are centred in the title bar's content box instead — `TITLE_BAR_HEIGHT` less the hairline `TitleBar` draws along its bottom edge — which is 23.5 in a 48pt bar. The constant was still 17, the value the 40-point bar needed (13) rewritten by hand when the bar grew to 48, without that border in it, so the lights' centre came out at 24: half a point low, one whole device pixel on a Retina panel. It comes from the bar's own height now — `(48 - 1 - 14) / 2 = 16.5` today — and a test holds the lights to the tile line, so the next change of bar height has somewhere to move with it. Measured on macOS 26.3 with the style mask gpui uses (`fullSizeContentView` and a transparent title bar): the standard buttons are 14×14 points with 9 points of padding, in a 32pt title bar. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -5,6 +5,22 @@ All notable changes to tty7 are documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- **The macOS traffic lights sit on the same line as the tiles beside them.**
|
||||
The buttons AppKit draws are 14 points tall and gpui hangs the top of the
|
||||
frame `y` points below the window's top edge, so the lights' centre falls
|
||||
seven points under the bar's top; the New Tab and sidebar tiles are centred
|
||||
in the bar's content box instead — its height less the hairline `TitleBar`
|
||||
draws along the bottom edge. The position was still the one the 40-point bar
|
||||
called for, carried over by hand when the bar grew to 48 without that
|
||||
hairline in it, which left the lights half a point below everything else in
|
||||
the row: one device pixel on a Retina panel. `traffic_light_position()` now
|
||||
derives it from `TITLE_BAR_HEIGHT`, and a test holds the lights to the tile
|
||||
line through the next change of bar height.
|
||||
|
||||
## [26.9.4] - 2026-09-29
|
||||
|
||||
### Added
|
||||
|
||||
+32
-1
@@ -11,14 +11,33 @@ use crate::terminal::view::{
|
||||
ClearScrollback, CopyText, CutText, FindInTerminal, FindNext, FindPrevious, PasteText,
|
||||
RedoEdit, SelectAll, UndoEdit,
|
||||
};
|
||||
use crate::ui::app::TITLE_BAR_HEIGHT;
|
||||
use crate::ui::i18n::{L10nKey, t};
|
||||
use crate::ui::presets;
|
||||
use crate::ui::presets::Fill;
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::sync::OnceLock;
|
||||
|
||||
/// Where macOS puts the window's traffic lights over the tab strip: nine
|
||||
/// points in from the left edge, and centred on the row of chrome tiles they
|
||||
/// share the bar with.
|
||||
///
|
||||
/// `y` is the gap between the window's top edge and the *top* of the button
|
||||
/// frame, and macOS draws those buttons 14 points tall — so the lights' centre
|
||||
/// falls seven points below it. The tiles sit in the middle of the bar's
|
||||
/// content box instead, which is `TITLE_BAR_HEIGHT` less the hairline
|
||||
/// `TitleBar` draws along its bottom edge. Deriving the number from those two
|
||||
/// facts rather than writing it out is what keeps the lights on the tile line:
|
||||
/// the value the 40-point bar needed was rewritten by hand when the bar grew
|
||||
/// to 48, without the border in it, and left the lights half a point — one
|
||||
/// device pixel on a Retina panel — below everything beside them.
|
||||
pub(crate) fn traffic_light_position() -> Point<Pixels> {
|
||||
point(px(9.), px(17.))
|
||||
// AppKit's own button frame, and the border `TitleBar` adds to the bar it
|
||||
// wraps. Neither moves with the bar's height.
|
||||
const BUTTON_H: f32 = 14.;
|
||||
const BAR_BORDER: f32 = 1.;
|
||||
|
||||
point(px(9.), px((TITLE_BAR_HEIGHT - BAR_BORDER - BUTTON_H) / 2.))
|
||||
}
|
||||
|
||||
pub(crate) fn set_menus(cx: &mut App) {
|
||||
@@ -1022,6 +1041,18 @@ mod tests {
|
||||
use super::*;
|
||||
use gpui::TestAppContext;
|
||||
|
||||
/// The lights share a line with the chrome tiles they sit beside. gpui
|
||||
/// hangs the top of the 14pt frame `y` below the window's top edge, so
|
||||
/// their centre is seven points under that; the tiles are centred in the
|
||||
/// bar's content box, its height less the hairline `TitleBar` draws along
|
||||
/// the bottom. Sixteen and a half points today, out of the 48pt bar.
|
||||
#[test]
|
||||
fn the_traffic_lights_sit_on_the_chrome_rows_centre() {
|
||||
let position = traffic_light_position();
|
||||
assert_eq!(position.x, px(9.));
|
||||
assert_eq!(position.y + px(7.), px((TITLE_BAR_HEIGHT - 1.) / 2.));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn effective_preset_follows_the_cached_system_appearance(cx: &mut TestAppContext) {
|
||||
cx.update(|cx| {
|
||||
|
||||
Reference in New Issue
Block a user