X11: cache custom cursors (#3366)

This commit is contained in:
daxpedda 2024-01-17 18:17:49 +01:00 committed by GitHub
parent 6b29253797
commit d1717b6a01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 100 additions and 38 deletions

View file

@ -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 {
@ -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,
}),
}
@ -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())