From 114e6999d31be0af1c9dce657f672434ba6197e6 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 4 Feb 2024 10:42:05 -0800 Subject: [PATCH] chore: Move parts of window.rs to winit-core As winit no longer owns some of the types this requires some adjustments in the Wayland backend. Signed-off-by: John Nunley --- Cargo.toml | 1 + winit-core/Cargo.toml | 3 +- winit-core/src/lib.rs | 1 + winit-core/src/window.rs | 156 ++++++++++++++++++ winit/Cargo.toml | 2 +- .../linux/wayland/seat/text_input/mod.rs | 1 + .../platform_impl/linux/wayland/window/mod.rs | 20 --- .../linux/wayland/window/state.rs | 24 ++- winit/src/window.rs | 155 +---------------- 9 files changed, 175 insertions(+), 188 deletions(-) create mode 100644 winit-core/src/window.rs diff --git a/Cargo.toml b/Cargo.toml index ecbcbd608..da7f2b1ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ resolver = "2" [workspace.dependencies] bitflags = "2" +cursor-icon = "1.1.0" serde = { version = "1", features = ["serde_derive"] } smol_str = "0.2.0" winit-core = { path = "./winit-core", default-features = false, features = ["std"] } diff --git a/winit-core/Cargo.toml b/winit-core/Cargo.toml index b0d310f17..1fe2249ff 100644 --- a/winit-core/Cargo.toml +++ b/winit-core/Cargo.toml @@ -16,9 +16,10 @@ rust-version = "1.70.0" default = ["std"] std = ["alloc"] alloc = [] -serde = ["dep:serde", "smol_str/serde"] +serde = ["dep:serde", "cursor-icon/serde", "smol_str/serde"] [dependencies] bitflags.workspace = true +cursor-icon.workspace = true serde = { workspace = true, optional = true } smol_str.workspace = true diff --git a/winit-core/src/lib.rs b/winit-core/src/lib.rs index 7b55f9201..b5fb0e3ac 100644 --- a/winit-core/src/lib.rs +++ b/winit-core/src/lib.rs @@ -13,3 +13,4 @@ compile_error! { "no-std and no-alloc usage are not yet supported" } pub mod dpi; pub mod error; pub mod keyboard; +pub mod window; diff --git a/winit-core/src/window.rs b/winit-core/src/window.rs new file mode 100644 index 000000000..6129e79c8 --- /dev/null +++ b/winit-core/src/window.rs @@ -0,0 +1,156 @@ +//! Types used in window construction. + +use cursor_icon::CursorIcon; + +/// The behavior of cursor grabbing. +/// +/// Use this enum with [`Window::set_cursor_grab`] to grab the cursor. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum CursorGrabMode { + /// No grabbing of the cursor is performed. + None, + + /// The cursor is confined to the window area. + /// + /// There's no guarantee that the cursor will be hidden. You should hide it by yourself if you + /// want to do so. + /// + /// ## Platform-specific + /// + /// - **macOS:** Not implemented. Always returns [`ExternalError::NotSupported`] for now. + /// - **iOS / Android / Web / Orbital:** Always returns an [`ExternalError::NotSupported`]. + Confined, + + /// The cursor is locked inside the window area to the certain position. + /// + /// There's no guarantee that the cursor will be hidden. You should hide it by yourself if you + /// want to do so. + /// + /// ## Platform-specific + /// + /// - **X11 / Windows:** Not implemented. Always returns [`ExternalError::NotSupported`] for now. + /// - **iOS / Android / Orbital:** Always returns an [`ExternalError::NotSupported`]. + Locked, +} + +/// Defines the orientation that a window resize will be performed. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum ResizeDirection { + East, + North, + NorthEast, + NorthWest, + South, + SouthEast, + SouthWest, + West, +} + +impl From for CursorIcon { + fn from(direction: ResizeDirection) -> Self { + use ResizeDirection::*; + match direction { + East => CursorIcon::EResize, + North => CursorIcon::NResize, + NorthEast => CursorIcon::NeResize, + NorthWest => CursorIcon::NwResize, + South => CursorIcon::SResize, + SouthEast => CursorIcon::SeResize, + SouthWest => CursorIcon::SwResize, + West => CursorIcon::WResize, + } + } +} + +/// The theme variant to use. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum Theme { + /// Use the light variant. + Light, + + /// Use the dark variant. + Dark, +} + +/// ## Platform-specific +/// +/// - **X11:** Sets the WM's `XUrgencyHint`. No distinction between [`Critical`] and [`Informational`]. +/// +/// [`Critical`]: Self::Critical +/// [`Informational`]: Self::Informational +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +pub enum UserAttentionType { + /// ## Platform-specific + /// + /// - **macOS:** Bounces the dock icon until the application is in focus. + /// - **Windows:** Flashes both the window and the taskbar button until the application is in focus. + Critical, + + /// ## Platform-specific + /// + /// - **macOS:** Bounces the dock icon once. + /// - **Windows:** Flashes the taskbar button until the application is in focus. + #[default] + Informational, +} + +bitflags::bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub struct WindowButtons: u32 { + const CLOSE = 1 << 0; + const MINIMIZE = 1 << 1; + const MAXIMIZE = 1 << 2; + } +} + +/// A window level groups windows with respect to their z-position. +/// +/// The relative ordering between windows in different window levels is fixed. +/// The z-order of a window within the same window level may change dynamically on user interaction. +/// +/// ## Platform-specific +/// +/// - **iOS / Android / Web / Wayland:** Unsupported. +#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] +pub enum WindowLevel { + /// The window will always be below normal windows. + /// + /// This is useful for a widget-based app. + AlwaysOnBottom, + + /// The default. + #[default] + Normal, + + /// The window will always be on top of normal windows. + AlwaysOnTop, +} + +/// Generic IME purposes for use in [`Window::set_ime_purpose`]. +/// +/// The purpose may improve UX by optimizing the IME for the specific use case, +/// if winit can express the purpose to the platform and the platform reacts accordingly. +/// +/// ## Platform-specific +/// +/// - **iOS / Android / Web / Windows / X11 / macOS / Orbital:** Unsupported. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[non_exhaustive] +pub enum ImePurpose { + /// No special hints for the IME (default). + Normal, + /// The IME is used for password input. + Password, + /// The IME is used to input into a terminal. + /// + /// For example, that could alter OSK on Wayland to show extra buttons. + Terminal, +} + +impl Default for ImePurpose { + fn default() -> Self { + Self::Normal + } +} diff --git a/winit/Cargo.toml b/winit/Cargo.toml index 2f83bdec1..8db59ef37 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -62,7 +62,7 @@ cfg_aliases = "0.2.0" [dependencies] bitflags.workspace = true -cursor-icon = "1.1.0" +cursor-icon.workspace = true log = "0.4" mint = { version = "0.5.6", optional = true } once_cell = "1.12" diff --git a/winit/src/platform_impl/linux/wayland/seat/text_input/mod.rs b/winit/src/platform_impl/linux/wayland/seat/text_input/mod.rs index cff18dffe..a74733335 100644 --- a/winit/src/platform_impl/linux/wayland/seat/text_input/mod.rs +++ b/winit/src/platform_impl/linux/wayland/seat/text_input/mod.rs @@ -178,6 +178,7 @@ impl ZwpTextInputV3Ext for ZwpTextInputV3 { ImePurpose::Normal => (ContentHint::None, ContentPurpose::Normal), ImePurpose::Password => (ContentHint::SensitiveData, ContentPurpose::Password), ImePurpose::Terminal => (ContentHint::None, ContentPurpose::Terminal), + _ => unreachable!() }; self.set_content_type(hint, purpose); } diff --git a/winit/src/platform_impl/linux/wayland/window/mod.rs b/winit/src/platform_impl/linux/wayland/window/mod.rs index c6578b6fb..e6472efd5 100644 --- a/winit/src/platform_impl/linux/wayland/window/mod.rs +++ b/winit/src/platform_impl/linux/wayland/window/mod.rs @@ -758,23 +758,3 @@ impl WindowRequests { self.redraw_requested.swap(false, Ordering::Relaxed) } } - -impl TryFrom<&str> for Theme { - type Error = (); - - /// ``` - /// use winit::window::Theme; - /// - /// assert_eq!("dark".try_into(), Ok(Theme::Dark)); - /// assert_eq!("lIghT".try_into(), Ok(Theme::Light)); - /// ``` - fn try_from(theme: &str) -> Result { - if theme.eq_ignore_ascii_case("dark") { - Ok(Self::Dark) - } else if theme.eq_ignore_ascii_case("light") { - Ok(Self::Light) - } else { - Err(()) - } - } -} diff --git a/winit/src/platform_impl/linux/wayland/window/state.rs b/winit/src/platform_impl/linux/wayland/window/state.rs index 4a59a0741..3f8aa7724 100644 --- a/winit/src/platform_impl/linux/wayland/window/state.rs +++ b/winit/src/platform_impl/linux/wayland/window/state.rs @@ -405,7 +405,7 @@ impl WindowState { self.apply_on_poiner(|_, data| { let serial = data.latest_button_serial(); let seat = data.seat(); - xdg_toplevel.resize(seat, serial, direction.into()); + xdg_toplevel.resize(seat, serial, cvt_resize_direction(direction)); }); Ok(()) @@ -1156,18 +1156,16 @@ pub enum FrameCallbackState { Received, } -impl From for XdgResizeEdge { - fn from(value: ResizeDirection) -> Self { - match value { - ResizeDirection::North => XdgResizeEdge::Top, - ResizeDirection::West => XdgResizeEdge::Left, - ResizeDirection::NorthWest => XdgResizeEdge::TopLeft, - ResizeDirection::NorthEast => XdgResizeEdge::TopRight, - ResizeDirection::East => XdgResizeEdge::Right, - ResizeDirection::SouthWest => XdgResizeEdge::BottomLeft, - ResizeDirection::SouthEast => XdgResizeEdge::BottomRight, - ResizeDirection::South => XdgResizeEdge::Bottom, - } +fn cvt_resize_direction(value: ResizeDirection) -> XdgResizeEdge { + match value { + ResizeDirection::North => XdgResizeEdge::Top, + ResizeDirection::West => XdgResizeEdge::Left, + ResizeDirection::NorthWest => XdgResizeEdge::TopLeft, + ResizeDirection::NorthEast => XdgResizeEdge::TopRight, + ResizeDirection::East => XdgResizeEdge::Right, + ResizeDirection::SouthWest => XdgResizeEdge::BottomLeft, + ResizeDirection::SouthEast => XdgResizeEdge::BottomRight, + ResizeDirection::South => XdgResizeEdge::Bottom, } } diff --git a/winit/src/window.rs b/winit/src/window.rs index 12747113f..c6e978cdb 100644 --- a/winit/src/window.rs +++ b/winit/src/window.rs @@ -16,6 +16,8 @@ pub use crate::icon::{BadIcon, Icon}; pub use cursor_icon::{CursorIcon, ParseError as CursorIconParseError}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[doc(inline)] +pub use winit_core::window::*; /// Represents a window. /// @@ -1625,67 +1627,6 @@ unsafe impl rwh_04::HasRawWindowHandle for Window { } } -/// The behavior of cursor grabbing. -/// -/// Use this enum with [`Window::set_cursor_grab`] to grab the cursor. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum CursorGrabMode { - /// No grabbing of the cursor is performed. - None, - - /// The cursor is confined to the window area. - /// - /// There's no guarantee that the cursor will be hidden. You should hide it by yourself if you - /// want to do so. - /// - /// ## Platform-specific - /// - /// - **macOS:** Not implemented. Always returns [`ExternalError::NotSupported`] for now. - /// - **iOS / Android / Web / Orbital:** Always returns an [`ExternalError::NotSupported`]. - Confined, - - /// The cursor is locked inside the window area to the certain position. - /// - /// There's no guarantee that the cursor will be hidden. You should hide it by yourself if you - /// want to do so. - /// - /// ## Platform-specific - /// - /// - **X11 / Windows:** Not implemented. Always returns [`ExternalError::NotSupported`] for now. - /// - **iOS / Android / Orbital:** Always returns an [`ExternalError::NotSupported`]. - Locked, -} - -/// Defines the orientation that a window resize will be performed. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum ResizeDirection { - East, - North, - NorthEast, - NorthWest, - South, - SouthEast, - SouthWest, - West, -} - -impl From for CursorIcon { - fn from(direction: ResizeDirection) -> Self { - use ResizeDirection::*; - match direction { - East => CursorIcon::EResize, - North => CursorIcon::NResize, - NorthEast => CursorIcon::NeResize, - NorthWest => CursorIcon::NwResize, - South => CursorIcon::SResize, - SouthEast => CursorIcon::SeResize, - SouthWest => CursorIcon::SwResize, - West => CursorIcon::WResize, - } - } -} - /// Fullscreen modes. #[derive(Clone, Debug, PartialEq, Eq)] pub enum Fullscreen { @@ -1695,98 +1636,6 @@ pub enum Fullscreen { Borderless(Option), } -/// The theme variant to use. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum Theme { - /// Use the light variant. - Light, - - /// Use the dark variant. - Dark, -} - -/// ## Platform-specific -/// -/// - **X11:** Sets the WM's `XUrgencyHint`. No distinction between [`Critical`] and [`Informational`]. -/// -/// [`Critical`]: Self::Critical -/// [`Informational`]: Self::Informational -#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] -pub enum UserAttentionType { - /// ## Platform-specific - /// - /// - **macOS:** Bounces the dock icon until the application is in focus. - /// - **Windows:** Flashes both the window and the taskbar button until the application is in focus. - Critical, - - /// ## Platform-specific - /// - /// - **macOS:** Bounces the dock icon once. - /// - **Windows:** Flashes the taskbar button until the application is in focus. - #[default] - Informational, -} - -bitflags::bitflags! { - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] - pub struct WindowButtons: u32 { - const CLOSE = 1 << 0; - const MINIMIZE = 1 << 1; - const MAXIMIZE = 1 << 2; - } -} - -/// A window level groups windows with respect to their z-position. -/// -/// The relative ordering between windows in different window levels is fixed. -/// The z-order of a window within the same window level may change dynamically on user interaction. -/// -/// ## Platform-specific -/// -/// - **iOS / Android / Web / Wayland:** Unsupported. -#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] -pub enum WindowLevel { - /// The window will always be below normal windows. - /// - /// This is useful for a widget-based app. - AlwaysOnBottom, - - /// The default. - #[default] - Normal, - - /// The window will always be on top of normal windows. - AlwaysOnTop, -} - -/// Generic IME purposes for use in [`Window::set_ime_purpose`]. -/// -/// The purpose may improve UX by optimizing the IME for the specific use case, -/// if winit can express the purpose to the platform and the platform reacts accordingly. -/// -/// ## Platform-specific -/// -/// - **iOS / Android / Web / Windows / X11 / macOS / Orbital:** Unsupported. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[non_exhaustive] -pub enum ImePurpose { - /// No special hints for the IME (default). - Normal, - /// The IME is used for password input. - Password, - /// The IME is used to input into a terminal. - /// - /// For example, that could alter OSK on Wayland to show extra buttons. - Terminal, -} - -impl Default for ImePurpose { - fn default() -> Self { - Self::Normal - } -} - /// An opaque token used to activate the [`Window`]. /// /// [`Window`]: crate::window::Window