Skip to main content

jay_config/
theme.rs

1//! Tools for configuring the look of the compositor.
2
3use crate::_private::WindowThemeKind;
4use crate::theme::colors::Colorable;
5use crate::theme::sized::Resizable;
6use crate::window::Window;
7use jay_proc::PrivateEnum;
8use serde::Deserialize;
9use serde::Serialize;
10use std::ops::Deref;
11
12/// A color.
13///
14/// When specifying RGBA values of a color, the RGB values can either be specified
15/// *straight* or *premultiplied*. Premultiplied means that the RGB values have already
16/// been multiplied by the alpha value.
17///
18/// Given a color, to reduce its opacity by half,
19///
20/// - if you're working with premultiplied values, you would multiply each component by `0.5`;
21/// - if you're working with straight values, you would multiply only the alpha component by `0.5`.
22///
23/// When using hexadecimal notation, `#RRGGBBAA`, the RGB values are usually straight.
24// values are stored premultiplied
25#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
26pub struct Color {
27    r: f32,
28    g: f32,
29    b: f32,
30    a: f32,
31}
32
33fn to_f32(c: u8) -> f32 {
34    c as f32 / 255f32
35}
36
37fn to_u8(c: f32) -> u8 {
38    (c * 255f32) as u8
39}
40
41fn validate_f32(f: f32) -> bool {
42    f >= 0.0 && f <= 1.0
43}
44
45fn validate_f32_all(f: [f32; 4]) -> bool {
46    if !f.into_iter().all(validate_f32) {
47        log::warn!(
48            "f32 values {:?} are not in the valid color range. Using solid black instead xyz",
49            f
50        );
51        return false;
52    }
53    true
54}
55
56impl Color {
57    /// Solid black.
58    pub const BLACK: Self = Self {
59        r: 0.0,
60        g: 0.0,
61        b: 0.0,
62        a: 1.0,
63    };
64
65    /// Creates a new color from `u8` RGB values.
66    pub fn new(r: u8, g: u8, b: u8) -> Self {
67        Self {
68            r: to_f32(r),
69            g: to_f32(g),
70            b: to_f32(b),
71            a: 1.0,
72        }
73    }
74
75    /// Creates a new color from straight `u8` RGBA values.
76    pub fn new_straight(r: u8, g: u8, b: u8, a: u8) -> Self {
77        Self::new_f32_straight(to_f32(r), to_f32(g), to_f32(b), to_f32(a))
78    }
79
80    /// Creates a new color from premultiplied `f32` RGBA values.
81    pub fn new_f32_premultiplied(r: f32, g: f32, b: f32, a: f32) -> Self {
82        if !validate_f32_all([r, g, b, a]) {
83            Self::BLACK
84        } else if r > a || g > a || b > a {
85            log::warn!(
86                "f32 values {:?} are not valid for a premultiplied color. Using solid black instead.",
87                [r, g, b, a]
88            );
89            Self::BLACK
90        } else {
91            Self { r, g, b, a }
92        }
93    }
94
95    /// Creates a new color from straight `f32` RGBA values.
96    pub fn new_f32_straight(r: f32, g: f32, b: f32, a: f32) -> Self {
97        if !validate_f32_all([r, g, b, a]) {
98            Self::BLACK
99        } else {
100            Self {
101                r: r * a,
102                g: g * a,
103                b: b * a,
104                a,
105            }
106        }
107    }
108
109    /// Creates a new color from `f32` RGB values.
110    pub fn new_f32(r: f32, g: f32, b: f32) -> Self {
111        Self { r, g, b, a: 1.0 }
112    }
113
114    /// Converts the color to its premultiplied `f32` RGBA values.
115    pub fn to_f32_premultiplied(&self) -> [f32; 4] {
116        [self.r, self.g, self.b, self.a]
117    }
118
119    /// Converts the color to its straight `f32` RGBA values.
120    pub fn to_f32_straight(&self) -> [f32; 4] {
121        if self.a == 0.0 {
122            [0.0, 0.0, 0.0, 0.0]
123        } else {
124            let a = self.a;
125            [self.r / a, self.g / a, self.b / a, a]
126        }
127    }
128
129    /// Converts the color to its straight `u8` RGBA values.
130    pub fn to_u8_straight(&self) -> [u8; 4] {
131        let [r, g, b, a] = self.to_f32_straight();
132        [to_u8(r), to_u8(g), to_u8(b), to_u8(a)]
133    }
134}
135
136/// Resets all sizes to their defaults.
137pub fn reset_sizes() {
138    get!().reset_sizes();
139}
140
141/// Resets all colors to their defaults.
142pub fn reset_colors() {
143    get!().reset_colors();
144}
145
146/// Returns the current font.
147pub fn get_font() -> String {
148    get!().get_font()
149}
150
151/// Sets the font.
152///
153/// Default: `monospace 8`.
154///
155/// See also [`set_bar_font`] and [`set_title_font`].
156///
157/// The font name should be specified in [pango][pango] syntax.
158///
159/// [pango]: https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html
160pub fn set_font(font: &str) {
161    get!().set_font(font)
162}
163
164/// Sets the font used by the bar.
165///
166/// If this function is not called, the font set by [`set_font`] is used. See that
167/// function for more details.
168pub fn set_bar_font(font: &str) {
169    get!().set_bar_font(font)
170}
171
172/// Sets the font used by window titles.
173///
174/// If this function is not called, the font set by [`set_font`] is used. See that
175/// function for more details.
176pub fn set_title_font(font: &str) {
177    get!().set_title_font(font)
178}
179
180/// Resets the fonts to the defaults.
181///
182/// Currently the default is `monospace 8`.
183pub fn reset_font() {
184    get!().reset_font()
185}
186
187#[non_exhaustive]
188#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Default, PrivateEnum)]
189pub enum BarPosition {
190    #[default]
191    Top,
192    Bottom,
193}
194
195/// Sets the position of the bar.
196///
197/// Default: `Top`.
198pub fn set_bar_position(position: BarPosition) {
199    get!().set_bar_position(position.to_private());
200}
201
202/// Gets the position of the bar.
203pub fn get_bar_position() -> BarPosition {
204    get!(BarPosition::Top).get_bar_position().to_public()
205}
206
207#[non_exhaustive]
208#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Default, PrivateEnum)]
209pub enum ContainerBorders {
210    /// Only separators are drawn between children.
211    #[default]
212    Separators,
213    /// A border is drawn around the entire container.
214    Full,
215    /// A border is drawn around the entire container, in addition to the separators
216    /// between children, unless the container has only one child and is the root
217    /// container of the workspace.
218    FullSmart,
219}
220
221/// Sets the container border style.
222///
223/// Default: `Separators`.
224pub fn set_container_borders(borders: ContainerBorders) {
225    get!().set_container_borders(borders.to_private());
226}
227
228/// Gets the container border style.
229pub fn get_container_borders() -> ContainerBorders {
230    get!(ContainerBorders::Separators)
231        .get_container_borders()
232        .to_public()
233}
234
235/// Sets the proportional fonts used by egui windows.
236///
237/// The default is `["sans-serif", "Noto Sans", "Noto Color Emoji"]`.
238pub fn set_egui_proportional_fonts<'a>(fonts: impl IntoIterator<Item = &'a str>) {
239    get!().set_egui_fonts(Some(fonts.into_iter().collect()), None);
240}
241
242/// Sets the monospace fonts used by egui windows.
243///
244/// The default is `["monospace", "Noto Sans Mono", "Noto Color Emoji"]`.
245pub fn set_egui_monospace_fonts<'a>(fonts: impl IntoIterator<Item = &'a str>) {
246    get!().set_egui_fonts(None, Some(fonts.into_iter().collect()));
247}
248
249/// Sets whether window icons set by the client are shown.
250///
251/// The default is `true`.
252pub fn set_show_window_icons(show: bool) {
253    get!().set_show_window_icons(show);
254}
255
256/// Sets whether window icons set by the client are rendered as grayscale.
257///
258/// This is only supported on the Vulkan renderer.
259///
260/// The default is `false`.
261pub fn set_window_icons_grayscale(grayscale: bool) {
262    get!().set_window_icons_grayscale(grayscale);
263}
264
265/// Theme overrides of a window or container.
266///
267/// This type implements the functionality shared by [`WindowTheme`] and
268/// [`ContainerTheme`]. Both dereference to this type. See their documentation for the
269/// supported settings.
270#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
271pub struct ThemeOverrides {
272    pub(crate) window: Window,
273    pub(crate) kind: WindowThemeKind,
274}
275
276impl ThemeOverrides {
277    /// Returns the window that the overrides belong to.
278    pub fn window(&self) -> Window {
279        self.window
280    }
281
282    /// Removes all overrides.
283    pub fn reset(&self) {
284        get!().reset_window_theme(self.window, self.kind);
285    }
286
287    /// Sets the color of a GUI element.
288    pub fn set_color(&self, element: Colorable, color: Color) {
289        get!().set_window_theme_color(self.window, self.kind, element, Some(color));
290    }
291
292    /// Removes the color override of a GUI element.
293    ///
294    /// See also [`set_color`](Self::set_color).
295    pub fn unset_color(&self, element: Colorable) {
296        get!().set_window_theme_color(self.window, self.kind, element, None);
297    }
298
299    /// Gets the color override of a GUI element.
300    pub fn get_color(&self, element: Colorable) -> Option<Color> {
301        get!().get_window_theme_color(self.window, self.kind, element)
302    }
303
304    /// Sets the size of a GUI element.
305    pub fn set_size(&self, element: Resizable, size: i32) {
306        get!().set_window_theme_size(self.window, self.kind, element, Some(size));
307    }
308
309    /// Removes the size override of a GUI element.
310    ///
311    /// See also [`set_size`](Self::set_size).
312    pub fn unset_size(&self, element: Resizable) {
313        get!().set_window_theme_size(self.window, self.kind, element, None);
314    }
315
316    /// Gets the size override of a GUI element.
317    pub fn get_size(&self, element: Resizable) -> Option<i32> {
318        get!().get_window_theme_size(self.window, self.kind, element)
319    }
320
321    /// Sets whether titles are shown.
322    ///
323    /// See also [`set_show_titles`](crate::set_show_titles).
324    pub fn set_show_titles(&self, show: bool) {
325        get!().set_window_theme_show_titles(self.window, self.kind, Some(show));
326    }
327
328    /// Removes the override of whether titles are shown.
329    ///
330    /// See also [`set_show_titles`](Self::set_show_titles).
331    pub fn unset_show_titles(&self) {
332        get!().set_window_theme_show_titles(self.window, self.kind, None);
333    }
334
335    /// Gets the override of whether titles are shown.
336    pub fn get_show_titles(&self) -> Option<bool> {
337        get!().get_window_theme_show_titles(self.window, self.kind)
338    }
339
340    /// Sets whether window icons set by the client are shown.
341    ///
342    /// See also [`set_show_window_icons`].
343    pub fn set_show_window_icons(&self, show: bool) {
344        get!().set_window_theme_show_window_icons(self.window, self.kind, Some(show));
345    }
346
347    /// Removes the override of whether window icons set by the client are shown.
348    ///
349    /// See also [`set_show_window_icons`](Self::set_show_window_icons).
350    pub fn unset_show_window_icons(&self) {
351        get!().set_window_theme_show_window_icons(self.window, self.kind, None);
352    }
353
354    /// Sets whether window icons set by the client are rendered as grayscale.
355    ///
356    /// See also [`set_window_icons_grayscale`].
357    pub fn set_window_icons_grayscale(&self, grayscale: bool) {
358        get!().set_window_theme_window_icons_grayscale(self.window, self.kind, Some(grayscale));
359    }
360
361    /// Removes the override of whether window icons set by the client are rendered as
362    /// grayscale.
363    ///
364    /// See also [`set_window_icons_grayscale`](Self::set_window_icons_grayscale).
365    pub fn unset_window_icons_grayscale(&self) {
366        get!().set_window_theme_window_icons_grayscale(self.window, self.kind, None);
367    }
368
369    /// Sets the font used by window titles.
370    ///
371    /// See also [`set_title_font`].
372    pub fn set_title_font(&self, font: &str) {
373        get!().set_window_theme_title_font(self.window, self.kind, Some(font));
374    }
375
376    /// Removes the override of the font used by window titles.
377    ///
378    /// See also [`set_title_font`](Self::set_title_font).
379    pub fn unset_title_font(&self) {
380        get!().set_window_theme_title_font(self.window, self.kind, None);
381    }
382}
383
384/// Theme overrides of a window.
385///
386/// This object is returned by [`Window::theme`]. It contains the theme of the window
387/// itself. How a container decorates its children is configured with
388/// [`ContainerTheme`].
389///
390/// Settings that are not set fall back to the theme of the parent container, if any, and
391/// then to the global theme. Not every setting has an effect on every window.
392#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
393pub struct WindowTheme(pub(crate) ThemeOverrides);
394
395impl Deref for WindowTheme {
396    type Target = ThemeOverrides;
397
398    fn deref(&self) -> &Self::Target {
399        &self.0
400    }
401}
402
403const _: () = {
404    use colors::*;
405    use sized::*;
406
407    impl WindowTheme {
408        /// Sets the color of a GUI element.
409        ///
410        /// Floating windows use the following elements. This theme takes priority over the
411        /// global theme.
412        ///
413        /// - [`BORDER_COLOR`]
414        /// - [`FOCUSED_BORDER_COLOR`]
415        /// - [`SEPARATOR_COLOR`]
416        /// - [`UNFOCUSED_TITLE_BACKGROUND_COLOR`]
417        /// - [`FOCUSED_TITLE_BACKGROUND_COLOR`]
418        /// - [`ATTENTION_REQUESTED_BACKGROUND_COLOR`]
419        /// - [`UNFOCUSED_TITLE_TEXT_COLOR`]
420        /// - [`FOCUSED_TITLE_TEXT_COLOR`]
421        ///
422        /// Tiled windows use the following elements. This theme takes priority over the
423        /// [`ContainerTheme`] of the parent container, which takes priority over the global
424        /// theme.
425        ///
426        /// - [`FOCUSED_BORDER_COLOR`]
427        /// - [`BORDER_COLOR`]: only used as the default of `FOCUSED_BORDER_COLOR`. The
428        ///   other borders use the border color of the container.
429        /// - [`UNFOCUSED_TITLE_BACKGROUND_COLOR`]
430        /// - [`FOCUSED_TITLE_BACKGROUND_COLOR`]
431        /// - [`FOCUSED_INACTIVE_TITLE_BACKGROUND_COLOR`]
432        /// - [`ATTENTION_REQUESTED_BACKGROUND_COLOR`]
433        /// - [`UNFOCUSED_TITLE_TEXT_COLOR`]
434        /// - [`FOCUSED_TITLE_TEXT_COLOR`]
435        /// - [`FOCUSED_INACTIVE_TITLE_TEXT_COLOR`]
436        ///
437        /// For tiled windows, the separator color is a property of the container and is set
438        /// with [`ContainerTheme::set_color`].
439        pub fn set_color(&self, element: Colorable, color: Color) {
440            self.0.set_color(element, color)
441        }
442
443        /// Sets the size of a GUI element.
444        ///
445        /// The following elements are supported:
446        ///
447        /// - [`TITLE_HEIGHT`]
448        /// - [`BORDER_WIDTH`]
449        ///
450        /// They are only used for floating windows. This theme takes priority over the
451        /// global theme. For tiled windows, these sizes are properties of the container and
452        /// are set with [`ContainerTheme::set_size`].
453        pub fn set_size(&self, element: Resizable, size: i32) {
454            self.0.set_size(element, size)
455        }
456
457        /// Sets whether titles are shown.
458        ///
459        /// This is only used for floating windows. This theme takes priority over the global
460        /// theme. For tiled windows, this is a property of the container and is set with
461        /// [`ContainerTheme::set_show_titles`].
462        ///
463        /// See also [`set_show_titles`](crate::set_show_titles).
464        pub fn set_show_titles(&self, show: bool) {
465            self.0.set_show_titles(show)
466        }
467
468        /// Sets whether window icons set by the client are shown.
469        ///
470        /// For floating windows, this theme takes priority over the global theme. For tiled
471        /// windows, this theme takes priority over the [`ContainerTheme`] of the parent
472        /// container, which takes priority over the global theme.
473        ///
474        /// See also [`set_show_window_icons`].
475        pub fn set_show_window_icons(&self, show: bool) {
476            self.0.set_show_window_icons(show)
477        }
478
479        /// Sets whether window icons set by the client are rendered as grayscale.
480        ///
481        /// For floating windows, this theme takes priority over the global theme. For tiled
482        /// windows, this theme takes priority over the [`ContainerTheme`] of the parent
483        /// container, which takes priority over the global theme.
484        ///
485        /// See also [`set_window_icons_grayscale`].
486        pub fn set_window_icons_grayscale(&self, grayscale: bool) {
487            self.0.set_window_icons_grayscale(grayscale)
488        }
489
490        /// Sets the font used by window titles.
491        ///
492        /// For floating windows, this theme takes priority over the global theme. For tiled
493        /// windows, this theme takes priority over the [`ContainerTheme`] of the parent
494        /// container, which takes priority over the global theme.
495        ///
496        /// See also [`set_title_font`].
497        pub fn set_title_font(&self, font: &str) {
498            self.0.set_title_font(font)
499        }
500    }
501};
502
503/// Theme overrides of how a container decorates its children.
504///
505/// This object is returned by [`Window::container_theme`]. It has no effect if the
506/// window is not a container.
507///
508/// Settings that are not set fall back to the global theme. Not every setting has an
509/// effect on every container.
510#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
511pub struct ContainerTheme(pub(crate) ThemeOverrides);
512
513impl Deref for ContainerTheme {
514    type Target = ThemeOverrides;
515
516    fn deref(&self) -> &Self::Target {
517        &self.0
518    }
519}
520
521const _: () = {
522    use colors::*;
523    use sized::*;
524
525    impl ContainerTheme {
526        /// Sets the color of a GUI element.
527        ///
528        /// The following elements apply to the container as a whole. This theme takes
529        /// priority over the global theme.
530        ///
531        /// - [`BORDER_COLOR`]
532        /// - [`SEPARATOR_COLOR`]
533        ///
534        /// The following elements apply to the decorations of each child. The
535        /// [`WindowTheme`] of the child takes priority over this theme, which takes priority
536        /// over the global theme.
537        ///
538        /// - [`FOCUSED_BORDER_COLOR`]
539        /// - [`BORDER_COLOR`]: only used as the default of `FOCUSED_BORDER_COLOR`.
540        /// - [`UNFOCUSED_TITLE_BACKGROUND_COLOR`]
541        /// - [`FOCUSED_TITLE_BACKGROUND_COLOR`]
542        /// - [`FOCUSED_INACTIVE_TITLE_BACKGROUND_COLOR`]
543        /// - [`ATTENTION_REQUESTED_BACKGROUND_COLOR`]
544        /// - [`UNFOCUSED_TITLE_TEXT_COLOR`]
545        /// - [`FOCUSED_TITLE_TEXT_COLOR`]
546        /// - [`FOCUSED_INACTIVE_TITLE_TEXT_COLOR`]
547        pub fn set_color(&self, element: Colorable, color: Color) {
548            self.0.set_color(element, color)
549        }
550
551        /// Sets the size of a GUI element.
552        ///
553        /// The following elements are supported:
554        ///
555        /// - [`TITLE_HEIGHT`]
556        /// - [`BORDER_WIDTH`]
557        ///
558        /// They apply to the container as a whole. This theme takes priority over the global
559        /// theme.
560        pub fn set_size(&self, element: Resizable, size: i32) {
561            self.0.set_size(element, size)
562        }
563
564        /// Sets whether titles are shown.
565        ///
566        /// This applies to the container as a whole. This theme takes priority over the
567        /// global theme.
568        ///
569        /// See also [`set_show_titles`](crate::set_show_titles).
570        pub fn set_show_titles(&self, show: bool) {
571            self.0.set_show_titles(show)
572        }
573
574        /// Sets whether window icons set by the client are shown.
575        ///
576        /// This applies to the decorations of each child. The [`WindowTheme`] of the child
577        /// takes priority over this theme, which takes priority over the global theme.
578        ///
579        /// See also [`set_show_window_icons`].
580        pub fn set_show_window_icons(&self, show: bool) {
581            self.0.set_show_window_icons(show)
582        }
583
584        /// Sets whether window icons set by the client are rendered as grayscale.
585        ///
586        /// This applies to the decorations of each child. The [`WindowTheme`] of the child
587        /// takes priority over this theme, which takes priority over the global theme.
588        ///
589        /// See also [`set_window_icons_grayscale`].
590        pub fn set_window_icons_grayscale(&self, grayscale: bool) {
591            self.0.set_window_icons_grayscale(grayscale)
592        }
593
594        /// Sets the font used by window titles.
595        ///
596        /// This applies to the decorations of each child. The [`WindowTheme`] of the child
597        /// takes priority over this theme, which takes priority over the global theme.
598        ///
599        /// See also [`set_title_font`].
600        pub fn set_title_font(&self, font: &str) {
601            self.0.set_title_font(font)
602        }
603
604        /// Sets the container border style.
605        ///
606        /// This theme takes priority over the global theme.
607        ///
608        /// See also [`set_container_borders`].
609        pub fn set_container_borders(&self, borders: ContainerBorders) {
610            get!().set_window_theme_container_borders(
611                self.0.window,
612                self.0.kind,
613                Some(borders.to_private()),
614            );
615        }
616
617        /// Removes the override of the container border style.
618        ///
619        /// See also [`set_container_borders`](Self::set_container_borders).
620        pub fn unset_container_borders(&self) {
621            get!().set_window_theme_container_borders(self.0.window, self.0.kind, None);
622        }
623
624        /// Gets the override of the container border style.
625        pub fn get_container_borders(&self) -> Option<ContainerBorders> {
626            get!(None)
627                .get_window_theme_container_borders(self.0.window, self.0.kind)
628                .map(|v| v.to_public())
629        }
630    }
631};
632
633/// Elements of the compositor whose color can be changed.
634pub mod colors {
635    #![allow(unused_imports)]
636    use crate::theme::Color;
637    use crate::theme::ContainerBorders;
638    use serde::Deserialize;
639    use serde::Serialize;
640
641    /// An element of the GUI whose color can be changed.
642    #[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
643    pub struct Colorable(#[doc(hidden)] pub u32);
644
645    impl Colorable {
646        /// Sets the color to an RGB value.
647        pub fn set(self, r: u8, g: u8, b: u8) {
648            let color = Color::new(r, g, b);
649            get!().set_color(self, color);
650        }
651
652        /// Sets the color to a `Color` that might contain an alpha component.
653        pub fn set_color(self, color: Color) {
654            get!().set_color(self, color);
655        }
656
657        /// Gets the current color.
658        pub fn get(self) -> Color {
659            get!(Color::BLACK).get_color(self)
660        }
661    }
662
663    macro_rules! colors {
664        ($($(#[$attr:meta])* const $n:expr => $name:ident,)*) => {
665            $(
666                $(#[$attr])*
667                pub const $name: Colorable = Colorable($n);
668            )*
669        }
670    }
671
672    colors! {
673        /// The title background color of an unfocused window.
674        ///
675        /// Default: `#222222`.
676        const 01 => UNFOCUSED_TITLE_BACKGROUND_COLOR,
677        /// The title background color of a focused window.
678        ///
679        /// Default: `#285577`.
680        const 02 => FOCUSED_TITLE_BACKGROUND_COLOR,
681        /// The title background color of an unfocused window that was the last focused
682        /// window in its container.
683        ///
684        /// Default: `#5f676a`.
685        const 03 => FOCUSED_INACTIVE_TITLE_BACKGROUND_COLOR,
686        /// The background color of the desktop.
687        ///
688        /// Default: `#001019`.
689        ///
690        /// You can use an application such as [swaybg][swaybg] to further customize the background.
691        ///
692        /// [swaybg]: https://github.com/swaywm/swaybg
693        const 04 => BACKGROUND_COLOR,
694        /// The background color of the bar.
695        ///
696        /// Default: `#000000`.
697        const 05 => BAR_BACKGROUND_COLOR,
698        /// The color of the 1px separator below window titles.
699        ///
700        /// Default: `#333333`.
701        const 06 => SEPARATOR_COLOR,
702        /// The color of the border between windows.
703        ///
704        /// Default: `#3f474a`.
705        const 07 => BORDER_COLOR,
706        /// The title text color of an unfocused window.
707        ///
708        /// Default: `#888888`.
709        const 08 => UNFOCUSED_TITLE_TEXT_COLOR,
710        /// The title text color of a focused window.
711        ///
712        /// Default: `#ffffff`.
713        const 09 => FOCUSED_TITLE_TEXT_COLOR,
714        /// The title text color of an unfocused window that was the last focused
715        /// window in its container.
716        ///
717        /// Default: `#ffffff`.
718        const 10 => FOCUSED_INACTIVE_TITLE_TEXT_COLOR,
719        /// The color of the status text in the bar.
720        ///
721        /// Default: `#ffffff`.
722        const 11 => BAR_STATUS_TEXT_COLOR,
723        /// The title background color of an unfocused window that might be captured.
724        ///
725        /// Default: `#220303`.
726        const 12 => CAPTURED_UNFOCUSED_TITLE_BACKGROUND_COLOR,
727        /// The title background color of a focused window that might be captured.
728        ///
729        /// Default: `#772831`.
730        const 13 => CAPTURED_FOCUSED_TITLE_BACKGROUND_COLOR,
731        /// The title background color of a window that has requested attention.
732        ///
733        /// Default: `#23092c`.
734        const 14 => ATTENTION_REQUESTED_BACKGROUND_COLOR,
735        /// Color used to highlight parts of the UI.
736        ///
737        /// Default: `#9d28c67f`.
738        const 15 => HIGHLIGHT_COLOR,
739        /// The color of the border between windows where at least one of the windows is
740        /// focused.
741        ///
742        /// For containers, this requires `Full` [`ContainerBorders`].
743        ///
744        /// Default: The `BORDER` color.
745        const 16 => FOCUSED_BORDER_COLOR,
746    }
747
748    /// Sets the color of GUI element.
749    pub fn set_color(element: Colorable, color: Color) {
750        get!().set_color(element, color);
751    }
752
753    /// Gets the color of GUI element.
754    pub fn get_color(element: Colorable) -> Color {
755        get!(Color::BLACK).get_color(element)
756    }
757}
758
759/// Elements of the compositor whose size can be changed.
760pub mod sized {
761    use serde::Deserialize;
762    use serde::Serialize;
763
764    /// An element of the GUI whose size can be changed.
765    #[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
766    pub struct Resizable(#[doc(hidden)] pub u32);
767
768    impl Resizable {
769        /// Gets the current size.
770        pub fn get(self) -> i32 {
771            get!(0).get_size(self)
772        }
773
774        /// Sets the size.
775        pub fn set(self, size: i32) {
776            get!().set_size(self, size)
777        }
778    }
779
780    macro_rules! sizes {
781        ($($(#[$attr:meta])* const $n:expr => $name:ident,)*) => {
782            $(
783                $(#[$attr])*
784                pub const $name: Resizable = Resizable($n);
785            )*
786        }
787    }
788
789    sizes! {
790        /// The height of window titles.
791        ///
792        /// Default: 17
793        const 01 => TITLE_HEIGHT,
794        /// The width of borders between windows.
795        ///
796        /// Default: 4
797        const 02 => BORDER_WIDTH,
798        /// The height of the bar.
799        ///
800        /// Defaults to the TITLE_HEIGHT if not set explicitly.
801        ///
802        /// Default: 17
803        const 03 => BAR_HEIGHT,
804        /// The width of the bar's separator.
805        ///
806        /// Default: 1
807        const 04 => BAR_SEPARATOR_WIDTH,
808    }
809}