From 4eb8b69611a216a2feecb7313cc70588192a332f Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 24 Dec 2023 23:33:42 +0100 Subject: [PATCH] Merge `Window::set_cursor_icon()` and `Window::set_custom_cursor()` --- CHANGELOG.md | 3 +- examples/cursor.rs | 2 +- examples/custom_cursors.rs | 6 +-- examples/multithreaded.rs | 2 +- examples/window_drag_resize.rs | 2 +- src/cursor.rs | 31 ++++++++++- src/platform_impl/android/mod.rs | 5 +- src/platform_impl/ios/window.rs | 15 +++--- src/platform_impl/linux/mod.rs | 11 ++-- src/platform_impl/linux/wayland/window/mod.rs | 21 ++++---- src/platform_impl/linux/x11/window.rs | 45 ++++++++-------- src/platform_impl/macos/window.rs | 31 ++++++----- src/platform_impl/orbital/window.rs | 9 ++-- src/platform_impl/web/cursor.rs | 49 +++++++++--------- src/platform_impl/web/window.rs | 12 ++--- src/platform_impl/windows/window.rs | 51 ++++++++++--------- src/window.rs | 25 +++------ 17 files changed, 163 insertions(+), 157 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1e475419d..05d70e0736 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ Unreleased` header. # Unreleased - On Windows, macOS, X11, Wayland and Web, implement setting images as cursors. See the `custom_cursors.rs` example. - - Add `Window::set_custom_cursor` + - **Breaking:** Remove `Window::set_cursor_icon` + - Add `Window::set_cursor` which takes a `CursorIcon` or `CustomCursor` - Add `CustomCursor` - Add `CustomCursor::from_rgba` to allow creating cursor images from RGBA data. - Add `CustomCursorExtWebSys::from_url` to allow loading cursor images from URLs. diff --git a/examples/cursor.rs b/examples/cursor.rs index 83ab1064ff..b2c80b89ce 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -31,7 +31,7 @@ fn main() -> Result<(), impl std::error::Error> { .. } => { println!("Setting cursor to \"{:?}\"", CURSORS[cursor_idx]); - window.set_cursor_icon(CURSORS[cursor_idx]); + window.set_cursor(CURSORS[cursor_idx]); if cursor_idx < CURSORS.len() - 1 { cursor_idx += 1; } else { diff --git a/examples/custom_cursors.rs b/examples/custom_cursors.rs index c29dd863f2..4c47f362d7 100644 --- a/examples/custom_cursors.rs +++ b/examples/custom_cursors.rs @@ -6,7 +6,7 @@ use winit::{ event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::{EventLoop, EventLoopWindowTarget}, keyboard::Key, - window::{CustomCursor, WindowBuilder}, + window::{CursorIcon, CustomCursor, WindowBuilder}, }; fn decode_cursor(bytes: &[u8], window_target: &EventLoopWindowTarget) -> CustomCursor { @@ -62,12 +62,12 @@ fn main() -> Result<(), impl std::error::Error> { } => match key.as_ref() { Key::Character("1") => { log::debug!("Setting cursor to {:?}", cursor_idx); - window.set_custom_cursor(&custom_cursors[cursor_idx]); + window.set_cursor(custom_cursors[cursor_idx].clone()); cursor_idx = (cursor_idx + 1) % 2; } Key::Character("2") => { log::debug!("Setting cursor icon to default"); - window.set_cursor_icon(Default::default()); + window.set_cursor(CursorIcon::default()); } Key::Character("3") => { cursor_visible = !cursor_visible; diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index b4660459cd..3bcf462ffe 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -84,7 +84,7 @@ fn main() -> Result<(), impl std::error::Error> { "1" => window.set_window_level(WindowLevel::AlwaysOnTop), "2" => window.set_window_level(WindowLevel::AlwaysOnBottom), "3" => window.set_window_level(WindowLevel::Normal), - "c" => window.set_cursor_icon(match state { + "c" => window.set_cursor(match state { true => CursorIcon::Progress, false => CursorIcon::Default, }), diff --git a/examples/window_drag_resize.rs b/examples/window_drag_resize.rs index b1d3cba43d..8db9fa543a 100644 --- a/examples/window_drag_resize.rs +++ b/examples/window_drag_resize.rs @@ -40,7 +40,7 @@ fn main() -> Result<(), impl std::error::Error> { if new_location != cursor_location { cursor_location = new_location; - window.set_cursor_icon(cursor_direction_icon(cursor_location)) + window.set_cursor(cursor_direction_icon(cursor_location)) } } } diff --git a/src/cursor.rs b/src/cursor.rs index c263d79200..b11104ee3e 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -3,6 +3,8 @@ use std::hash::Hasher; use std::sync::Arc; use std::{error::Error, hash::Hash}; +use cursor_icon::CursorIcon; + use crate::event_loop::EventLoopWindowTarget; use crate::platform_impl::{self, PlatformCustomCursor, PlatformCustomCursorBuilder}; @@ -11,8 +13,35 @@ pub const MAX_CURSOR_SIZE: u16 = 2048; const PIXEL_SIZE: usize = 4; +/// See [`Window::set_cursor()`](crate::window::Window::set_cursor) for more details. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub enum Cursor { + Icon(CursorIcon), + Custom(CustomCursor), +} + +impl Default for Cursor { + fn default() -> Self { + Self::Icon(CursorIcon::default()) + } +} + +impl From for Cursor { + fn from(icon: CursorIcon) -> Self { + Self::Icon(icon) + } +} + +impl From for Cursor { + fn from(custom: CustomCursor) -> Self { + Self::Custom(custom) + } +} + /// Use a custom image as a cursor (mouse pointer). /// +/// Is guaranteed to be cheap to clone. +/// /// ## Platform-specific /// /// **Web**: Some browsers have limits on cursor sizes usually at 128x128. @@ -44,7 +73,7 @@ const PIXEL_SIZE: usize = 4; /// let custom_cursor = builder.build(&event_loop); /// /// let window = Window::new(&event_loop).unwrap(); -/// window.set_custom_cursor(&custom_cursor); +/// window.set_cursor(custom_cursor.clone()); /// ``` #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct CustomCursor { diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 22b05717ca..9e6e466ce0 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -18,6 +18,7 @@ use android_activity::{ use once_cell::sync::Lazy; use crate::{ + cursor::Cursor, dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error, event::{self, Force, InnerSizeWriter, StartCause}, @@ -908,9 +909,7 @@ impl Window { pub fn request_user_attention(&self, _request_type: Option) {} - pub fn set_cursor_icon(&self, _: window::CursorIcon) {} - - pub(crate) fn set_custom_cursor(&self, _: PlatformCustomCursor) {} + pub fn set_cursor(&self, _: Cursor) {} pub fn set_cursor_position(&self, _: Position) -> Result<(), error::ExternalError> { Err(error::ExternalError::NotSupported( diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index e34801696e..53d91b1f71 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -11,17 +11,18 @@ use super::app_state::EventWrapper; use super::uikit::{UIApplication, UIScreen, UIScreenOverscanCompensation}; use super::view::{WinitUIWindow, WinitView, WinitViewController}; use crate::{ + cursor::Cursor, dpi::{self, LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError, OsError as RootOsError}, event::{Event, WindowEvent}, icon::Icon, platform::ios::{ScreenEdge, StatusBarStyle, ValidOrientations}, platform_impl::platform::{ - app_state, monitor, EventLoopWindowTarget, Fullscreen, MonitorHandle, PlatformCustomCursor, + app_state, monitor, EventLoopWindowTarget, Fullscreen, MonitorHandle, }, window::{ - CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, UserAttentionType, - WindowAttributes, WindowButtons, WindowId as RootWindowId, WindowLevel, + CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, + WindowButtons, WindowId as RootWindowId, WindowLevel, }, }; @@ -173,12 +174,8 @@ impl Inner { self.view.contentScaleFactor() as _ } - pub fn set_cursor_icon(&self, _cursor: CursorIcon) { - debug!("`Window::set_cursor_icon` ignored on iOS") - } - - pub(crate) fn set_custom_cursor(&self, _: PlatformCustomCursor) { - debug!("`Window::set_custom_cursor` ignored on iOS") + pub fn set_cursor(&self, _cursor: Cursor) { + debug!("`Window::set_cursor` ignored on iOS") } pub fn set_cursor_position(&self, _position: Position) -> Result<(), ExternalError> { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 92eeb0d41c..371aeedcd4 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -31,7 +31,7 @@ use crate::{ scancode::PhysicalKeyExtScancode, }, window::{ - ActivationToken, CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, + ActivationToken, Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowButtons, WindowLevel, }, }; @@ -422,13 +422,8 @@ impl Window { } #[inline] - pub fn set_cursor_icon(&self, cursor: CursorIcon) { - x11_or_wayland!(match self; Window(w) => w.set_cursor_icon(cursor)) - } - - #[inline] - pub(crate) fn set_custom_cursor(&self, cursor: PlatformCustomCursor) { - x11_or_wayland!(match self; Window(w) => w.set_custom_cursor(cursor)) + pub fn set_cursor(&self, cursor: Cursor) { + x11_or_wayland!(match self; Window(w) => w.set_cursor(cursor)) } #[inline] diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 74ff1baf11..31e893083c 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -20,11 +20,11 @@ use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError}; use crate::event::{Ime, WindowEvent}; use crate::event_loop::AsyncRequestSerial; use crate::platform_impl::{ - Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformCustomCursor, - PlatformIcon, PlatformSpecificWindowBuilderAttributes as PlatformAttributes, + Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformIcon, + PlatformSpecificWindowBuilderAttributes as PlatformAttributes, }; use crate::window::{ - CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, UserAttentionType, + Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowButtons, WindowLevel, }; @@ -502,16 +502,13 @@ impl Window { } #[inline] - pub fn set_cursor_icon(&self, cursor: CursorIcon) { - self.window_state.lock().unwrap().set_cursor(cursor); - } + pub fn set_cursor(&self, cursor: Cursor) { + let window_state = &mut self.window_state.lock().unwrap(); - #[inline] - pub(crate) fn set_custom_cursor(&self, cursor: PlatformCustomCursor) { - self.window_state - .lock() - .unwrap() - .set_custom_cursor(&cursor.0); + match cursor { + Cursor::Icon(icon) => window_state.set_cursor(icon), + Cursor::Custom(cursor) => window_state.set_custom_cursor(&cursor.inner.0), + } } #[inline] diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index b7ea8e1a12..ef83003a50 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -7,7 +7,6 @@ use std::{ sync::{Arc, Mutex, MutexGuard}, }; -use cursor_icon::CursorIcon; use x11rb::{ connection::Connection, properties::{WmHints, WmHintsState, WmSizeHints, WmSizeHintsSpecification}, @@ -21,6 +20,7 @@ use x11rb::{ }; use crate::{ + cursor::Cursor, dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError, OsError as RootOsError}, event::{Event, InnerSizeWriter, WindowEvent}, @@ -30,8 +30,8 @@ use crate::{ atoms::*, xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender, X11Error, }, - Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformCustomCursor, - PlatformIcon, PlatformSpecificWindowBuilderAttributes, VideoMode as PlatformVideoMode, + Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformIcon, + PlatformSpecificWindowBuilderAttributes, VideoMode as PlatformVideoMode, }, window::{ CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, @@ -1537,28 +1537,31 @@ impl UnownedWindow { } #[inline] - pub fn set_cursor_icon(&self, cursor: CursorIcon) { - let old_cursor = replace( - &mut *self.selected_cursor.lock().unwrap(), - SelectedCursor::Named(cursor), - ); + pub fn set_cursor(&self, cursor: Cursor) { + match cursor { + Cursor::Icon(icon) => { + let old_cursor = replace( + &mut *self.selected_cursor.lock().unwrap(), + SelectedCursor::Named(icon), + ); - #[allow(clippy::mutex_atomic)] - if SelectedCursor::Named(cursor) != old_cursor && *self.cursor_visible.lock().unwrap() { - self.xconn.set_cursor_icon(self.xwindow, Some(cursor)); - } - } + #[allow(clippy::mutex_atomic)] + if SelectedCursor::Named(icon) != old_cursor && *self.cursor_visible.lock().unwrap() + { + self.xconn.set_cursor_icon(self.xwindow, Some(icon)); + } + } + Cursor::Custom(cursor) => { + let new_cursor = unsafe { CustomCursor::new(&self.xconn, &cursor.inner.0) }; - #[inline] - pub(crate) fn set_custom_cursor(&self, cursor: PlatformCustomCursor) { - let new_cursor = unsafe { CustomCursor::new(&self.xconn, &cursor.0) }; + #[allow(clippy::mutex_atomic)] + if *self.cursor_visible.lock().unwrap() { + self.xconn.set_custom_cursor(self.xwindow, &new_cursor); + } - #[allow(clippy::mutex_atomic)] - if *self.cursor_visible.lock().unwrap() { - self.xconn.set_custom_cursor(self.xwindow, &new_cursor); + *self.selected_cursor.lock().unwrap() = SelectedCursor::Custom(new_cursor); + } } - - *self.selected_cursor.lock().unwrap() = SelectedCursor::Custom(new_cursor); } #[inline] diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index aac58b9184..d2718e8525 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -6,6 +6,7 @@ use std::ops; use std::sync::{Mutex, MutexGuard}; use crate::{ + cursor::Cursor, dpi::{ LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size, Size::Logical, }, @@ -20,11 +21,11 @@ use crate::{ monitor::{self, MonitorHandle, VideoMode}, view::WinitView, window_delegate::WinitWindowDelegate, - Fullscreen, OsError, PlatformCustomCursor, + Fullscreen, OsError, }, window::{ - CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, UserAttentionType, - WindowAttributes, WindowButtons, WindowId as RootWindowId, WindowLevel, + CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, + WindowButtons, WindowId as RootWindowId, WindowLevel, }, }; use core_graphics::display::{CGDisplay, CGPoint}; @@ -795,17 +796,19 @@ impl WinitWindow { buttons } - pub fn set_cursor_icon(&self, icon: CursorIcon) { - let view = self.view(); - view.set_cursor_icon(cursor_from_icon(icon)); - self.invalidateCursorRectsForView(&view); - } - - #[inline] - pub(crate) fn set_custom_cursor(&self, cursor: PlatformCustomCursor) { - let view = self.view(); - view.set_cursor_icon(cursor.0.clone()); - self.invalidateCursorRectsForView(&view); + pub fn set_cursor(&self, cursor: Cursor) { + match cursor { + Cursor::Icon(icon) => { + let view = self.view(); + view.set_cursor_icon(cursor_from_icon(icon)); + self.invalidateCursorRectsForView(&view); + } + Cursor::Custom(cursor) => { + let view = self.view(); + view.set_cursor_icon(cursor.inner.0.clone()); + self.invalidateCursorRectsForView(&view); + } + } } #[inline] diff --git a/src/platform_impl/orbital/window.rs b/src/platform_impl/orbital/window.rs index 3a5c74b7e1..9a15330781 100644 --- a/src/platform_impl/orbital/window.rs +++ b/src/platform_impl/orbital/window.rs @@ -4,6 +4,7 @@ use std::{ }; use crate::{ + cursor::Cursor, dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error, platform_impl::Fullscreen, @@ -12,8 +13,8 @@ use crate::{ }; use super::{ - EventLoopWindowTarget, MonitorHandle, PlatformCustomCursor, - PlatformSpecificWindowBuilderAttributes, RedoxSocket, TimeSocket, WindowId, WindowProperties, + EventLoopWindowTarget, MonitorHandle, PlatformSpecificWindowBuilderAttributes, RedoxSocket, + TimeSocket, WindowId, WindowProperties, }; // These values match the values uses in the `window_new` function in orbital: @@ -350,9 +351,7 @@ impl Window { pub fn request_user_attention(&self, _request_type: Option) {} #[inline] - pub fn set_cursor_icon(&self, _: window::CursorIcon) {} - - pub(crate) fn set_custom_cursor(&self, _: PlatformCustomCursor) {} + pub fn set_cursor(&self, _: Cursor) {} #[inline] pub fn set_cursor_position(&self, _: Position) -> Result<(), error::ExternalError> { diff --git a/src/platform_impl/web/cursor.rs b/src/platform_impl/web/cursor.rs index cd8922ecc8..4d57c20079 100644 --- a/src/platform_impl/web/cursor.rs +++ b/src/platform_impl/web/cursor.rs @@ -10,7 +10,7 @@ use std::{ }; use crate::{ - cursor::{BadImage, CursorImage}, + cursor::{BadImage, Cursor, CursorImage}, platform_impl::platform::r#async, }; use cursor_icon::CursorIcon; @@ -141,35 +141,34 @@ impl CursorState { }))) } - pub fn set_cursor_icon(&self, cursor: CursorIcon) { + pub fn set_cursor(&self, cursor: Cursor) { let mut this = self.0.borrow_mut(); - if let SelectedCursor::ImageLoading { state, .. } = &this.cursor { - if let ImageState::Loading(state) = state.get().borrow_mut().deref_mut() { - state.take(); - } - } - - this.cursor = SelectedCursor::Named(cursor); - this.set_style(); - } - - pub(crate) fn set_custom_cursor(&self, cursor: CustomCursor) { - let mut this = self.0.borrow_mut(); + match cursor { + Cursor::Icon(icon) => { + if let SelectedCursor::ImageLoading { state, .. } = &this.cursor { + if let ImageState::Loading(state) = state.get().borrow_mut().deref_mut() { + state.take(); + } + } - match cursor.0.get().borrow_mut().deref_mut() { - ImageState::Loading(state) => { - this.cursor = SelectedCursor::ImageLoading { - state: cursor.0.clone(), - previous: mem::take(&mut this.cursor).into(), - }; - *state = Some(Rc::downgrade(&self.0)); - } - ImageState::Failed => log::error!("tried to load invalid cursor"), - ImageState::Ready(image) => { - this.cursor = SelectedCursor::ImageReady(image.clone()); + this.cursor = SelectedCursor::Named(icon); this.set_style(); } + Cursor::Custom(cursor) => match cursor.inner.0.get().borrow_mut().deref_mut() { + ImageState::Loading(state) => { + this.cursor = SelectedCursor::ImageLoading { + state: cursor.inner.0.clone(), + previous: mem::take(&mut this.cursor).into(), + }; + *state = Some(Rc::downgrade(&self.0)); + } + ImageState::Failed => log::error!("tried to load invalid cursor"), + ImageState::Ready(image) => { + this.cursor = SelectedCursor::ImageReady(image.clone()); + this.set_style(); + } + }, } } diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index f3845dc810..56bfa49a21 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -2,14 +2,13 @@ use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size}; use crate::error::{ExternalError, NotSupportedError, OsError as RootOE}; use crate::icon::Icon; use crate::window::{ - CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, UserAttentionType, + Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowButtons, WindowId as RootWI, WindowLevel, }; use crate::SendSyncWrapper; use super::cursor::CursorState; use super::r#async::Dispatcher; -use super::PlatformCustomCursor; use super::{backend, monitor::MonitorHandle, EventLoopWindowTarget, Fullscreen}; use web_sys::HtmlCanvasElement; @@ -212,13 +211,8 @@ impl Inner { } #[inline] - pub fn set_cursor_icon(&self, cursor: CursorIcon) { - self.cursor.set_cursor_icon(cursor) - } - - #[inline] - pub(crate) fn set_custom_cursor(&self, cursor: PlatformCustomCursor) { - self.cursor.set_custom_cursor(cursor) + pub fn set_cursor(&self, cursor: Cursor) { + self.cursor.set_cursor(cursor) } #[inline] diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 65b879c62d..25944a6f38 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -55,6 +55,7 @@ use windows_sys::Win32::{ }; use crate::{ + cursor::Cursor, dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError, OsError as RootOsError}, icon::Icon, @@ -72,12 +73,11 @@ use crate::{ monitor::{self, MonitorHandle}, util, window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState}, - Fullscreen, PlatformCustomCursor, PlatformSpecificWindowBuilderAttributes, SelectedCursor, - WindowId, + Fullscreen, PlatformSpecificWindowBuilderAttributes, SelectedCursor, WindowId, }, window::{ - CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, UserAttentionType, - WindowAttributes, WindowButtons, WindowLevel, + CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, + WindowButtons, WindowLevel, }, }; @@ -395,27 +395,30 @@ impl Window { } #[inline] - pub fn set_cursor_icon(&self, cursor: CursorIcon) { - self.window_state_lock().mouse.selected_cursor = SelectedCursor::Named(cursor); - self.thread_executor.execute_in_thread(move || unsafe { - let cursor = LoadCursorW(0, util::to_windows_cursor(cursor)); - SetCursor(cursor); - }); - } - - #[inline] - pub(crate) fn set_custom_cursor(&self, cursor: PlatformCustomCursor) { - let new_cursor = match WinCursor::new(&cursor.0) { - Ok(cursor) => cursor, - Err(err) => { - warn!("Failed to create custom cursor: {err}"); - return; + pub fn set_cursor(&self, cursor: Cursor) { + match cursor { + Cursor::Icon(icon) => { + self.window_state_lock().mouse.selected_cursor = SelectedCursor::Named(icon); + self.thread_executor.execute_in_thread(move || unsafe { + let cursor = LoadCursorW(0, util::to_windows_cursor(icon)); + SetCursor(cursor); + }); } - }; - self.window_state_lock().mouse.selected_cursor = SelectedCursor::Custom(new_cursor.clone()); - self.thread_executor.execute_in_thread(move || unsafe { - SetCursor(new_cursor.as_raw_handle()); - }); + Cursor::Custom(cursor) => { + let new_cursor = match WinCursor::new(&cursor.inner.0) { + Ok(cursor) => cursor, + Err(err) => { + warn!("Failed to create custom cursor: {err}"); + return; + } + }; + self.window_state_lock().mouse.selected_cursor = + SelectedCursor::Custom(new_cursor.clone()); + self.thread_executor.execute_in_thread(move || unsafe { + SetCursor(new_cursor.as_raw_handle()); + }); + } + } } #[inline] diff --git a/src/window.rs b/src/window.rs index 89fd0439d6..c9b9f0f0c6 100644 --- a/src/window.rs +++ b/src/window.rs @@ -9,7 +9,7 @@ use crate::{ platform_impl, SendSyncWrapper, }; -pub use crate::cursor::{BadImage, CustomCursor, CustomCursorBuilder, MAX_CURSOR_SIZE}; +pub use crate::cursor::{BadImage, Cursor, CustomCursor, CustomCursorBuilder, MAX_CURSOR_SIZE}; pub use crate::icon::{BadIcon, Icon}; #[doc(inline)] @@ -1336,30 +1336,17 @@ impl Window { /// Cursor functions. impl Window { /// Modifies the cursor icon of the window. - /// Overwrites cursors set in [`Window::set_custom_cursor`]. /// /// ## Platform-specific /// /// - **iOS / Android / Orbital:** Unsupported. + /// - **Web:** Custom cursors have to be loaded and decoded first, until + /// then the previous cursor is shown. #[inline] - pub fn set_cursor_icon(&self, cursor: CursorIcon) { + pub fn set_cursor(&self, cursor: impl Into) { + let cursor = cursor.into(); self.window - .maybe_queue_on_main(move |w| w.set_cursor_icon(cursor)) - } - - /// Modifies the cursor icon of the window with a custom cursor. - /// Overwrites cursors set in [`Window::set_cursor_icon`]. - /// - /// ## Platform-specific - /// - /// - **iOS / Android / Orbital:** Unsupported. - /// - **Web:** Cursor have to be loaded and decoded first, which introduces - /// a delay until cursors are shown. - #[inline] - pub fn set_custom_cursor(&self, cursor: &CustomCursor) { - let cursor = cursor.inner.clone(); - self.window - .maybe_queue_on_main(move |w| w.set_custom_cursor(cursor)) + .maybe_queue_on_main(move |w| w.set_cursor(cursor)) } /// Changes the position of the cursor in window coordinates.