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}