platform_windows.rs

  1use gpui::{Hsla, Rgba, WindowControlArea, prelude::*};
  2
  3use ui::prelude::*;
  4
  5#[derive(IntoElement)]
  6pub struct WindowsWindowControls {
  7    button_height: Pixels,
  8}
  9
 10impl WindowsWindowControls {
 11    pub const fn new(button_height: Pixels) -> Self {
 12        Self { button_height }
 13    }
 14
 15    #[cfg(not(target_os = "windows"))]
 16    const fn get_font() -> &'static str {
 17        "Segoe Fluent Icons"
 18    }
 19
 20    #[cfg(target_os = "windows")]
 21    fn get_font() -> &'static str {
 22        use windows::Wdk::System::SystemServices::RtlGetVersion;
 23
 24        let mut version = unsafe { std::mem::zeroed() };
 25        let status = unsafe { RtlGetVersion(&mut version) };
 26
 27        if status.is_ok() && version.dwBuildNumber >= 22000 {
 28            "Segoe Fluent Icons"
 29        } else {
 30            "Segoe MDL2 Assets"
 31        }
 32    }
 33}
 34
 35impl RenderOnce for WindowsWindowControls {
 36    fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
 37        let close_button_hover_color = Rgba {
 38            r: 232.0 / 255.0,
 39            g: 17.0 / 255.0,
 40            b: 32.0 / 255.0,
 41            a: 1.0,
 42        };
 43
 44        let button_hover_color = cx.theme().colors().ghost_element_hover;
 45        let button_active_color = cx.theme().colors().ghost_element_active;
 46
 47        div()
 48            .id("windows-window-controls")
 49            .font_family(Self::get_font())
 50            .flex()
 51            .flex_row()
 52            .justify_center()
 53            .content_stretch()
 54            .max_h(self.button_height)
 55            .min_h(self.button_height)
 56            .child(WindowsCaptionButton::new(
 57                "minimize",
 58                WindowsCaptionButtonIcon::Minimize,
 59                button_hover_color,
 60                button_active_color,
 61            ))
 62            .child(WindowsCaptionButton::new(
 63                "maximize-or-restore",
 64                if window.is_maximized() {
 65                    WindowsCaptionButtonIcon::Restore
 66                } else {
 67                    WindowsCaptionButtonIcon::Maximize
 68                },
 69                button_hover_color,
 70                button_active_color,
 71            ))
 72            .child(WindowsCaptionButton::new(
 73                "close",
 74                WindowsCaptionButtonIcon::Close,
 75                close_button_hover_color,
 76                button_active_color,
 77            ))
 78    }
 79}
 80
 81#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
 82enum WindowsCaptionButtonIcon {
 83    Minimize,
 84    Restore,
 85    Maximize,
 86    Close,
 87}
 88
 89#[derive(IntoElement)]
 90struct WindowsCaptionButton {
 91    id: ElementId,
 92    icon: WindowsCaptionButtonIcon,
 93    hover_background_color: Hsla,
 94    active_background_color: Hsla,
 95}
 96
 97impl WindowsCaptionButton {
 98    pub fn new(
 99        id: impl Into<ElementId>,
100        icon: WindowsCaptionButtonIcon,
101        hover_background_color: impl Into<Hsla>,
102        active_background_color: impl Into<Hsla>,
103    ) -> Self {
104        Self {
105            id: id.into(),
106            icon,
107            hover_background_color: hover_background_color.into(),
108            active_background_color: active_background_color.into(),
109        }
110    }
111}
112
113impl RenderOnce for WindowsCaptionButton {
114    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
115        h_flex()
116            .id(self.id)
117            .justify_center()
118            .content_center()
119            .occlude()
120            .w(px(36.))
121            .h_full()
122            .text_size(px(10.0))
123            .hover(|style| style.bg(self.hover_background_color))
124            .active(|style| style.bg(self.active_background_color))
125            .map(|this| match self.icon {
126                WindowsCaptionButtonIcon::Close => {
127                    this.window_control_area(WindowControlArea::Close)
128                }
129                WindowsCaptionButtonIcon::Maximize | WindowsCaptionButtonIcon::Restore => {
130                    this.window_control_area(WindowControlArea::Max)
131                }
132                WindowsCaptionButtonIcon::Minimize => {
133                    this.window_control_area(WindowControlArea::Min)
134                }
135            })
136            .child(match self.icon {
137                WindowsCaptionButtonIcon::Minimize => "\u{e921}",
138                WindowsCaptionButtonIcon::Restore => "\u{e923}",
139                WindowsCaptionButtonIcon::Maximize => "\u{e922}",
140                WindowsCaptionButtonIcon::Close => "\u{e8bb}",
141            })
142    }
143}