use gpui::prelude::FluentBuilder; use gpui::{ div, px, App, ElementId, Hsla, InteractiveElement, IntoElement, ParentElement, Pixels, RenderOnce, Rgba, StatefulInteractiveElement, Styled, Window, WindowControlArea, }; use theme::ActiveTheme; use ui::h_flex; #[derive(IntoElement)] pub struct WindowsWindowControls { button_height: Pixels, } impl WindowsWindowControls { pub fn new(button_height: Pixels) -> Self { Self { button_height } } #[cfg(not(target_os = "windows"))] fn get_font() -> &'static str { "Segoe Fluent Icons" } #[cfg(target_os = "windows")] fn get_font() -> &'static str { use windows::Wdk::System::SystemServices::RtlGetVersion; let mut version = unsafe { std::mem::zeroed() }; let status = unsafe { RtlGetVersion(&mut version) }; if status.is_ok() && version.dwBuildNumber >= 22000 { "Segoe Fluent Icons" } else { "Segoe MDL2 Assets" } } } 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().ghost_element_hover; let button_active_color = cx.theme().ghost_element_active; div() .id("windows-window-controls") .font_family(Self::get_font()) .flex() .flex_row() .justify_center() .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 } else { WindowsCaptionButtonIcon::Maximize }, button_hover_color, button_active_color, )) .child(WindowsCaptionButton::new( "close", WindowsCaptionButtonIcon::Close, close_button_hover_color, button_active_color, )) } } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] enum WindowsCaptionButtonIcon { 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(), } } } impl RenderOnce for WindowsCaptionButton { fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement { h_flex() .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}", }) } }