2018-09-11 01:31:25 +00:00
|
|
|
use std::ffi::CString;
|
|
|
|
|
2018-09-11 21:58:16 +00:00
|
|
|
use libc;
|
2018-09-11 01:31:25 +00:00
|
|
|
use x11::xlib as x;
|
|
|
|
|
2018-09-30 12:05:02 +00:00
|
|
|
use {Cursor, Event, Visual, Window, X11Error};
|
2018-09-11 01:31:25 +00:00
|
|
|
|
|
|
|
/// A connection to an X server.
|
|
|
|
pub struct Display {
|
|
|
|
inner: *mut x::Display,
|
|
|
|
}
|
|
|
|
|
2018-09-30 21:59:42 +00:00
|
|
|
pub struct Grab(pub(crate) *mut x::Display);
|
|
|
|
|
2018-09-11 21:58:16 +00:00
|
|
|
/// Something that's part of a display.
|
|
|
|
pub trait GetDisplay {
|
|
|
|
/// Get the current display
|
|
|
|
fn get_display(&self) -> *mut x::Display;
|
|
|
|
}
|
|
|
|
|
2018-09-11 01:31:25 +00:00
|
|
|
impl Display {
|
|
|
|
/// Opens a new connection to an X server.
|
|
|
|
///
|
|
|
|
/// On POSIX-conformant systems, the display name or DISPLAY environment variable can be a string in the format:
|
|
|
|
/// hostname:number.screen_number
|
|
|
|
pub fn connect(display_name: impl AsRef<str>) -> Result<Display, X11Error> {
|
|
|
|
let display_name = CString::new(display_name.as_ref()).unwrap();
|
|
|
|
let inner = unsafe { x::XOpenDisplay(display_name.as_ptr()) };
|
2018-09-11 02:23:11 +00:00
|
|
|
if inner.is_null() {
|
|
|
|
return Err(X11Error::DisplayOpenError);
|
|
|
|
}
|
2018-09-11 01:31:25 +00:00
|
|
|
Ok(Display { inner })
|
|
|
|
}
|
|
|
|
|
2018-09-30 21:59:42 +00:00
|
|
|
/// Create a Display for an existing connection
|
|
|
|
pub fn from_handle(handle: u64) -> Self {
|
|
|
|
Display {
|
|
|
|
inner: handle as *mut x::Display,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Grab
|
|
|
|
pub fn grab(&self) -> Grab {
|
|
|
|
unsafe { x::XGrabServer(self.inner) };
|
|
|
|
Grab(self.inner)
|
|
|
|
}
|
|
|
|
|
2018-09-11 22:25:50 +00:00
|
|
|
/// Wrapper around XCreateFontCursor
|
|
|
|
pub fn create_font_cursor(&self, shape: u32) -> Result<Cursor, X11Error> {
|
|
|
|
let cursor = unsafe { x::XCreateFontCursor(self.inner, shape) as x::Cursor };
|
|
|
|
if cursor == 0 {
|
|
|
|
return Err(X11Error::CreateCursorError);
|
|
|
|
}
|
|
|
|
Ok(Cursor {
|
|
|
|
display: self.inner,
|
|
|
|
inner: cursor,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-09-11 21:58:16 +00:00
|
|
|
/// Get the next event, blocks until an event is reached.
|
|
|
|
pub fn next_event(&self) -> Result<Event, X11Error> {
|
|
|
|
let event =
|
|
|
|
unsafe { libc::malloc(::std::mem::size_of::<x::XAnyEvent>()) as *mut x::XAnyEvent };
|
|
|
|
Event::from_raw(event)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the number of events that are still pending
|
|
|
|
pub fn pending(&self) -> Result<i32, X11Error> {
|
|
|
|
Ok(unsafe { x::XPending(self.inner) })
|
|
|
|
}
|
|
|
|
|
2018-09-11 04:13:33 +00:00
|
|
|
/// Gets the raw X Display handle
|
|
|
|
pub fn as_raw(&self) -> *mut x::Display {
|
|
|
|
self.inner
|
|
|
|
}
|
|
|
|
|
2018-09-11 19:08:15 +00:00
|
|
|
/// Gets the default visual
|
|
|
|
pub fn default_visual(&self, screen: i32) -> Visual {
|
|
|
|
let visual = unsafe { x::XDefaultVisual(self.inner, screen) };
|
|
|
|
Visual { inner: visual }
|
|
|
|
}
|
|
|
|
|
2018-09-11 01:31:25 +00:00
|
|
|
/// Returns the root window for the given screen.
|
|
|
|
pub fn get_root_window(&self, screen: i32) -> Result<Window, X11Error> {
|
2018-09-11 02:23:11 +00:00
|
|
|
let inner = unsafe { x::XRootWindow(self.inner, screen) };
|
|
|
|
if inner == 0 {
|
|
|
|
return Err(X11Error::GetWindowError);
|
|
|
|
}
|
2018-09-11 01:31:25 +00:00
|
|
|
let window = Window {
|
|
|
|
display: self.inner,
|
2018-09-11 02:23:11 +00:00
|
|
|
inner,
|
2018-09-11 01:31:25 +00:00
|
|
|
};
|
|
|
|
Ok(window)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the root window for the default screen.
|
|
|
|
pub fn get_default_root_window(&self) -> Result<Window, X11Error> {
|
2018-09-11 02:23:11 +00:00
|
|
|
let inner = unsafe { x::XDefaultRootWindow(self.inner) };
|
|
|
|
if inner == 0 {
|
|
|
|
return Err(X11Error::GetWindowError);
|
|
|
|
}
|
2018-09-11 01:31:25 +00:00
|
|
|
let window = Window {
|
|
|
|
display: self.inner,
|
2018-09-11 02:23:11 +00:00
|
|
|
inner,
|
2018-09-11 01:31:25 +00:00
|
|
|
};
|
|
|
|
Ok(window)
|
|
|
|
}
|
2018-09-11 01:44:07 +00:00
|
|
|
|
2018-09-11 02:23:11 +00:00
|
|
|
/// Translate coordinates relative to w1 to coordinates relative to w2.
|
|
|
|
/// If the coordinates are contained in a mapped child of the destination window, the third return
|
|
|
|
/// value will hold that child window.
|
|
|
|
pub fn translate_coordinates(
|
|
|
|
&self,
|
|
|
|
w1: Window,
|
|
|
|
x: i32,
|
|
|
|
y: i32,
|
|
|
|
w2: Window,
|
|
|
|
) -> Result<(i32, i32, Option<Window>), X11Error> {
|
|
|
|
let mut rx = 0;
|
|
|
|
let mut ry = 0;
|
|
|
|
let mut child_return: x::Window = 0;
|
|
|
|
let status = unsafe {
|
|
|
|
x::XTranslateCoordinates(
|
|
|
|
self.inner,
|
|
|
|
w1.inner,
|
|
|
|
w2.inner,
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
&mut rx,
|
|
|
|
&mut ry,
|
|
|
|
&mut child_return,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
if status == 0 {
|
|
|
|
return Err(X11Error::TranslateCoordinatesError);
|
|
|
|
}
|
|
|
|
let child = match child_return {
|
|
|
|
0 => None,
|
|
|
|
val => Some(Window {
|
|
|
|
display: self.inner,
|
|
|
|
inner: val,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
Ok((rx, ry, child))
|
|
|
|
}
|
|
|
|
|
2018-09-11 22:25:50 +00:00
|
|
|
/// Sync
|
|
|
|
pub fn sync(&self, discard: bool) {
|
|
|
|
unsafe { x::XSync(self.inner, if discard { 1 } else { 0 }) };
|
|
|
|
}
|
|
|
|
|
2018-09-11 01:44:07 +00:00
|
|
|
/// eturns the focus window and the current focus state.
|
|
|
|
pub fn get_input_focus(&self) -> Result<(Window, i32), X11Error> {
|
|
|
|
let mut focus_return: x::Window = 0;
|
|
|
|
let mut revert_to_return = 0;
|
|
|
|
unsafe { x::XGetInputFocus(self.inner, &mut focus_return, &mut revert_to_return) };
|
|
|
|
let window = Window {
|
|
|
|
display: self.inner,
|
|
|
|
inner: focus_return,
|
|
|
|
};
|
|
|
|
return Ok((window, revert_to_return));
|
|
|
|
}
|
2018-09-11 01:31:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for Display {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe { x::XCloseDisplay(self.inner) };
|
|
|
|
}
|
|
|
|
}
|
2018-09-30 21:59:42 +00:00
|
|
|
|
|
|
|
impl Drop for Grab {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe { x::XUngrabServer(self.0) };
|
|
|
|
}
|
|
|
|
}
|