use std::os::raw::{c_uint, c_ulong};
use x11::{xlib, xtest};
pub struct OpenDisplay {
raw: *mut x11::xlib::Display,
}
impl OpenDisplay {
pub fn open() -> Result<Self, super::Error> {
let raw = unsafe { xlib::XOpenDisplay(std::ptr::null()) };
if raw.is_null() {
return Err(super::Error::OpenDisplay);
}
Ok(Self { raw })
}
#[inline]
pub fn raw(&self) -> *mut x11::xlib::Display {
self.raw
}
pub fn xtest_query_extension(&self) -> bool {
let mut event_base = 0;
let mut error_base = 0;
let mut major_version = 0;
let mut minor_version = 0;
unsafe {
xtest::XTestQueryExtension(
self.raw,
&mut event_base,
&mut error_base,
&mut major_version,
&mut minor_version,
) != xlib::False
}
}
#[inline]
pub fn get_input_focus(&self) -> Result<xlib::Window, super::Error> {
let mut window = 0;
let mut revert_to = 0;
let status = unsafe { xlib::XGetInputFocus(self.raw(), &mut window, &mut revert_to) };
if status == xlib::False {
Err(super::Error::Unexpected)
} else {
Ok(window)
}
}
#[inline]
pub fn keysym_to_keycode(&self, keysym: xlib::KeySym) -> Option<xlib::KeyCode> {
let keycode = unsafe { xlib::XKeysymToKeycode(self.raw, keysym) };
if keycode == 0 {
None
} else {
Some(keycode)
}
}
#[inline]
pub fn flush(&self) -> Result<(), super::Error> {
let status = unsafe { xlib::XFlush(self.raw) };
if status == xlib::False {
Err(super::Error::Unexpected)
} else {
Ok(())
}
}
pub fn send_key_event(
&self,
window: xlib::Window,
keycode: c_uint,
state: c_uint,
press: bool,
) -> Result<(), super::Error> {
let (type_, mask) = match press {
true => (xlib::KeyPress, xlib::KeyPressMask),
false => (xlib::KeyRelease, xlib::KeyReleaseMask),
};
let mut event = xlib::XEvent {
key: xlib::XKeyEvent {
display: self.raw,
keycode,
root: 0,
same_screen: xlib::True,
send_event: xlib::True,
serial: 0,
state,
subwindow: 0,
time: xlib::CurrentTime,
type_,
window,
x: 0,
x_root: 0,
y: 0,
y_root: 0,
},
};
let status = unsafe { xlib::XSendEvent(self.raw, window, xlib::True, mask, &mut event) };
if status == xlib::False {
Err(super::Error::Unexpected)
} else {
Ok(())
}
}
pub fn send_button_event(
&self,
window: xlib::Window,
button: c_uint,
press: bool,
) -> Result<(), super::Error> {
let (type_, mask) = match press {
true => (xlib::ButtonPress, xlib::ButtonPressMask),
false => (xlib::ButtonRelease, xlib::ButtonReleaseMask),
};
let mut event = xlib::XEvent {
button: xlib::XButtonEvent {
button,
display: self.raw,
root: 0,
same_screen: xlib::True,
send_event: xlib::True,
serial: 0,
state: 0,
subwindow: 0,
time: xlib::CurrentTime,
type_,
window,
x: 0,
x_root: 0,
y: 0,
y_root: 0,
},
};
let status = unsafe { xlib::XSendEvent(self.raw, window, xlib::True, mask, &mut event) };
if status == xlib::False {
Err(super::Error::Unexpected)
} else {
Ok(())
}
}
#[inline]
pub fn xtest_fake_key_event(
&self,
keycode: c_uint,
press: bool,
delay: c_ulong,
) -> Result<(), super::Error> {
let status = unsafe { xtest::XTestFakeKeyEvent(self.raw, keycode, press as _, delay) };
if status == xlib::False {
Err(super::Error::Unexpected)
} else {
Ok(())
}
}
#[inline]
pub fn xtest_fake_button_event(
&self,
button: c_uint,
press: bool,
delay: c_ulong,
) -> Result<(), super::Error> {
let status = unsafe { xtest::XTestFakeButtonEvent(self.raw, button, press as _, delay) };
if status == xlib::False {
Err(super::Error::Unexpected)
} else {
Ok(())
}
}
}
impl Drop for OpenDisplay {
#[inline]
fn drop(&mut self) {
unsafe { xlib::XCloseDisplay(self.raw) };
}
}