Merge Window::set_cursor_icon() and Window::set_custom_cursor() (#3308)
This commit is contained in:
parent
34dd2cdba9
commit
be4a660011
17 changed files with 165 additions and 159 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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<T>(bytes: &[u8], window_target: &EventLoopWindowTarget<T>) -> 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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<CursorIcon> for Cursor {
|
||||
fn from(icon: CursorIcon) -> Self {
|
||||
Self::Icon(icon)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CustomCursor> 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 {
|
||||
|
|
|
|||
|
|
@ -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<window::UserAttentionType>) {}
|
||||
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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,30 +1537,33 @@ 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) };
|
||||
|
||||
#[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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
*self.selected_cursor.lock().unwrap() = SelectedCursor::Custom(new_cursor);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
|
||||
let mut grabbed_lock = self.cursor_grabbed_mode.lock().unwrap();
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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<window::UserAttentionType>) {}
|
||||
|
||||
#[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> {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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.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();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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<Cursor>) {
|
||||
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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue