Skip to content

Commit

Permalink
Fixup style issues
Browse files Browse the repository at this point in the history
  • Loading branch information
kchibisov committed Dec 16, 2023
1 parent 1c6673f commit 60fae4f
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 146 deletions.
59 changes: 29 additions & 30 deletions src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand All @@ -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<Vec<u8>>,
width: u16,
Expand All @@ -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<u8>,
width: u16,
height: u16,
hotspot_x: u16,
hotspot_y: u16,
) -> Result<Self, BadImage> {
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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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<u8>,
width: u16,
height: u16,
hotspot_x: u16,
hotspot_y: u16,
) -> Result<Self, BadImage> {
CursorImage::from_rgba(rgba, width, height, hotspot_x, hotspot_y)?;
Ok(Self)
}
}
31 changes: 16 additions & 15 deletions src/platform_impl/linux/wayland/types/cursor.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
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,
pub hotspot_x: i32,
pub hotspot_y: i32,
}

impl CustomCursorInternal {
impl CustomCursor {
pub fn new(pool: &mut SlotPool, image: &CursorImage) -> Self {
let (buffer, canvas) = pool
.create_buffer(
Expand All @@ -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,
Expand All @@ -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())
}
}
13 changes: 6 additions & 7 deletions src/platform_impl/linux/wayland/window/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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);

Expand All @@ -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 {
Expand All @@ -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();

Expand Down
144 changes: 72 additions & 72 deletions src/platform_impl/linux/x11/util/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,77 +6,6 @@ use crate::{cursor::CursorImage, window::CursorIcon};

use super::*;

#[derive(Debug)]
struct RaiiCursor {
xconn: Arc<XConnection>,
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<RaiiCursor>,
}

impl CustomCursorInternal {
pub(crate) unsafe fn new(xconn: &Arc<XConnection>, 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<CursorIcon>) {
let cursor = *self
Expand All @@ -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");
}
Expand Down Expand Up @@ -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<CustomCursorInner>,
}

impl CustomCursor {
pub(crate) unsafe fn new(xconn: &Arc<XConnection>, 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<XConnection>,
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())
}
}
Loading

0 comments on commit 60fae4f

Please sign in to comment.