diff --git a/src/xwrap/display.rs b/src/xwrap/display.rs index 1e9dcec..819e204 100644 --- a/src/xwrap/display.rs +++ b/src/xwrap/display.rs @@ -1,18 +1,44 @@ -use std::{env, ffi, ptr}; +use std::{env, ffi, ptr, ops}; use x11::xlib::{self, BadGC}; -use super::error; +use anyhow::Result; + +use super::{error, screen, window}; pub struct Display { - ptr: *mut xlib::Display, + pub(super) ptr: *mut xlib::Display, name: String, + keyboard_grab: Option, + pointer_grab: Option, +} + +// for keyboard/pointer grabs so Display is less messy +#[derive(Debug)] +struct Grabbables { + keyboard_mode: GrabMode, + pointer_mode: GrabMode, +} + +#[derive(Clone, Copy, Debug)] +pub enum GrabMode { + Sync, + Async, +} + +impl From for i32 { + fn from(v: GrabMode) -> Self { + match v { + GrabMode::Sync => xlib::GrabModeSync, + GrabMode::Async => xlib::GrabModeAsync, + } + } } impl Display { /// Call XOpenDisplay to open a connection to the X Server. /// If `display_name` is `None`, the value of the `DISPLAY` environment variable will be used. - pub fn open(display_name: Option) -> anyhow::Result { + pub fn open(display_name: Option) -> Result { let name = ffi::CString::new(if let Some(name) = display_name { name } else { @@ -31,6 +57,8 @@ impl Display { Ok(Self { ptr: display_ptr, name: name.into_string()?, + pointer_grab: None, + keyboard_grab: None, }) } } @@ -38,7 +66,7 @@ impl Display { /// Calls XFlush to flush the output buffer. pub fn flush(&self) { unsafe { - xlib::XFlush(self.ptr) + xlib::XFlush(self.ptr); } } @@ -52,8 +80,80 @@ impl Display { } } + /// Calls xlib::XDefaultScreen to get the default screen number referenced by Display::open. + /// This should be used to retrieve the screen number in applications that'll only use a single + /// screen. + pub fn default_screen_nr(&self) -> i32 { + unsafe { + xlib::XDefaultScreen(self.ptr) + } + } + + /// Gets the default screen + pub fn default_screen(&self) -> screen::Screen { + screen::Screen { + ptr: unsafe { + xlib::XDefaultScreenOfDisplay(self.ptr) + } + } + } + + /// Gets the root window of the default screen + pub fn default_root_window(&self) -> window::Window { + window::Window { + wid: unsafe { + xlib::XDefaultRootWindow(self.ptr) + } + } + } + + /// Get the range of legal KeyCodes for a display. + pub fn keycodes(&self) -> Result> { + let (mut min, mut max) = (0, 0); + + if unsafe { xlib::XDisplayKeycodes(self.ptr, &mut min, &mut max) } == 0 { + Err(error::XError::DisplayKeycodesError.into()) + } else { + Ok(min..max) + } + } + + pub fn grab_keyboard( + &mut self, + grab_window: window::Window, + owner_events: bool, + pointer_mode: GrabMode, + keyboard_mode: GrabMode, + time:xlib::Time, + ) -> Result<()> { + match unsafe { + xlib::XGrabKeyboard( + self.ptr, + grab_window.wid, + owner_events.into(), + pointer_mode.into(), + keyboard_mode.into(), + time + ) + } { + xlib::GrabSuccess => { + self.keyboard_grab = Some(Grabbables { + keyboard_mode, + pointer_mode + }); + + Ok(()) + }, + xlib::AlreadyGrabbed => todo!(), + xlib::GrabInvalidTime => todo!(), + xlib::GrabNotViewable => todo!(), + xlib::GrabFrozen => todo!(), + _ => todo!() + } + } } + impl Drop for Display { fn drop(&mut self) { if unsafe { xlib::XCloseDisplay(self.ptr) } == BadGC.into() { diff --git a/src/xwrap/error.rs b/src/xwrap/error.rs index 7bfe885..615b15a 100644 --- a/src/xwrap/error.rs +++ b/src/xwrap/error.rs @@ -1,9 +1,13 @@ -use std::fmt; +use std::{fmt, ops}; + +use x11::xlib; /// Various errors to be used in this wrapper #[derive(Debug)] pub enum XError { OpenDisplayError(String), + DisplayKeycodesError, + InvalidKeycodeError(xlib::KeyCode, ops::Range), } impl std::fmt::Display for XError { @@ -14,6 +18,8 @@ impl std::fmt::Display for XError { match self { XError::OpenDisplayError(display_name) => format!("error when opening display '{}'", display_name), + XError::DisplayKeycodesError => String::from("error when running XDisplayKeycodes"), + XError::InvalidKeycodeError(code, range) => format!("keycode {} outside of range {:?}", code, range), } ) } diff --git a/src/xwrap/mod.rs b/src/xwrap/mod.rs index 2848c7e..3f520cb 100644 --- a/src/xwrap/mod.rs +++ b/src/xwrap/mod.rs @@ -1,2 +1,5 @@ pub mod display; +pub mod screen; +pub mod window; pub mod error; +pub mod key;