From fc45f6e04273bc22d02e431b84e9af347554bf0a Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 30 Dec 2025 23:17:17 +0800 Subject: [PATCH] title_bar: Fix close button hover color on Windows (#45867) Release Notes: - Fix close button hover text color on Windows | Before | After | | --- | --- | | before |after | https://github.com/user-attachments/assets/27e88bf1-eddd-4ec8-a360-6a68eef484e0 And I also improved this file's implementation to merge the `WindowsCaptionButtonIcon` into `WindowsCaptionButton`. --- .../src/platforms/platform_windows.rs | 142 +++++++++--------- 1 file changed, 68 insertions(+), 74 deletions(-) diff --git a/crates/title_bar/src/platforms/platform_windows.rs b/crates/title_bar/src/platforms/platform_windows.rs index 1df75ee8a9b3d2716e79f9a632b79e8c6df739c0..4b882c827570001589e510399bdc438262f3a178 100644 --- a/crates/title_bar/src/platforms/platform_windows.rs +++ b/crates/title_bar/src/platforms/platform_windows.rs @@ -33,17 +33,7 @@ impl WindowsWindowControls { } impl RenderOnce for WindowsWindowControls { - fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { - let close_button_hover_color = Rgba { - r: 232.0 / 255.0, - g: 17.0 / 255.0, - b: 32.0 / 255.0, - a: 1.0, - }; - - let button_hover_color = cx.theme().colors().ghost_element_hover; - let button_active_color = cx.theme().colors().ghost_element_active; - + fn render(self, window: &mut Window, _: &mut App) -> impl IntoElement { div() .id("windows-window-controls") .font_family(Self::get_font()) @@ -53,91 +43,95 @@ impl RenderOnce for WindowsWindowControls { .content_stretch() .max_h(self.button_height) .min_h(self.button_height) - .child(WindowsCaptionButton::new( - "minimize", - WindowsCaptionButtonIcon::Minimize, - button_hover_color, - button_active_color, - )) - .child(WindowsCaptionButton::new( - "maximize-or-restore", - if window.is_maximized() { - WindowsCaptionButtonIcon::Restore + .child(WindowsCaptionButton::Minimize) + .map(|this| { + this.child(if window.is_maximized() { + WindowsCaptionButton::Restore } else { - WindowsCaptionButtonIcon::Maximize - }, - button_hover_color, - button_active_color, - )) - .child(WindowsCaptionButton::new( - "close", - WindowsCaptionButtonIcon::Close, - close_button_hover_color, - button_active_color, - )) + WindowsCaptionButton::Maximize + }) + }) + .child(WindowsCaptionButton::Close) } } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] -enum WindowsCaptionButtonIcon { +#[derive(IntoElement)] +enum WindowsCaptionButton { Minimize, Restore, Maximize, Close, } -#[derive(IntoElement)] -struct WindowsCaptionButton { - id: ElementId, - icon: WindowsCaptionButtonIcon, - hover_background_color: Hsla, - active_background_color: Hsla, -} - impl WindowsCaptionButton { - pub fn new( - id: impl Into, - icon: WindowsCaptionButtonIcon, - hover_background_color: impl Into, - active_background_color: impl Into, - ) -> Self { - Self { - id: id.into(), - icon, - hover_background_color: hover_background_color.into(), - active_background_color: active_background_color.into(), + #[inline] + fn id(&self) -> &'static str { + match self { + Self::Minimize => "minimize", + Self::Restore => "restore", + Self::Maximize => "maximize", + Self::Close => "close", + } + } + + #[inline] + fn icon(&self) -> &'static str { + match self { + Self::Minimize => "\u{e921}", + Self::Restore => "\u{e923}", + Self::Maximize => "\u{e922}", + Self::Close => "\u{e8bb}", + } + } + + #[inline] + fn control_area(&self) -> WindowControlArea { + match self { + Self::Close => WindowControlArea::Close, + Self::Maximize | Self::Restore => WindowControlArea::Max, + Self::Minimize => WindowControlArea::Min, } } } impl RenderOnce for WindowsCaptionButton { - fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement { + fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { + let (hover_bg, hover_fg, active_bg, active_fg) = match self { + Self::Close => { + let color: Hsla = Rgba { + r: 232.0 / 255.0, + g: 17.0 / 255.0, + b: 32.0 / 255.0, + a: 1.0, + } + .into(); + + ( + color, + gpui::white(), + color.opacity(0.8), + gpui::white().opacity(0.8), + ) + } + _ => ( + cx.theme().colors().ghost_element_hover, + cx.theme().colors().text, + cx.theme().colors().ghost_element_active, + cx.theme().colors().text, + ), + }; + h_flex() - .id(self.id) + .id(self.id()) .justify_center() .content_center() .occlude() .w(px(36.)) .h_full() .text_size(px(10.0)) - .hover(|style| style.bg(self.hover_background_color)) - .active(|style| style.bg(self.active_background_color)) - .map(|this| match self.icon { - WindowsCaptionButtonIcon::Close => { - this.window_control_area(WindowControlArea::Close) - } - WindowsCaptionButtonIcon::Maximize | WindowsCaptionButtonIcon::Restore => { - this.window_control_area(WindowControlArea::Max) - } - WindowsCaptionButtonIcon::Minimize => { - this.window_control_area(WindowControlArea::Min) - } - }) - .child(match self.icon { - WindowsCaptionButtonIcon::Minimize => "\u{e921}", - WindowsCaptionButtonIcon::Restore => "\u{e923}", - WindowsCaptionButtonIcon::Maximize => "\u{e922}", - WindowsCaptionButtonIcon::Close => "\u{e8bb}", - }) + .hover(|style| style.bg(hover_bg).text_color(hover_fg)) + .active(|style| style.bg(active_bg).text_color(active_fg)) + .window_control_area(self.control_area()) + .child(self.icon()) } }