2017-12-13 06:22:03 -05:00
|
|
|
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};
|
|
|
|
|
|
2017-12-15 14:37:09 -05:00
|
|
|
pub unsafe fn get_atom(xconn: &Arc<XConnection>, name: &[u8]) -> Result<ffi::Atom, XError> {
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-13 06:22:03 -05:00
|
|
|
pub unsafe fn send_client_msg(
|
|
|
|
|
xconn: &Arc<XConnection>,
|
2017-12-15 14:37:09 -05:00
|
|
|
window: c_ulong, // the window this is "about"; not necessarily this window
|
|
|
|
|
target_window: c_ulong, // the window we're sending to
|
2017-12-13 06:22:03 -05:00
|
|
|
message_type: ffi::Atom,
|
2017-12-15 14:37:09 -05:00
|
|
|
event_mask: Option<c_long>,
|
2017-12-13 06:22:03 -05:00
|
|
|
data: (c_long, c_long, c_long, c_long, c_long),
|
2017-12-15 14:37:09 -05:00
|
|
|
) -> Result<(), XError> {
|
2017-12-13 06:22:03 -05:00
|
|
|
let mut event: ffi::XClientMessageEvent = mem::uninitialized();
|
|
|
|
|
event.type_ = ffi::ClientMessage;
|
|
|
|
|
event.display = xconn.display;
|
2017-12-15 14:37:09 -05:00
|
|
|
event.window = window;
|
2017-12-13 06:22:03 -05:00
|
|
|
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);
|
|
|
|
|
|
2017-12-15 14:37:09 -05:00
|
|
|
let event_mask = event_mask.unwrap_or(ffi::NoEventMask);
|
|
|
|
|
|
2017-12-13 06:22:03 -05:00
|
|
|
(xconn.xlib.XSendEvent)(
|
|
|
|
|
xconn.display,
|
|
|
|
|
target_window,
|
|
|
|
|
ffi::False,
|
2017-12-15 14:37:09 -05:00
|
|
|
event_mask,
|
2017-12-13 06:22:03 -05:00
|
|
|
&mut event.into(),
|
|
|
|
|
);
|
2017-12-15 14:37:09 -05:00
|
|
|
|
|
|
|
|
xconn.check_errors().map(|_| ())
|
2017-12-13 06:22:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub enum GetPropertyError {
|
|
|
|
|
XError(XError),
|
|
|
|
|
TypeMismatch(ffi::Atom),
|
|
|
|
|
FormatMismatch(c_int),
|
|
|
|
|
NothingAllocated,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub unsafe fn get_property<T>(
|
|
|
|
|
xconn: &Arc<XConnection>,
|
|
|
|
|
window: c_ulong,
|
|
|
|
|
property: ffi::Atom,
|
|
|
|
|
property_type: ffi::Atom,
|
|
|
|
|
) -> Result<Vec<T>, 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::<T>() != mem::size_of::<c_char>(),
|
|
|
|
|
16 => mem::size_of::<T>() != mem::size_of::<c_short>(),
|
|
|
|
|
32 => mem::size_of::<T>() != mem::size_of::<c_long>(),
|
|
|
|
|
_ => 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)
|
|
|
|
|
}
|