Create custom cursor with directly with event loop

Replace the `CustomCursorBuilder` with the `CustomCursorSource` and
perform the loading of the cursor via the
`EventLoop::create_custom_cursor` instead of passing it to the builder
itself.

This follows the `EventLoop::create_window` API.
This commit is contained in:
Kirill Chibisov 2024-02-03 07:27:17 +04:00
parent 3fb93b4f83
commit 7abd427216
26 changed files with 213 additions and 175 deletions

View file

@ -18,6 +18,7 @@ use smol_str::SmolStr;
use self::x11::{X11Error, XConnection, XError, XNotSupported};
#[cfg(x11_platform)]
use crate::platform::x11::{WindowType as XWindowType, XlibErrorHook};
use crate::window::{CustomCursor, CustomCursorSource};
use crate::{
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
error::{EventLoopError, ExternalError, NotSupportedError, OsError as RootOsError},
@ -34,7 +35,7 @@ use crate::{
};
pub(crate) use self::common::xkb::{physicalkey_to_scancode, scancode_to_physicalkey};
pub(crate) use crate::cursor::OnlyCursorImageBuilder as PlatformCustomCursorBuilder;
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
pub(crate) use crate::platform_impl::Fullscreen;
@ -643,19 +644,6 @@ pub(crate) enum PlatformCustomCursor {
#[cfg(x11_platform)]
X(x11::CustomCursor),
}
impl PlatformCustomCursor {
pub(crate) fn build(
builder: PlatformCustomCursorBuilder,
p: &ActiveEventLoop,
) -> PlatformCustomCursor {
match p {
#[cfg(wayland_platform)]
ActiveEventLoop::Wayland(_) => Self::Wayland(wayland::CustomCursor::build(builder, p)),
#[cfg(x11_platform)]
ActiveEventLoop::X(p) => Self::X(x11::CustomCursor::build(builder, p)),
}
}
}
/// Hooks for X11 errors.
#[cfg(x11_platform)]
@ -867,6 +855,10 @@ impl ActiveEventLoop {
}
}
pub fn create_custom_cursor(&self, cursor: CustomCursorSource) -> CustomCursor {
x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.create_custom_cursor(cursor))
}
#[inline]
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
match *self {

View file

@ -15,13 +15,17 @@ use sctk::reexports::calloop_wayland_source::WaylandSource;
use sctk::reexports::client::globals;
use sctk::reexports::client::{Connection, QueueHandle};
use crate::cursor::OnlyCursorImage;
use crate::dpi::LogicalSize;
use crate::error::{EventLoopError, OsError as RootOsError};
use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent};
use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents};
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::platform::min_timeout;
use crate::platform_impl::{ActiveEventLoop as PlatformActiveEventLoop, OsError};
use crate::platform_impl::{
ActiveEventLoop as PlatformActiveEventLoop, OsError, PlatformCustomCursor,
};
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource};
mod proxy;
pub mod sink;
@ -686,6 +690,12 @@ impl ActiveEventLoop {
#[inline]
pub fn listen_device_events(&self, _allowed: DeviceEvents) {}
pub(crate) fn create_custom_cursor(&self, cursor: CustomCursorSource) -> RootCustomCursor {
RootCustomCursor {
inner: PlatformCustomCursor::Wayland(OnlyCursorImage(Arc::from(cursor.inner.0))),
}
}
#[cfg(feature = "rwh_05")]
#[inline]
pub fn raw_display_handle_rwh_05(&self) -> rwh_05::RawDisplayHandle {

View file

@ -28,16 +28,16 @@ use x11rb::protocol::xproto::{self, ConnectionExt as _};
use x11rb::x11_utils::X11Error as LogicalError;
use x11rb::xcb_ffi::ReplyOrIdError;
use super::{ControlFlow, OsError};
use crate::{
error::{EventLoopError, OsError as RootOsError},
event::{Event, StartCause, WindowEvent},
event_loop::{ActiveEventLoop as RootAEL, DeviceEvents, EventLoopClosed},
platform::pump_events::PumpStatus,
platform_impl::common::xkb::Context,
platform_impl::platform::{min_timeout, WindowId},
window::WindowAttributes,
use crate::error::{EventLoopError, OsError as RootOsError};
use crate::event::{Event, StartCause, WindowEvent};
use crate::event_loop::{ActiveEventLoop as RootAEL, ControlFlow, DeviceEvents, EventLoopClosed};
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::common::xkb::Context;
use crate::platform_impl::platform::{min_timeout, WindowId};
use crate::platform_impl::{
ActiveEventLoop as PlatformActiveEventLoop, OsError, PlatformCustomCursor,
};
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, WindowAttributes};
mod activation;
mod atoms;
@ -310,7 +310,7 @@ impl<T: 'static> EventLoop<T> {
window_target.update_listen_device_events(true);
let root_window_target = RootAEL {
p: super::ActiveEventLoop::X(window_target),
p: PlatformActiveEventLoop::X(window_target),
_marker: PhantomData,
};
@ -670,6 +670,12 @@ impl ActiveEventLoop {
self.xconn.primary_monitor().ok()
}
pub(crate) fn create_custom_cursor(&self, cursor: CustomCursorSource) -> RootCustomCursor {
RootCustomCursor {
inner: PlatformCustomCursor::X(CustomCursor::new(self, cursor.inner)),
}
}
pub fn listen_device_events(&self, allowed: DeviceEvents) {
self.device_events.set(allowed);
}

View file

@ -7,7 +7,7 @@ use std::{
use x11rb::connection::Connection;
use crate::{platform_impl::PlatformCustomCursorBuilder, window::CursorIcon};
use crate::{platform_impl::PlatformCustomCursorSource, window::CursorIcon};
use super::super::ActiveEventLoop;
use super::*;
@ -124,32 +124,36 @@ impl PartialEq for CustomCursor {
impl Eq for CustomCursor {}
impl CustomCursor {
pub(crate) fn build(builder: PlatformCustomCursorBuilder, p: &ActiveEventLoop) -> CustomCursor {
pub(crate) fn new(
event_loop: &ActiveEventLoop,
cursor: PlatformCustomCursorSource,
) -> CustomCursor {
unsafe {
let ximage = (p.xconn.xcursor.XcursorImageCreate)(
builder.0.width as i32,
builder.0.height as i32,
let ximage = (event_loop.xconn.xcursor.XcursorImageCreate)(
cursor.0.width as i32,
cursor.0.height as i32,
);
if ximage.is_null() {
panic!("failed to allocate cursor image");
}
(*ximage).xhot = builder.0.hotspot_x as u32;
(*ximage).yhot = builder.0.hotspot_y as u32;
(*ximage).xhot = cursor.0.hotspot_x as u32;
(*ximage).yhot = cursor.0.hotspot_y as u32;
(*ximage).delay = 0;
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)) {
let dst = slice::from_raw_parts_mut((*ximage).pixels, cursor.0.rgba.len() / 4);
for (dst, chunk) in dst.iter_mut().zip(cursor.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 = (p.xconn.xcursor.XcursorImageLoadCursor)(p.xconn.display, ximage);
(p.xconn.xcursor.XcursorImageDestroy)(ximage);
let cursor =
(event_loop.xconn.xcursor.XcursorImageLoadCursor)(event_loop.xconn.display, ximage);
(event_loop.xconn.xcursor.XcursorImageDestroy)(ximage);
Self {
inner: Arc::new(CustomCursorInner {
xconn: p.xconn.clone(),
xconn: event_loop.xconn.clone(),
cursor,
}),
}