Skip to main content

xgpui_shell/
controls.rs

1//! Replaceable artwork for shell-drawn window controls.
2//!
3//! The shell keeps control order, availability, capability filtering, window
4//! state, accessible names, keyboard/pointer activation, drag isolation and the
5//! keyboard focus ring. A [`ShellControlPresenter`] supplies everything drawn
6//! inside the control: background, icon, size of the icon and state treatment.
7use crate::ShellColors;
8use gpui::{AnyElement, App, Pixels, Window, WindowAppearance};
9use std::{fmt, rc::Rc};
10
11/// A window control drawn by the shell.
12///
13/// `Restore` replaces `Maximize` while the window is maximized; both dispatch
14/// the same maximize/restore operation.
15#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
16#[non_exhaustive]
17pub enum ShellControl {
18    Minimize,
19    Maximize,
20    Restore,
21    Close,
22}
23
24impl ShellControl {
25    /// The accessible name the shell gives this control.
26    pub fn accessible_label(self) -> &'static str {
27        match self {
28            Self::Minimize => "Minimize window",
29            Self::Maximize => "Maximize window",
30            Self::Restore => "Restore window",
31            Self::Close => "Close window",
32        }
33    }
34}
35
36/// Everything a presenter may use to draw one control.
37///
38/// New fields may be added in minor releases; read the fields you need.
39#[derive(Clone, Debug, PartialEq)]
40#[non_exhaustive]
41pub struct ShellControlState {
42    /// Which control to draw.
43    pub control: ShellControl,
44    /// The pointer is over the control (or hover is simulated in a preview).
45    pub hovered: bool,
46    /// The primary button is held down on the control.
47    pub pressed: bool,
48    /// Keyboard focus is visible on the control (or simulated in a preview).
49    /// The shell already paints a focus ring; use this only for extra treatment.
50    pub focused: bool,
51    /// The window is active.
52    pub window_active: bool,
53    /// Light or dark appearance used for the frame.
54    pub appearance: WindowAppearance,
55    /// High contrast is in effect. Presenters should switch to high-contrast
56    /// artwork; `colors` already holds the shell's high-contrast tokens.
57    pub high_contrast: bool,
58    /// The frame's resolved colors for this appearance and activation.
59    pub colors: ShellColors,
60    /// The focus-ring color the shell uses (0xRRGGBB).
61    pub focus_color: u32,
62    /// Logical text/target scale (0.5–4), independent of device DPI.
63    pub scale: f32,
64    /// Side of the square clickable target. Presenter content is centered in it
65    /// and clipped to it; draw the icon smaller to keep a comfortable target.
66    pub target_size: Pixels,
67    /// Drawn in an inert [`crate::ClientFramePreview`], not a real window.
68    pub preview: bool,
69}
70
71type Render = dyn Fn(&ShellControlState, &mut Window, &mut App) -> AnyElement;
72
73/// App-supplied artwork for shell-drawn window controls.
74///
75/// Called once per visible control per frame. Return ordinary GPUI elements,
76/// including `svg()` assets; don't attach click handlers, since activation,
77/// keyboard handling and accessibility stay with the shell.
78#[derive(Clone)]
79pub struct ShellControlPresenter(Rc<Render>);
80
81impl ShellControlPresenter {
82    pub fn new(
83        render: impl Fn(&ShellControlState, &mut Window, &mut App) -> AnyElement + 'static,
84    ) -> Self {
85        Self(Rc::new(render))
86    }
87
88    pub(crate) fn render(
89        &self,
90        state: &ShellControlState,
91        window: &mut Window,
92        cx: &mut App,
93    ) -> AnyElement {
94        (self.0)(state, window, cx)
95    }
96}
97
98impl fmt::Debug for ShellControlPresenter {
99    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        f.write_str("ShellControlPresenter")
101    }
102}