use std::mem; use std::ptr; use std::sync::Arc; use libc::{c_char, c_int, c_long, c_short, c_uchar, c_ulong}; use super::{ffi, XConnection, XError}; pub unsafe fn get_atom(xconn: &Arc, name: &[u8]) -> Result { let atom_name: *const c_char = name.as_ptr() as _; let atom = (xconn.xlib.XInternAtom)(xconn.display, atom_name, ffi::False); xconn.check_errors().map(|_| atom) } pub unsafe fn send_client_msg( xconn: &Arc, window: c_ulong, // the window this is "about"; not necessarily this window target_window: c_ulong, // the window we're sending to message_type: ffi::Atom, event_mask: Option, data: (c_long, c_long, c_long, c_long, c_long), ) -> Result<(), XError> { let mut event: ffi::XClientMessageEvent = mem::uninitialized(); event.type_ = ffi::ClientMessage; event.display = xconn.display; event.window = window; event.message_type = message_type; event.format = 32; event.data = ffi::ClientMessageData::new(); event.data.set_long(0, data.0); event.data.set_long(1, data.1); event.data.set_long(2, data.2); event.data.set_long(3, data.3); event.data.set_long(4, data.4); let event_mask = event_mask.unwrap_or(ffi::NoEventMask); (xconn.xlib.XSendEvent)( xconn.display, target_window, ffi::False, event_mask, &mut event.into(), ); xconn.check_errors().map(|_| ()) } #[derive(Debug)] pub enum GetPropertyError { XError(XError), TypeMismatch(ffi::Atom), FormatMismatch(c_int), NothingAllocated, } pub unsafe fn get_property( xconn: &Arc, window: c_ulong, property: ffi::Atom, property_type: ffi::Atom, ) -> Result, GetPropertyError> { let mut data = Vec::new(); let mut done = false; while !done { let mut actual_type: ffi::Atom = mem::uninitialized(); let mut actual_format: c_int = mem::uninitialized(); let mut byte_count: c_ulong = mem::uninitialized(); let mut bytes_after: c_ulong = mem::uninitialized(); let mut buf: *mut c_uchar = ptr::null_mut(); (xconn.xlib.XGetWindowProperty)( xconn.display, window, property, (data.len() / 4) as c_long, 1024, ffi::False, property_type, &mut actual_type, &mut actual_format, &mut byte_count, &mut bytes_after, &mut buf, ); if let Err(e) = xconn.check_errors() { return Err(GetPropertyError::XError(e)); } if actual_type != property_type { return Err(GetPropertyError::TypeMismatch(actual_type)); } // Fun fact: actual_format ISN'T the size of the type; it's more like a really bad enum let format_mismatch = match actual_format as usize { 8 => mem::size_of::() != mem::size_of::(), 16 => mem::size_of::() != mem::size_of::(), 32 => mem::size_of::() != mem::size_of::(), _ => true, // this won't actually be reached; the XError condition above is triggered }; if format_mismatch { return Err(GetPropertyError::FormatMismatch(actual_format)); } if !buf.is_null() { let mut buf = Vec::from_raw_parts(buf as *mut T, byte_count as usize, byte_count as usize); data.append(&mut buf); } else { return Err(GetPropertyError::NothingAllocated); } done = bytes_after == 0; } Ok(data) }