From d4a73a0e8d55b4b0ee72444260f2cb0d282f12a0 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Sun, 28 Jun 2020 14:50:29 -0500 Subject: [PATCH] add some extensions stuff --- Cargo.toml | 3 ++- src/errors.rs | 6 +++++ src/ffi.rs | 15 +++++++++++ src/lib.rs | 4 +++ src/xinput/mod.rs | 1 + src/xlib/display.rs | 61 +++++++++++++++++++++++++++++++++++++++++- src/xrender/picture.rs | 2 +- 7 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 src/ffi.rs create mode 100644 src/xinput/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 2721a5e..32fdbbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "safex11" -version = "0.0.1" +version = "0.0.2" description = "Safe, high-level x11 bindings" license-file = "LICENSE" authors = ["Michael Zhang "] @@ -14,6 +14,7 @@ default = [] xlib = ["x11/xlib"] xrender = ["x11/xrender"] xinerama = ["x11/xlib", "x11/xinerama"] +xinput = ["x11/xinput"] [dependencies] libc = "0.2" diff --git a/src/errors.rs b/src/errors.rs index db4f989..5cb66ee 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -25,6 +25,12 @@ pub enum Error { #[error("failed to translate coordinates")] TranslateCoordinatesError, + #[error("utf8 decoding error: {0}")] + Utf8(#[from] std::str::Utf8Error), + + #[error("nul error: {0}")] + Nul(#[from] std::ffi::NulError), + #[error("error")] Error, } diff --git a/src/ffi.rs b/src/ffi.rs new file mode 100644 index 0000000..44fcea5 --- /dev/null +++ b/src/ffi.rs @@ -0,0 +1,15 @@ +use std::ffi::{CStr, CString}; +use std::os::raw::c_char; + +use crate::Result; + +pub unsafe fn string_from_c_char_star(ptr: *mut c_char) -> Result { + let c_str = CStr::from_ptr(ptr); + let s = c_str.to_str()?; + Ok(s.to_owned()) +} + +pub fn c_char_star_from_string(s: impl AsRef) -> Result<*mut c_char> { + let c_str = CString::new(s.as_ref().as_bytes())?; + Ok(c_str.into_raw()) +} diff --git a/src/lib.rs b/src/lib.rs index 2227a9f..f608330 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,9 @@ extern crate log; pub extern crate x11; +#[cfg(feature = "xinput")] +pub mod xinput; + #[cfg(feature = "xlib")] pub mod xlib; @@ -17,6 +20,7 @@ pub mod xrender; pub mod xinerama; mod errors; +mod ffi; mod rect; pub use crate::errors::{Error, Result}; diff --git a/src/xinput/mod.rs b/src/xinput/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/xinput/mod.rs @@ -0,0 +1 @@ + diff --git a/src/xlib/display.rs b/src/xlib/display.rs index bf0ec09..7ad88dd 100644 --- a/src/xlib/display.rs +++ b/src/xlib/display.rs @@ -1,9 +1,11 @@ use std::ffi::CString; +use std::os::raw::c_char; use std::ptr; use x11::xlib; use crate::errors::{Error, Result}; +use crate::ffi; use super::cursor::Cursor; use super::event::Event; @@ -26,7 +28,9 @@ pub trait GetDisplay { 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: + /// 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) -> Result { let display_name = CString::new(display_name.as_ref()).unwrap(); @@ -166,6 +170,36 @@ impl Display { }; return Ok((window, revert_to_return)); } + + /// Query extension + pub fn query_extension(&self, name: impl AsRef) -> Result<()> { + let name = ffi::c_char_star_from_string(name)?; + let mut major_opcode_return = ptr::null_mut(); + let mut first_event_return = ptr::null_mut(); + let mut first_error_return = ptr::null_mut(); + let result = unsafe { + xlib::XQueryExtension( + self.inner, + name, + major_opcode_return, + first_event_return, + first_error_return, + ) + }; + // TODO: check reuslt + + unimplemented!() + } + + /// List extensions + pub fn list_extensions(&self) -> Result { + let mut nextensions_return = ptr::null_mut(); + let result = unsafe { xlib::XListExtensions(self.inner, nextensions_return) }; + // TODO: check result null + // TODO: check nextensions_return + let nextensions_return = unsafe { *nextensions_return } as isize; + Ok(ListExtensions(&self, result, nextensions_return)) + } } impl Drop for Display { @@ -179,3 +213,28 @@ impl Drop for Grab { unsafe { xlib::XUngrabServer(self.0) }; } } + +pub struct ListExtensions<'a>(&'a Display, *mut *mut c_char, isize); + +impl<'a> ListExtensions<'a> { + pub fn iter(&self) -> ListExtensionsIter { + ListExtensionsIter(self, 0) + } +} + +pub struct ListExtensionsIter<'a>(&'a ListExtensions<'a>, isize); + +impl<'a> Iterator for ListExtensionsIter<'a> { + type Item = String; + fn next(&mut self) -> Option { + if self.1 >= (self.0).2 { + return None; + } + + // TODO: check for null + let base = unsafe { *(self.0).1.offset(self.1) }; + let s = unsafe { ffi::string_from_c_char_star(base).unwrap() }; + // TODO: don't unwrap here + Some(s) + } +} diff --git a/src/xrender/picture.rs b/src/xrender/picture.rs index 82c0c32..8a2023e 100644 --- a/src/xrender/picture.rs +++ b/src/xrender/picture.rs @@ -3,5 +3,5 @@ pub struct Picture {} impl Picture {} impl Drop for Picture { - fn drop(&self) {} + fn drop(&mut self) {} }