m: Replace libxcursor with custom cursor code

Another one bites the dust.

This replaces the code dependent on libxcursor with equivalent code
written using x11rb, featuring its special "cursor" module.

cc #3198

Signed-off-by: John Nunley <dev@notgull.net>
This commit is contained in:
John Nunley 2024-08-22 19:25:20 -07:00 committed by John Nunley
parent 8f4a8efa99
commit aee95114db
7 changed files with 204 additions and 102 deletions

View file

@ -6,6 +6,7 @@ use std::{fmt, ptr};
use x11rb::connection::Connection;
use x11rb::protocol::randr::ConnectionExt as _;
use x11rb::protocol::render;
use x11rb::protocol::xproto::{self, ConnectionExt};
use x11rb::resource_manager;
use x11rb::xcb_ffi::XCBConnection;
@ -18,7 +19,6 @@ use crate::window::CursorIcon;
/// A connection to an X server.
pub struct XConnection {
pub xlib: ffi::Xlib,
pub xcursor: ffi::Xcursor,
// TODO(notgull): I'd like to remove this, but apparently Xlib and Xinput2 are tied together
// for some reason.
@ -55,8 +55,11 @@ pub struct XConnection {
/// Atom for the XSettings screen.
xsettings_screen: Option<xproto::Atom>,
/// XRender format information.
render_formats: render::QueryPictFormatsReply,
pub latest_error: Mutex<Option<XError>>,
pub cursor_cache: Mutex<HashMap<Option<CursorIcon>, ffi::Cursor>>,
pub cursor_cache: Mutex<HashMap<Option<CursorIcon>, xproto::Cursor>>,
}
unsafe impl Send for XConnection {}
@ -69,7 +72,6 @@ impl XConnection {
pub fn new(error_handler: XErrorHandler) -> Result<XConnection, XNotSupported> {
// opening the libraries
let xlib = ffi::Xlib::open()?;
let xcursor = ffi::Xcursor::open()?;
let xlib_xcb = ffi::Xlib_xcb::open()?;
let xinput2 = ffi::XInput2::open()?;
@ -118,15 +120,22 @@ impl XConnection {
tracing::warn!("error setting XSETTINGS; Xft options won't reload automatically")
}
// Start getting the XRender formats.
let formats_cookie = render::query_pict_formats(&xcb)
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?;
// Fetch atoms.
let atoms = Atoms::new(&xcb)
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?
.reply()
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?;
// Finish getting everything else.
let formats =
formats_cookie.reply().map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?;
Ok(XConnection {
xlib,
xcursor,
xinput2,
display,
xcb: Some(xcb),
@ -138,6 +147,7 @@ impl XConnection {
database: RwLock::new(database),
cursor_cache: Default::default(),
randr_version: (randr_version.major_version, randr_version.minor_version),
render_formats: formats,
xsettings_screen,
})
}
@ -257,6 +267,23 @@ impl XConnection {
pub fn xsettings_screen(&self) -> Option<xproto::Atom> {
self.xsettings_screen
}
/// Get the data containing our rendering formats.
#[inline]
pub fn render_formats(&self) -> &render::QueryPictFormatsReply {
&self.render_formats
}
/// Do we need to do an endian swap?
#[inline]
pub fn needs_endian_swap(&self) -> bool {
#[cfg(target_endian = "big")]
let endian = xproto::ImageOrder::MSB_FIRST;
#[cfg(not(target_endian = "big"))]
let endian = xproto::ImageOrder::LSB_FIRST;
self.xcb_connection().setup().image_byte_order != endian
}
}
impl fmt::Debug for XConnection {