From 60fae4fe5f64694583876e79eaf36421429ae910 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 16 Dec 2023 21:06:25 +0400 Subject: [PATCH] Fixup style issues --- src/cursor.rs | 59 ++++--- .../linux/wayland/types/cursor.rs | 31 ++-- .../linux/wayland/window/state.rs | 13 +- src/platform_impl/linux/x11/util/cursor.rs | 144 +++++++++--------- src/platform_impl/linux/x11/window.rs | 8 +- src/platform_impl/macos/appkit/cursor.rs | 6 +- src/platform_impl/windows/icon.rs | 30 ++-- 7 files changed, 145 insertions(+), 146 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index f7a079ffc09..1687689334a 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -3,21 +3,25 @@ use std::{error::Error, sync::Arc}; use crate::platform_impl::PlatformCustomCursor; +/// The maximum width and height for a cursor when using [`CustomCursor::from_rgba`]. +pub const MAX_CURSOR_SIZE: u16 = 2048; + +const PIXEL_SIZE: usize = 4; + /// Use a custom image as a cursor (mouse pointer). /// /// ## Platform-specific /// -/// **Web**: Some browsers have limits on cursor sizes typically at 128x128. -/// +/// **Web**: Some browsers have limits on cursor sizes usually at 128x128. /// -/// # Examples +/// # Example /// /// ``` /// use winit::window::CustomCursor; /// /// let w = 10; /// let h = 10; -/// let rgba = vec![0xff_u8; (w * h * 4) as usize]; +/// let rgba = vec![255; (w * h * 4) as usize]; /// let custom_cursor = CustomCursor::from_rgba(rgba, w, h, w / 2, h / 2).unwrap(); /// /// #[cfg(target_family = "wasm")] @@ -36,8 +40,8 @@ impl CustomCursor { /// /// ## Platform-specific /// - /// - **Web** Uses data URLs. They are generated asynchronously, so there can be latency when - /// setting a cursor. + /// - **Web:** Setting cursor could be delayed due to use of data URLs, which are async by + /// nature. pub fn from_rgba( rgba: impl Into>, width: u16, @@ -58,29 +62,8 @@ impl CustomCursor { } } -/// Platforms that don't support cursors will export this as `PlatformCustomCursor`. -#[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) struct NoCustomCursor; - -#[allow(dead_code)] -impl NoCustomCursor { - pub fn from_rgba( - rgba: Vec, - width: u16, - height: u16, - hotspot_x: u16, - hotspot_y: u16, - ) -> Result { - CursorImage::from_rgba(rgba, width, height, hotspot_x, hotspot_y)?; - Ok(Self) - } -} - -/// The maximum width and height for a cursor when using [`CustomCursor::from_rgba`]. -pub const MAX_CURSOR_SIZE: u16 = 2048; - -#[derive(Debug)] /// An error produced when using [`CustomCursor::from_rgba`] with invalid arguments. +#[derive(Debug, Clone)] pub enum BadImage { /// Produced when the image dimensions are larger than [`MAX_CURSOR_SIZE`]. This doesn't /// guarantee that the cursor will work, but should avoid many platform and device specific @@ -147,8 +130,6 @@ pub struct CursorImage { pub(crate) hotspot_y: u16, } -pub const PIXEL_SIZE: usize = 4; - #[allow(dead_code)] impl CursorImage { pub fn from_rgba( @@ -197,3 +178,21 @@ impl CursorImage { }) } } + +// Platforms that don't support cursors will export this as `PlatformCustomCursor`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct NoCustomCursor; + +#[allow(dead_code)] +impl NoCustomCursor { + pub fn from_rgba( + rgba: Vec, + width: u16, + height: u16, + hotspot_x: u16, + hotspot_y: u16, + ) -> Result { + CursorImage::from_rgba(rgba, width, height, hotspot_x, hotspot_y)?; + Ok(Self) + } +} diff --git a/src/platform_impl/linux/wayland/types/cursor.rs b/src/platform_impl/linux/wayland/types/cursor.rs index b2d0b1dbbaf..483486197f6 100644 --- a/src/platform_impl/linux/wayland/types/cursor.rs +++ b/src/platform_impl/linux/wayland/types/cursor.rs @@ -1,11 +1,24 @@ use cursor_icon::CursorIcon; + use sctk::reexports::client::protocol::wl_shm::Format; use sctk::shm::slot::{Buffer, SlotPool}; use crate::cursor::CursorImage; #[derive(Debug)] -pub struct CustomCursorInternal { +pub enum SelectedCursor { + Named(CursorIcon), + Custom(CustomCursor), +} + +impl Default for SelectedCursor { + fn default() -> Self { + Self::Named(Default::default()) + } +} + +#[derive(Debug)] +pub struct CustomCursor { pub buffer: Buffer, pub w: i32, pub h: i32, @@ -13,7 +26,7 @@ pub struct CustomCursorInternal { pub hotspot_y: i32, } -impl CustomCursorInternal { +impl CustomCursor { pub fn new(pool: &mut SlotPool, image: &CursorImage) -> Self { let (buffer, canvas) = pool .create_buffer( @@ -32,7 +45,7 @@ impl CustomCursorInternal { canvas_chunk[3] = rgba_chunk[3]; } - CustomCursorInternal { + CustomCursor { buffer, w: image.width as i32, h: image.height as i32, @@ -41,15 +54,3 @@ impl CustomCursorInternal { } } } - -#[derive(Debug)] -pub enum SelectedCursor { - Named(CursorIcon), - Custom(CustomCursorInternal), -} - -impl Default for SelectedCursor { - fn default() -> Self { - Self::Named(Default::default()) - } -} diff --git a/src/platform_impl/linux/wayland/window/state.rs b/src/platform_impl/linux/wayland/window/state.rs index fb1ecec0505..5f20e43e9b9 100644 --- a/src/platform_impl/linux/wayland/window/state.rs +++ b/src/platform_impl/linux/wayland/window/state.rs @@ -28,13 +28,13 @@ use sctk::shm::Shm; use sctk::subcompositor::SubcompositorState; use wayland_protocols_plasma::blur::client::org_kde_kwin_blur::OrgKdeKwinBlur; -use crate::cursor::CustomCursor; +use crate::cursor::CustomCursor as RootCustomCursor; use crate::dpi::{LogicalPosition, LogicalSize, PhysicalSize, Size}; use crate::error::{ExternalError, NotSupportedError}; use crate::event::WindowEvent; use crate::platform_impl::wayland::event_loop::sink::EventSink; use crate::platform_impl::wayland::make_wid; -use crate::platform_impl::wayland::types::cursor::{CustomCursorInternal, SelectedCursor}; +use crate::platform_impl::wayland::types::cursor::{CustomCursor, SelectedCursor}; use crate::platform_impl::wayland::types::kwin_blur::KWinBlurManager; use crate::platform_impl::WindowId; use crate::window::{CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme}; @@ -695,8 +695,6 @@ impl WindowState { } /// Set the cursor icon. - /// - /// Providing `None` will hide the cursor. pub fn set_cursor(&mut self, cursor_icon: CursorIcon) { self.selected_cursor = SelectedCursor::Named(cursor_icon); @@ -711,10 +709,11 @@ impl WindowState { }) } - pub fn set_custom_cursor(&mut self, cursor: CustomCursor) { + /// Set the custom cursor icon. + pub fn set_custom_cursor(&mut self, cursor: RootCustomCursor) { let cursor = { let mut pool = self.custom_cursor_pool.lock().unwrap(); - CustomCursorInternal::new(&mut pool, &cursor.inner) + CustomCursor::new(&mut pool, &cursor.inner) }; if self.cursor_visible { @@ -724,7 +723,7 @@ impl WindowState { self.selected_cursor = SelectedCursor::Custom(cursor); } - pub fn apply_custom_cursor(&self, cursor: &CustomCursorInternal) { + fn apply_custom_cursor(&self, cursor: &CustomCursor) { self.apply_on_poiner(|pointer, _| { let surface = pointer.surface(); diff --git a/src/platform_impl/linux/x11/util/cursor.rs b/src/platform_impl/linux/x11/util/cursor.rs index accf783d56a..e9b457d9677 100644 --- a/src/platform_impl/linux/x11/util/cursor.rs +++ b/src/platform_impl/linux/x11/util/cursor.rs @@ -6,77 +6,6 @@ use crate::{cursor::CursorImage, window::CursorIcon}; use super::*; -#[derive(Debug)] -struct RaiiCursor { - xconn: Arc, - cursor: ffi::Cursor, -} - -impl Drop for RaiiCursor { - fn drop(&mut self) { - unsafe { - (self.xconn.xlib.XFreeCursor)(self.xconn.display, self.cursor); - } - } -} - -impl PartialEq for RaiiCursor { - fn eq(&self, other: &Self) -> bool { - self.cursor == other.cursor - } -} - -impl Eq for RaiiCursor {} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct CustomCursorInternal { - inner: Arc, -} - -impl CustomCursorInternal { - pub(crate) unsafe fn new(xconn: &Arc, image: &CursorImage) -> Self { - unsafe { - let ximage = - (xconn.xcursor.XcursorImageCreate)(image.width as i32, image.height as i32); - if ximage.is_null() { - panic!("failed to allocate cursor image"); - } - (*ximage).xhot = image.hotspot_x as u32; - (*ximage).yhot = image.hotspot_y as u32; - (*ximage).delay = 0; - - let dst = slice::from_raw_parts_mut((*ximage).pixels, image.rgba.len() / 4); - for (dst, chunk) in dst.iter_mut().zip(image.rgba.chunks_exact(4)) { - *dst = (chunk[0] as u32) << 16 - | (chunk[1] as u32) << 8 - | (chunk[2] as u32) - | (chunk[3] as u32) << 24; - } - - let cursor = (xconn.xcursor.XcursorImageLoadCursor)(xconn.display, ximage); - (xconn.xcursor.XcursorImageDestroy)(ximage); - Self { - inner: Arc::new(RaiiCursor { - xconn: xconn.clone(), - cursor, - }), - } - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum SelectedCursor { - Custom(CustomCursorInternal), - Named(CursorIcon), -} - -impl Default for SelectedCursor { - fn default() -> Self { - SelectedCursor::Named(Default::default()) - } -} - impl XConnection { pub fn set_cursor_icon(&self, window: xproto::Window, cursor: Option) { let cursor = *self @@ -90,7 +19,7 @@ impl XConnection { .expect("Failed to set cursor"); } - pub fn set_custom_cursor(&self, window: xproto::Window, cursor: &CustomCursorInternal) { + pub fn set_custom_cursor(&self, window: xproto::Window, cursor: &CustomCursor) { self.update_cursor(window, cursor.inner.cursor) .expect("Failed to set cursor"); } @@ -162,3 +91,74 @@ impl XConnection { Ok(()) } } + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SelectedCursor { + Custom(CustomCursor), + Named(CursorIcon), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct CustomCursor { + inner: Arc, +} + +impl CustomCursor { + pub(crate) unsafe fn new(xconn: &Arc, image: &CursorImage) -> Self { + unsafe { + let ximage = + (xconn.xcursor.XcursorImageCreate)(image.width as i32, image.height as i32); + if ximage.is_null() { + panic!("failed to allocate cursor image"); + } + (*ximage).xhot = image.hotspot_x as u32; + (*ximage).yhot = image.hotspot_y as u32; + (*ximage).delay = 0; + + let dst = slice::from_raw_parts_mut((*ximage).pixels, image.rgba.len() / 4); + for (dst, chunk) in dst.iter_mut().zip(image.rgba.chunks_exact(4)) { + *dst = (chunk[0] as u32) << 16 + | (chunk[1] as u32) << 8 + | (chunk[2] as u32) + | (chunk[3] as u32) << 24; + } + + let cursor = (xconn.xcursor.XcursorImageLoadCursor)(xconn.display, ximage); + (xconn.xcursor.XcursorImageDestroy)(ximage); + Self { + inner: Arc::new(CustomCursorInner { + xconn: xconn.clone(), + cursor, + }), + } + } + } +} + +#[derive(Debug)] +struct CustomCursorInner { + xconn: Arc, + cursor: ffi::Cursor, +} + +impl Drop for CustomCursorInner { + fn drop(&mut self) { + unsafe { + (self.xconn.xlib.XFreeCursor)(self.xconn.display, self.cursor); + } + } +} + +impl PartialEq for CustomCursorInner { + fn eq(&self, other: &Self) -> bool { + self.cursor == other.cursor + } +} + +impl Eq for CustomCursorInner {} + +impl Default for SelectedCursor { + fn default() -> Self { + SelectedCursor::Named(Default::default()) + } +} diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 5a3244e84d5..bfc87d99e0a 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -7,7 +7,7 @@ use std::{ sync::{Arc, Mutex, MutexGuard}, }; -use crate::cursor::CustomCursor; +use crate::cursor::CustomCursor as RootCustomCursor; use cursor_icon::CursorIcon; use x11rb::{ @@ -43,7 +43,7 @@ use crate::{ use super::{ ffi, - util::{self, CustomCursorInternal, SelectedCursor}, + util::{self, CustomCursor, SelectedCursor}, CookieResultExt, EventLoopWindowTarget, ImeRequest, ImeSender, VoidCookie, WindowId, XConnection, }; @@ -1550,8 +1550,8 @@ impl UnownedWindow { } #[inline] - pub fn set_custom_cursor(&self, cursor: CustomCursor) { - let new_cursor = unsafe { CustomCursorInternal::new(&self.xconn, &cursor.inner) }; + pub fn set_custom_cursor(&self, cursor: RootCustomCursor) { + let new_cursor = unsafe { CustomCursor::new(&self.xconn, &cursor.inner) }; #[allow(clippy::mutex_atomic)] if *self.cursor_visible.lock().unwrap() { diff --git a/src/platform_impl/macos/appkit/cursor.rs b/src/platform_impl/macos/appkit/cursor.rs index 95b1180b190..6414d7159d9 100644 --- a/src/platform_impl/macos/appkit/cursor.rs +++ b/src/platform_impl/macos/appkit/cursor.rs @@ -243,12 +243,12 @@ impl NSCursor { unsafe { std::slice::from_raw_parts_mut(bitmap.bitmap_data(), image.rgba.len()) }; bitmap_data.copy_from_slice(&image.rgba); - let nsimage = NSImage::init_with_size(NSSize::new(w.into(), h.into())); - nsimage.add_representation(&bitmap); + let image = NSImage::init_with_size(NSSize::new(w.into(), h.into())); + image.add_representation(&bitmap); let hotspot = NSPoint::new(image.hotspot_x as f64, image.hotspot_y as f64); - NSCursor::new(&nsimage, hotspot) + NSCursor::new(&image, hotspot) } } diff --git a/src/platform_impl/windows/icon.rs b/src/platform_impl/windows/icon.rs index 5a026b14ea5..275f7fb699d 100644 --- a/src/platform_impl/windows/icon.rs +++ b/src/platform_impl/windows/icon.rs @@ -166,9 +166,16 @@ pub fn unset_for_window(hwnd: HWND, icon_type: IconType) { } } -#[derive(Debug)] -struct RaiiCursor { - handle: HCURSOR, +#[derive(Debug, Clone)] +pub enum SelectedCursor { + Named(CursorIcon), + Custom(WinCursor), +} + +impl Default for SelectedCursor { + fn default() -> Self { + Self::Named(Default::default()) + } } #[derive(Clone, Debug)] @@ -237,20 +244,13 @@ impl WinCursor { } } +#[derive(Debug)] +struct RaiiCursor { + handle: HCURSOR, +} + impl Drop for RaiiCursor { fn drop(&mut self) { unsafe { DestroyCursor(self.handle) }; } } - -#[derive(Debug, Clone)] -pub enum SelectedCursor { - Named(CursorIcon), - Custom(WinCursor), -} - -impl Default for SelectedCursor { - fn default() -> Self { - Self::Named(Default::default()) - } -}