From e49fdfa5be09a9dc3a2408ee4631b56837c125d9 Mon Sep 17 00:00:00 2001 From: Janis Date: Sat, 7 May 2022 00:32:37 +0200 Subject: [PATCH] adds new XPointer type --- src/backends/xlib/mod.rs | 128 +++++++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 24 deletions(-) diff --git a/src/backends/xlib/mod.rs b/src/backends/xlib/mod.rs index 4d222d1..eedfb75 100644 --- a/src/backends/xlib/mod.rs +++ b/src/backends/xlib/mod.rs @@ -1,6 +1,6 @@ use log::{error, warn}; use num_traits::Zero; -use std::{ffi::CString, mem::MaybeUninit, rc::Rc}; +use std::{ffi::CString, rc::Rc}; use thiserror::Error; @@ -292,10 +292,15 @@ impl XLib { (ev.atom == self.atoms.net_wm_window_type) .then(|| { - (self.get_atom_property( - ev.window, - self.atoms.net_wm_state, - ) == Some(self.atoms.net_wm_state_fullscreen)) + (self + .get_atom_property( + ev.window, + self.atoms.net_wm_state, + ) + .map(|atom| { + *atom == self.atoms.net_wm_state_fullscreen + }) + == Some(true)) .then(|| { XLibWindowEvent::FullscreenEvent( FullscreenEvent::new( @@ -361,31 +366,31 @@ impl XLib { &self, window: xlib::Window, atom: xlib::Atom, - ) -> Option { + ) -> Option> { let mut di = 0; let mut dl0 = 0; let mut dl1 = 0; let mut da = 0; - let mut atom_out = MaybeUninit::::zeroed(); + let (atom_out, success) = + xpointer::XPointer::::build_with_result(|ptr| unsafe { + xlib::XGetWindowProperty( + self.dpy(), + window, + atom, + 0, + std::mem::size_of::() as i64, + 0, + xlib::XA_ATOM, + &mut da, + &mut di, + &mut dl0, + &mut dl1, + ptr as *mut _ as *mut _, + ) != 0 + }); - unsafe { - (xlib::XGetWindowProperty( - self.dpy(), - window, - atom, - 0, - std::mem::size_of::() as i64, - 0, - xlib::XA_ATOM, - &mut da, - &mut di, - &mut dl0, - &mut dl1, - atom_out.as_mut_ptr() as *mut _, - ) != 0) - .then(|| atom_out.assume_init()) - } + success.then(|| atom_out).flatten() } fn check_for_protocol( @@ -1056,3 +1061,78 @@ unsafe extern "C" fn xlib_error_handler( } } } + +pub mod xpointer { + use std::{ + ops::{Deref, DerefMut}, + ptr::{null, NonNull}, + }; + + use x11::xlib::XFree; + + #[repr(C)] + pub struct XPointer(NonNull); + + impl XPointer { + pub fn build_with(cb: F) -> Option + where + F: FnOnce(&mut *const ()), + { + let mut ptr = null() as *const (); + cb(&mut ptr); + NonNull::new(ptr as *mut T).map(|ptr| Self(ptr)) + } + + pub fn build_with_result(cb: F) -> (Option, R) + where + F: FnOnce(&mut *const ()) -> R, + { + let mut ptr = null() as *const (); + let result = cb(&mut ptr); + (NonNull::new(ptr as *mut T).map(|ptr| Self(ptr)), result) + } + } + + impl AsRef for XPointer { + fn as_ref(&self) -> &T { + &**self + } + } + + impl AsMut for XPointer { + fn as_mut(&mut self) -> &mut T { + &mut **self + } + } + + impl PartialEq for XPointer + where + T: PartialEq, + { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + + impl Eq for XPointer where T: Eq {} + + impl Deref for XPointer { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { self.0.as_ref() } + } + } + + impl DerefMut for XPointer { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { self.0.as_mut() } + } + } + + impl Drop for XPointer { + fn drop(&mut self) { + unsafe { XFree(self.0.as_ptr() as _) }; + } + } +}