cursor: refactor CustomCursor to be dyn
cursor: refactor `CustomCursor` to be `dyn` Same as for `MonitorHandle`, the source was changed to support all kinds of sources.
This commit is contained in:
parent
a0464ae83b
commit
ae28eea406
26 changed files with 329 additions and 333 deletions
|
|
@ -36,10 +36,9 @@ use crate::platform::x11::XlibErrorHook;
|
|||
use crate::platform_impl::common::xkb::Context;
|
||||
use crate::platform_impl::platform::min_timeout;
|
||||
use crate::platform_impl::x11::window::Window;
|
||||
use crate::platform_impl::PlatformCustomCursor;
|
||||
use crate::utils::Lazy;
|
||||
use crate::window::{
|
||||
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
|
||||
CustomCursor as CoreCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
|
||||
WindowAttributes, WindowId,
|
||||
};
|
||||
|
||||
|
|
@ -731,10 +730,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
fn create_custom_cursor(
|
||||
&self,
|
||||
custom_cursor: CustomCursorSource,
|
||||
) -> Result<RootCustomCursor, RequestError> {
|
||||
Ok(RootCustomCursor {
|
||||
inner: PlatformCustomCursor::X(CustomCursor::new(self, custom_cursor.inner)?),
|
||||
})
|
||||
) -> Result<CoreCustomCursor, RequestError> {
|
||||
Ok(CoreCustomCursor(Arc::new(CustomCursor::new(self, custom_cursor)?)))
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ use x11rb::protocol::xproto;
|
|||
|
||||
use super::super::ActiveEventLoop;
|
||||
use super::*;
|
||||
use crate::error::RequestError;
|
||||
use crate::platform_impl::PlatformCustomCursorSource;
|
||||
use crate::cursor::{CustomCursorProvider, CustomCursorSource};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::window::CursorIcon;
|
||||
|
||||
impl XConnection {
|
||||
|
|
@ -36,7 +36,7 @@ impl XConnection {
|
|||
window: xproto::Window,
|
||||
cursor: &CustomCursor,
|
||||
) -> Result<(), X11Error> {
|
||||
self.update_cursor(window, cursor.inner.cursor)
|
||||
self.update_cursor(window, cursor.cursor)
|
||||
}
|
||||
|
||||
/// Create a cursor from an image.
|
||||
|
|
@ -170,32 +170,45 @@ pub enum SelectedCursor {
|
|||
Named(CursorIcon),
|
||||
}
|
||||
|
||||
impl Default for SelectedCursor {
|
||||
fn default() -> Self {
|
||||
SelectedCursor::Named(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CustomCursor {
|
||||
inner: Arc<CustomCursorInner>,
|
||||
xconn: Arc<XConnection>,
|
||||
cursor: xproto::Cursor,
|
||||
}
|
||||
|
||||
impl Hash for CustomCursor {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
Arc::as_ptr(&self.inner).hash(state);
|
||||
self.cursor.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for CustomCursor {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Arc::ptr_eq(&self.inner, &other.inner)
|
||||
self.cursor == other.cursor
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for CustomCursor {}
|
||||
|
||||
impl CustomCursor {
|
||||
pub(crate) fn new(
|
||||
event_loop: &ActiveEventLoop,
|
||||
mut cursor: PlatformCustomCursorSource,
|
||||
cursor: CustomCursorSource,
|
||||
) -> Result<CustomCursor, RequestError> {
|
||||
let mut cursor = match cursor {
|
||||
CustomCursorSource::Image(cursor_image) => cursor_image,
|
||||
CustomCursorSource::Animation { .. } | CustomCursorSource::Url { .. } => {
|
||||
return Err(NotSupportedError::new("unsupported cursor kind").into())
|
||||
},
|
||||
};
|
||||
|
||||
// Reverse RGBA order to BGRA.
|
||||
cursor.0.rgba.chunks_mut(4).for_each(|chunk| {
|
||||
cursor.rgba.chunks_mut(4).for_each(|chunk| {
|
||||
let chunk: &mut [u8; 4] = chunk.try_into().unwrap();
|
||||
chunk[0..3].reverse();
|
||||
|
||||
|
|
@ -209,32 +222,26 @@ impl CustomCursor {
|
|||
let cursor = event_loop
|
||||
.xconn
|
||||
.create_cursor_from_image(
|
||||
cursor.0.width,
|
||||
cursor.0.height,
|
||||
cursor.0.hotspot_x,
|
||||
cursor.0.hotspot_y,
|
||||
&cursor.0.rgba,
|
||||
cursor.width,
|
||||
cursor.height,
|
||||
cursor.hotspot_x,
|
||||
cursor.hotspot_y,
|
||||
&cursor.rgba,
|
||||
)
|
||||
.map_err(|err| os_error!(err))?;
|
||||
|
||||
Ok(Self { inner: Arc::new(CustomCursorInner { xconn: event_loop.xconn.clone(), cursor }) })
|
||||
Ok(Self { xconn: event_loop.xconn.clone(), cursor })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CustomCursorInner {
|
||||
xconn: Arc<XConnection>,
|
||||
cursor: xproto::Cursor,
|
||||
}
|
||||
|
||||
impl Drop for CustomCursorInner {
|
||||
impl Drop for CustomCursor {
|
||||
fn drop(&mut self) {
|
||||
self.xconn.xcb_connection().free_cursor(self.cursor).map(|r| r.ignore_error()).ok();
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SelectedCursor {
|
||||
fn default() -> Self {
|
||||
SelectedCursor::Named(Default::default())
|
||||
impl CustomCursorProvider for CustomCursor {
|
||||
fn is_animated(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@ use x11rb::protocol::{randr, xinput};
|
|||
|
||||
use super::util::{self, SelectedCursor};
|
||||
use super::{
|
||||
ffi, ActiveEventLoop, CookieResultExt, ImeRequest, ImeSender, VoidCookie, XConnection,
|
||||
ffi, ActiveEventLoop, CookieResultExt, CustomCursor, ImeRequest, ImeSender, VoidCookie,
|
||||
XConnection,
|
||||
};
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::cursor::{Cursor, CustomCursor as RootCustomCursor};
|
||||
use crate::cursor::Cursor;
|
||||
use crate::dpi::{PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{SurfaceSizeWriter, WindowEvent};
|
||||
|
|
@ -35,7 +36,7 @@ use crate::platform_impl::x11::atoms::*;
|
|||
use crate::platform_impl::x11::{
|
||||
xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender, X11Error,
|
||||
};
|
||||
use crate::platform_impl::{common, PlatformCustomCursor, PlatformIcon};
|
||||
use crate::platform_impl::{common, PlatformIcon};
|
||||
use crate::window::{
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
|
||||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
|
|
@ -1808,19 +1809,23 @@ impl UnownedWindow {
|
|||
}
|
||||
}
|
||||
},
|
||||
Cursor::Custom(RootCustomCursor { inner: PlatformCustomCursor::X(cursor) }) => {
|
||||
Cursor::Custom(cursor) => {
|
||||
let cursor = match cursor.cast_ref::<CustomCursor>() {
|
||||
Some(cursor) => cursor,
|
||||
None => {
|
||||
tracing::error!("unrecognized cursor passed to X11 backend");
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
#[allow(clippy::mutex_atomic)]
|
||||
if *self.cursor_visible.lock().unwrap() {
|
||||
if let Err(err) = self.xconn.set_custom_cursor(self.xwindow, &cursor) {
|
||||
if let Err(err) = self.xconn.set_custom_cursor(self.xwindow, cursor) {
|
||||
tracing::error!("failed to set window icon: {err}");
|
||||
}
|
||||
}
|
||||
|
||||
*self.selected_cursor.lock().unwrap() = SelectedCursor::Custom(cursor);
|
||||
},
|
||||
#[cfg(wayland_platform)]
|
||||
Cursor::Custom(RootCustomCursor { inner: PlatformCustomCursor::Wayland(_) }) => {
|
||||
tracing::error!("passed a Wayland cursor to X11 backend")
|
||||
*self.selected_cursor.lock().unwrap() = SelectedCursor::Custom(cursor.clone());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue