diff --git a/CHANGELOG.md b/CHANGELOG.md index cd299bdc..78cfc83e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - **Breaking:** `WindowEvent::CursorMoved` changed to `f64` units, preserving high-precision data supplied by most backends - On Wayland, fix coordinates in mouse events when scale factor isn't 1 - On Web, add the ability to provide a custom canvas +- **Breaking:** On Wayland, the `WaylandTheme` struct has been replaced with a `Theme` trait, allowing for extra configuration # 0.20.0 (2020-01-05) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 0484d71e..12711506 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -2,7 +2,7 @@ use std::{os::raw, ptr, sync::Arc}; -use smithay_client_toolkit::window::{ButtonState, Theme}; +use smithay_client_toolkit::window::{ButtonState as SCTKButtonState, Theme as SCTKTheme}; use crate::{ dpi::Size, @@ -23,74 +23,6 @@ pub use crate::platform_impl::x11; pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported}; -/// Theme for wayland client side decorations -/// -/// Colors must be in ARGB8888 format -pub struct WaylandTheme { - /// Primary color when the window is focused - pub primary_active: [u8; 4], - /// Primary color when the window is unfocused - pub primary_inactive: [u8; 4], - /// Secondary color when the window is focused - pub secondary_active: [u8; 4], - /// Secondary color when the window is unfocused - pub secondary_inactive: [u8; 4], - /// Close button color when hovered over - pub close_button_hovered: [u8; 4], - /// Close button color - pub close_button: [u8; 4], - /// Close button color when hovered over - pub maximize_button_hovered: [u8; 4], - /// Maximize button color - pub maximize_button: [u8; 4], - /// Minimize button color when hovered over - pub minimize_button_hovered: [u8; 4], - /// Minimize button color - pub minimize_button: [u8; 4], -} - -struct WaylandThemeObject(WaylandTheme); - -impl Theme for WaylandThemeObject { - fn get_primary_color(&self, active: bool) -> [u8; 4] { - if active { - self.0.primary_active - } else { - self.0.primary_inactive - } - } - - // Used for division line - fn get_secondary_color(&self, active: bool) -> [u8; 4] { - if active { - self.0.secondary_active - } else { - self.0.secondary_inactive - } - } - - fn get_close_button_color(&self, state: ButtonState) -> [u8; 4] { - match state { - ButtonState::Hovered => self.0.close_button_hovered, - _ => self.0.close_button, - } - } - - fn get_maximize_button_color(&self, state: ButtonState) -> [u8; 4] { - match state { - ButtonState::Hovered => self.0.maximize_button_hovered, - _ => self.0.maximize_button, - } - } - - fn get_minimize_button_color(&self, state: ButtonState) -> [u8; 4] { - match state { - ButtonState::Hovered => self.0.minimize_button_hovered, - _ => self.0.minimize_button, - } - } -} - /// Additional methods on `EventLoopWindowTarget` that are specific to Unix. pub trait EventLoopWindowTargetExtUnix { /// True if the `EventLoopWindowTarget` uses Wayland. @@ -275,7 +207,7 @@ pub trait WindowExtUnix { fn wayland_display(&self) -> Option<*mut raw::c_void>; /// Sets the color theme of the client side window decorations on wayland - fn set_wayland_theme(&self, theme: WaylandTheme); + fn set_wayland_theme(&self, theme: T); /// Check if the window is ready for drawing /// @@ -353,9 +285,9 @@ impl WindowExtUnix for Window { } #[inline] - fn set_wayland_theme(&self, theme: WaylandTheme) { + fn set_wayland_theme(&self, theme: T) { match self.window { - LinuxWindow::Wayland(ref w) => w.set_theme(WaylandThemeObject(theme)), + LinuxWindow::Wayland(ref w) => w.set_theme(WaylandTheme(theme)), _ => {} } } @@ -461,3 +393,96 @@ impl MonitorHandleExtUnix for MonitorHandle { self.inner.native_identifier() } } + +/// Wrapper for implementing SCTK's theme trait. +struct WaylandTheme(T); + +pub trait Theme: Send + 'static { + /// Primary color of the scheme. + fn primary_color(&self, window_active: bool) -> [u8; 4]; + + /// Secondary color of the scheme. + fn secondary_color(&self, window_active: bool) -> [u8; 4]; + + /// Color for the close button. + fn close_button_color(&self, status: ButtonState) -> [u8; 4]; + + /// Icon color for the close button, defaults to the secondary color. + #[allow(unused_variables)] + fn close_button_icon_color(&self, status: ButtonState) -> [u8; 4] { + self.secondary_color(true) + } + + /// Background color for the maximize button. + fn maximize_button_color(&self, status: ButtonState) -> [u8; 4]; + + /// Icon color for the maximize button, defaults to the secondary color. + #[allow(unused_variables)] + fn maximize_button_icon_color(&self, status: ButtonState) -> [u8; 4] { + self.secondary_color(true) + } + + /// Background color for the minimize button. + fn minimize_button_color(&self, status: ButtonState) -> [u8; 4]; + + /// Icon color for the minimize button, defaults to the secondary color. + #[allow(unused_variables)] + fn minimize_button_icon_color(&self, status: ButtonState) -> [u8; 4] { + self.secondary_color(true) + } +} + +impl SCTKTheme for WaylandTheme { + fn get_primary_color(&self, active: bool) -> [u8; 4] { + self.0.primary_color(active) + } + + fn get_secondary_color(&self, active: bool) -> [u8; 4] { + self.0.secondary_color(active) + } + + fn get_close_button_color(&self, status: SCTKButtonState) -> [u8; 4] { + self.0.close_button_color(ButtonState::from_sctk(status)) + } + + fn get_close_button_icon_color(&self, status: SCTKButtonState) -> [u8; 4] { + self.0.close_button_color(ButtonState::from_sctk(status)) + } + + fn get_maximize_button_color(&self, status: SCTKButtonState) -> [u8; 4] { + self.0.maximize_button_color(ButtonState::from_sctk(status)) + } + + fn get_maximize_button_icon_color(&self, status: SCTKButtonState) -> [u8; 4] { + self.0 + .maximize_button_icon_color(ButtonState::from_sctk(status)) + } + + fn get_minimize_button_color(&self, status: SCTKButtonState) -> [u8; 4] { + self.0.minimize_button_color(ButtonState::from_sctk(status)) + } + + fn get_minimize_button_icon_color(&self, status: SCTKButtonState) -> [u8; 4] { + self.0 + .minimize_button_icon_color(ButtonState::from_sctk(status)) + } +} + +pub enum ButtonState { + /// Button is being hovered over by pointer. + Hovered, + /// Button is not being hovered over by pointer. + Idle, + /// Button is disabled. + Disabled, +} + +impl ButtonState { + fn from_sctk(button_state: SCTKButtonState) -> Self { + match button_state { + SCTKButtonState::Hovered => Self::Hovered, + SCTKButtonState::Idle => Self::Idle, + SCTKButtonState::Disabled => Self::Disabled, + } + } +}