Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,10 @@ impl Eq for OnlyCursorImage {}

#[allow(dead_code)]
impl OnlyCursorImage {
fn build(builder: OnlyCursorImageBuilder, _: &platform_impl::EventLoopWindowTarget) -> Self {
pub(crate) fn build(
builder: OnlyCursorImageBuilder,
_: &platform_impl::EventLoopWindowTarget,
) -> Self {
Self(Arc::new(builder.0))
}
}
Expand Down
24 changes: 23 additions & 1 deletion src/platform_impl/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ use crate::{
};

pub(crate) use self::common::keymap::{physicalkey_to_scancode, scancode_to_physicalkey};
pub(crate) use crate::cursor::OnlyCursorImage as PlatformCustomCursor;
pub(crate) use crate::cursor::OnlyCursorImageBuilder as PlatformCustomCursorBuilder;
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
pub(crate) use crate::platform_impl::Fullscreen;
Expand Down Expand Up @@ -639,6 +638,29 @@ pub struct KeyEventExtra {
pub key_without_modifiers: Key,
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(crate) enum PlatformCustomCursor {
#[cfg(wayland_platform)]
Wayland(wayland::CustomCursor),
#[cfg(x11_platform)]
X(x11::CustomCursor),
}
impl PlatformCustomCursor {
pub(crate) fn build(
builder: PlatformCustomCursorBuilder,
p: &EventLoopWindowTarget,
) -> PlatformCustomCursor {
match p {
#[cfg(wayland_platform)]
EventLoopWindowTarget::Wayland(_) => {
Self::Wayland(wayland::CustomCursor::build(builder, p))
}
#[cfg(x11_platform)]
EventLoopWindowTarget::X(p) => Self::X(x11::CustomCursor::build(builder, p)),
}
}
}

/// Hooks for X11 errors.
#[cfg(x11_platform)]
pub(crate) static mut XLIB_ERROR_HOOKS: Lazy<Mutex<Vec<XlibErrorHook>>> =
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/linux/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use sctk::reexports::client::globals::{BindError, GlobalError};
use sctk::reexports::client::protocol::wl_surface::WlSurface;
use sctk::reexports::client::{self, ConnectError, DispatchError, Proxy};

pub(super) use crate::cursor::OnlyCursorImage as CustomCursor;
use crate::dpi::{LogicalSize, PhysicalSize};
pub use crate::platform_impl::platform::{OsError, WindowId};
pub use event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget};
Expand Down
4 changes: 2 additions & 2 deletions src/platform_impl/linux/wayland/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl Window {

match attributes.cursor {
Cursor::Icon(icon) => window_state.set_cursor(icon),
Cursor::Custom(cursor) => window_state.set_custom_cursor(&cursor.inner.0),
Cursor::Custom(cursor) => window_state.set_custom_cursor(cursor),
}

// Activate the window when the token is passed.
Expand Down Expand Up @@ -514,7 +514,7 @@ impl Window {

match cursor {
Cursor::Icon(icon) => window_state.set_cursor(icon),
Cursor::Custom(cursor) => window_state.set_custom_cursor(&cursor.inner.0),
Cursor::Custom(cursor) => window_state.set_custom_cursor(cursor),
}
}

Expand Down
21 changes: 17 additions & 4 deletions src/platform_impl/linux/wayland/window/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ use sctk::shm::Shm;
use sctk::subcompositor::SubcompositorState;
use wayland_protocols_plasma::blur::client::org_kde_kwin_blur::OrgKdeKwinBlur;

use crate::cursor::CursorImage;
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::types::cursor::{CustomCursor, SelectedCursor};
use crate::platform_impl::wayland::types::kwin_blur::KWinBlurManager;
use crate::platform_impl::wayland::{logical_to_physical_rounded, make_wid};
use crate::platform_impl::WindowId;
use crate::platform_impl::{PlatformCustomCursor, WindowId};
use crate::window::{CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme};

use crate::platform_impl::wayland::seat::{
Expand Down Expand Up @@ -726,10 +726,23 @@ impl WindowState {
}

/// Set the custom cursor icon.
pub(crate) fn set_custom_cursor(&mut self, cursor: &CursorImage) {
pub(crate) fn set_custom_cursor(&mut self, cursor: RootCustomCursor) {
let cursor = match cursor {
RootCustomCursor {
inner: PlatformCustomCursor::Wayland(cursor),
} => cursor.0,
#[cfg(x11_platform)]
RootCustomCursor {
inner: PlatformCustomCursor::X(_),
} => {
log::error!("passed a X11 cursor to Wayland backend");
return;
}
};

let cursor = {
let mut pool = self.custom_cursor_pool.lock().unwrap();
CustomCursor::new(&mut pool, cursor)
CustomCursor::new(&mut pool, &cursor)
};

if self.cursor_visible {
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/linux/x11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ use x11rb::{
xcb_ffi::ReplyOrIdError,
};

pub(super) use self::util::CustomCursor;
use self::{
dnd::{Dnd, DndState},
event_processor::EventProcessor,
Expand Down
59 changes: 38 additions & 21 deletions src/platform_impl/linux/x11/util/cursor.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
use std::{ffi::CString, iter, slice, sync::Arc};
use std::{
ffi::CString,
hash::{Hash, Hasher},
iter, slice,
sync::Arc,
};

use x11rb::connection::Connection;

use crate::{cursor::CursorImage, window::CursorIcon};
use crate::{platform_impl::PlatformCustomCursorBuilder, window::CursorIcon};

use super::super::EventLoopWindowTarget;
use super::*;

impl XConnection {
Expand Down Expand Up @@ -98,36 +104,55 @@ pub enum SelectedCursor {
Named(CursorIcon),
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone)]
pub struct CustomCursor {
inner: Arc<CustomCursorInner>,
}

impl Hash for CustomCursor {
fn hash<H: Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.inner).hash(state);
}
}

impl PartialEq for CustomCursor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}

impl Eq for CustomCursor {}

impl CustomCursor {
pub(crate) unsafe fn new(xconn: &Arc<XConnection>, image: &CursorImage) -> Self {
pub(crate) fn build(
builder: PlatformCustomCursorBuilder,
p: &EventLoopWindowTarget,
) -> CustomCursor {
unsafe {
let ximage =
(xconn.xcursor.XcursorImageCreate)(image.width as i32, image.height as i32);
let ximage = (p.xconn.xcursor.XcursorImageCreate)(
builder.0.width as i32,
builder.0.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).xhot = builder.0.hotspot_x as u32;
(*ximage).yhot = builder.0.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)) {
let dst = slice::from_raw_parts_mut((*ximage).pixels, builder.0.rgba.len() / 4);
for (dst, chunk) in dst.iter_mut().zip(builder.0.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);
let cursor = (p.xconn.xcursor.XcursorImageLoadCursor)(p.xconn.display, ximage);
(p.xconn.xcursor.XcursorImageDestroy)(ximage);
Self {
inner: Arc::new(CustomCursorInner {
xconn: xconn.clone(),
xconn: p.xconn.clone(),
cursor,
}),
}
Expand All @@ -149,14 +174,6 @@ impl Drop for CustomCursorInner {
}
}

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())
Expand Down
23 changes: 14 additions & 9 deletions src/platform_impl/linux/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use x11rb::{
};

use crate::{
cursor::Cursor,
cursor::{Cursor, CustomCursor as RootCustomCursor},
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
error::{ExternalError, NotSupportedError, OsError as RootOsError},
event::{Event, InnerSizeWriter, WindowEvent},
Expand All @@ -32,8 +32,9 @@ use crate::{
atoms::*, xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender,
X11Error,
},
Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformIcon,
PlatformSpecificWindowBuilderAttributes, VideoModeHandle as PlatformVideoModeHandle,
Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformCustomCursor,
PlatformIcon, PlatformSpecificWindowBuilderAttributes,
VideoModeHandle as PlatformVideoModeHandle,
},
window::{
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
Expand All @@ -43,7 +44,7 @@ use crate::{

use super::{
ffi,
util::{self, CustomCursor, SelectedCursor},
util::{self, SelectedCursor},
CookieResultExt, EventLoopWindowTarget, ImeRequest, ImeSender, VoidCookie, WindowId,
XConnection,
};
Expand Down Expand Up @@ -1552,16 +1553,20 @@ impl UnownedWindow {
self.xconn.set_cursor_icon(self.xwindow, Some(icon));
}
}
Cursor::Custom(cursor) => {
let new_cursor = unsafe { CustomCursor::new(&self.xconn, &cursor.inner.0) };

Cursor::Custom(RootCustomCursor {
inner: PlatformCustomCursor::X(cursor),
}) => {
#[allow(clippy::mutex_atomic)]
if *self.cursor_visible.lock().unwrap() {
self.xconn.set_custom_cursor(self.xwindow, &new_cursor);
self.xconn.set_custom_cursor(self.xwindow, &cursor);
}

*self.selected_cursor.lock().unwrap() = SelectedCursor::Custom(new_cursor);
*self.selected_cursor.lock().unwrap() = SelectedCursor::Custom(cursor);
}
#[cfg(wayland_platform)]
Cursor::Custom(RootCustomCursor {
inner: PlatformCustomCursor::Wayland(_),
}) => log::error!("passed a Wayland cursor to X11 backend"),
}
}

Expand Down