add theme titlebar height and app-owned strip dragging

This commit is contained in:
2026-11-03 08:15:23 +07:00
parent 6d7b9fbf24
commit 1340dcf3e9
12 changed files with 114 additions and 26 deletions
+3
View File
@@ -53,6 +53,8 @@ pub struct Theme {
pub motion: Motion,
/// Overlay scrollbar geometry.
pub scrollbar: Scrollbar,
/// The height the window's titlebar strips draw at, per the platform.
pub titlebar_height: Pixels,
/// The platform's native root font size; rem-based sizing scales with it.
pub root_font_size: Pixels,
pub sizes: SizeTable,
@@ -403,6 +405,7 @@ impl Theme {
elevations: resolved.elevations,
motion: resolved.motion,
scrollbar: resolved.scrollbar,
titlebar_height: resolved.titlebar_height,
root_font_size: resolved.root_font_size,
sizes: resolved.sizes,
accessibility: resolved.accessibility,
+21
View File
@@ -4,6 +4,10 @@ use crate::system::SystemTheme;
use crate::{ColorTokens, Elevations, Motion, Radius, Scrollbar, SizeTable, ThemeVariant};
use gpui::px;
/// The floor of a custom titlebar's height, in px at 100% scaling: the height
/// macOS and Linux titlebars draw at regardless of the control scale.
const TITLEBAR_HEIGHT_MIN_PX: f32 = 34.0;
/// Derived state shades for the colors that get pressed and hovered.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Ramps {
@@ -25,6 +29,8 @@ pub struct ResolvedTheme {
pub elevations: Elevations,
pub motion: Motion,
pub scrollbar: Scrollbar,
/// The height the window's titlebar strips draw at, per the platform.
pub titlebar_height: gpui::Pixels,
/// The platform's native root font size; the fallback theme uses 16.
pub root_font_size: gpui::Pixels,
pub sizes: SizeTable,
@@ -196,6 +202,11 @@ pub(crate) fn resolve(
sizes.set_input_height(input_height);
}
// A platform that states its titlebar height wins.
let titlebar_height = system
.titlebar_height
.unwrap_or_else(|| sizes.medium.control_height.max(px(TITLEBAR_HEIGHT_MIN_PX)));
let mut radius = Radius::default();
if let Some(control) = preset
.and_then(|def| def.control_radius)
@@ -228,6 +239,7 @@ pub(crate) fn resolve(
elevations: Elevations::for_platform(system.source, variant),
motion: Motion::default(),
scrollbar: Scrollbar::default(),
titlebar_height,
root_font_size,
sizes,
accessibility,
@@ -255,6 +267,7 @@ mod tests {
palette,
control_radius: None,
input_height: None,
titlebar_height: None,
root_font_size: None,
accessibility: AccessibilityPreferences::default(),
source: SourceKind::Macos,
@@ -303,9 +316,17 @@ mod tests {
assert_eq!(resolved.sizes.medium.dense_padding_x, px(16. * 0.75));
assert_eq!(resolved.sizes.medium.plate_inset, px(4.));
assert_eq!(resolved.sizes.medium.strip_height, px(32.));
assert_eq!(resolved.titlebar_height, px(34.));
}
}
#[test]
fn a_stated_titlebar_height_wins_over_the_control_scale() {
let mut stated = system(ThemeVariant::Dark, PartialPalette::default(), None);
stated.titlebar_height = Some(px(32.));
assert_eq!(resolve(&stated, None, None).titlebar_height, px(32.));
}
#[test]
fn a_stated_root_font_size_scales_the_size_table() {
// macOS states 13pt; the medium control shrinks to native proportions.
+1
View File
@@ -79,6 +79,7 @@ impl KdeScheme {
palette: self.palette,
control_radius: None,
input_height: None,
titlebar_height: None,
root_font_size: None,
accessibility,
source: SourceKind::Kde,
+2
View File
@@ -142,6 +142,7 @@ impl LinuxSource {
palette: PartialPalette::default(),
control_radius: None,
input_height: None,
titlebar_height: None,
root_font_size: None,
accessibility,
source: SourceKind::Gnome,
@@ -154,6 +155,7 @@ impl LinuxSource {
palette: PartialPalette::default(),
control_radius: None,
input_height: None,
titlebar_height: None,
root_font_size: None,
accessibility,
source: SourceKind::Gnome,
+1
View File
@@ -113,6 +113,7 @@ impl ThemeSource for MacosSource {
palette,
control_radius: Some(gpui::px(CONTROL_RADIUS_PTS)),
input_height: Some(gpui::px(INPUT_HEIGHT_PTS)),
titlebar_height: None,
root_font_size: Some(gpui::px(ROOT_FONT_SIZE_PTS)),
accessibility,
source: SourceKind::Macos,
+1
View File
@@ -62,6 +62,7 @@ impl OmarchyTheme {
palette: self.palette,
control_radius: None,
input_height: None,
titlebar_height: None,
root_font_size: None,
accessibility,
source: SourceKind::Omarchy,
+3
View File
@@ -16,6 +16,8 @@ use crate::system::{AccessibilityPreferences, PartialPalette, SourceKind, System
const CONTROL_RADIUS_PX: f32 = 4.0;
/// WinUI 11's default text-box height, in pixels at 100% scaling.
const INPUT_HEIGHT_PX: f32 = 32.0;
/// The window caption's height, in pixels at 100% scaling, as Win32 reports it.
const TITLEBAR_HEIGHT_PX: f32 = 32.0;
/// WinUI 11's default body text size, in pixels at 100% scaling.
const ROOT_FONT_SIZE_PX: f32 = 14.0;
@@ -158,6 +160,7 @@ impl ThemeSource for WindowsSource {
},
control_radius: Some(gpui::px(CONTROL_RADIUS_PX)),
input_height: Some(gpui::px(INPUT_HEIGHT_PX)),
titlebar_height: Some(gpui::px(TITLEBAR_HEIGHT_PX)),
root_font_size: Some(gpui::px(ROOT_FONT_SIZE_PX * text_scale as f32)),
accessibility: self.accessibility(),
source: SourceKind::Windows,
+3
View File
@@ -78,6 +78,8 @@ pub struct SystemTheme {
pub control_radius: Option<Pixels>,
/// The platform's stated text-field height, if it has one.
pub input_height: Option<Pixels>,
/// The platform's native titlebar height, if it states one.
pub titlebar_height: Option<Pixels>,
/// The platform's native root font size, if it has one.
pub root_font_size: Option<Pixels>,
pub accessibility: AccessibilityPreferences,
@@ -92,6 +94,7 @@ impl SystemTheme {
palette: PartialPalette::default(),
control_radius: None,
input_height: None,
titlebar_height: None,
root_font_size: None,
accessibility: AccessibilityPreferences::default(),
source: SourceKind::Fallback,