diff options
author | Matias Linares <matiaslina@openmailbox.org> | 2016-05-25 13:18:18 -0300 |
---|---|---|
committer | Matias Linares <matiaslina@openmailbox.org> | 2016-05-25 13:18:18 -0300 |
commit | da3fa00ccf4cde76d1d6489c6043d7e56d4f52c5 (patch) | |
tree | 49dbdb5ce9d0baed54ee41a64393b01b6953f2e6 | |
parent | 77e4450afef9fb5d1acb8f2b690bd5e228f61d8e (diff) | |
download | dotwm-da3fa00ccf4cde76d1d6489c6043d7e56d4f52c5.tar.gz |
Add a lazy_static connection to the X server
-rw-r--r-- | Cargo.lock | 24 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/dotwm.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 3 | ||||
-rw-r--r-- | src/safe_x11/display.rs | 101 | ||||
-rw-r--r-- | src/safe_x11/mod.rs | 25 |
6 files changed, 117 insertions, 41 deletions
@@ -2,10 +2,10 @@ name = "dotwm" version = "0.1.0" dependencies = [ - "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "nom 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "unix_socket 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "x11 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "x11 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -14,18 +14,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "libc" -version = "0.2.2" +name = "lazy_static" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "nom" -version = "1.0.1" +name = "libc" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pkg-config" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -34,15 +34,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "x11" -version = "2.3.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6,7 +6,7 @@ authors = ["Matias Linares <matiaslina@openmailbox.org>"] [dependencies] libc = "0.2.*" unix_socket = "*" -nom = "~1.0.0" +lazy_static = "0.1.15" [dependencies.x11] version = "*" diff --git a/src/dotwm.rs b/src/dotwm.rs index 2781ae8..666deff 100644 --- a/src/dotwm.rs +++ b/src/dotwm.rs @@ -9,7 +9,6 @@ use x11::xlib::{ }; use safe_x11::{ - open_display, close_display, atom, }; @@ -79,7 +78,7 @@ pub struct DotWM { impl DotWM { /// Create a state of the Dot Window Manager pub fn new() -> DotWM { - let d = open_display("").unwrap(); + let d = unsafe { xlib::XOpenDisplay(0x0 as *const i8) }; unsafe { xlib::XSetErrorHandler(Some(error_handler)) }; // Add substructure notify mask diff --git a/src/main.rs b/src/main.rs index 2f5e80c..4f292b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ extern crate libc; extern crate x11; extern crate unix_socket; #[macro_use] -extern crate nom; +extern crate lazy_static; pub mod safe_x11; pub mod command; @@ -21,7 +21,6 @@ use socket::parser; use std::collections::HashMap; use x11::xlib; -use x11::xlib::XEvent; use x11::keysym; use std::fs; diff --git a/src/safe_x11/display.rs b/src/safe_x11/display.rs new file mode 100644 index 0000000..72b5b49 --- /dev/null +++ b/src/safe_x11/display.rs @@ -0,0 +1,101 @@ +use x11::xlib; +use libc::{c_int, c_char}; +use std::ptr; +use std::fmt; +use std::sync::Arc; +use std::cell::RefCell; +use std::error::Error; + +pub type XErrorHandler = Option<unsafe extern fn(*mut xlib::Display, evptr: *mut xlib::XErrorEvent) -> c_int>; + +struct XConnection { + display: *mut xlib::Display, + last_error: RefCell<Option<XError>>, +} + +#[derive(Debug)] +struct XError { + description: String, + error_code: u8, + request_code: u8, + minor_code: u8, +} + +lazy_static! { + static ref X: Arc<XConnection> = { + match XConnection::new(Some(x_error_handler)) { + Ok(x) => Arc::new(x), + Err(_) => panic!("Error connecting to the X server"), + } + }; +} + +unsafe extern "C" fn x_error_handler(d: *mut xlib::Display, evptr: *mut xlib::XErrorEvent) -> c_int { + let ev = ptr::read(evptr); + let mut buf: [i8; 1024] = [0i8; 1024]; + let bufptr = buf.as_mut_ptr(); + + xlib::XGetErrorText(d, ev.error_code as i32, bufptr as *mut c_char, 1024); + + *X.last_error.borrow_mut() = Some(XError { + description: String::from_raw_parts(bufptr as *mut u8, 1024, 1024), + error_code: ev.error_code, + request_code: ev.request_code, + minor_code: ev.minor_code, + }); + 0 +} + +impl Error for XError { + #[inline] + fn description(&self) -> &str { + &self.description + } +} + +impl fmt::Display for XError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(formatter, "X error: {} (code: {}, request code: {}, minor code: {})", + self.description, self.error_code, self.request_code, self.minor_code) + } +} + +impl XConnection { + /// Open a display. If the string passed by parameter is `""`, it will open the + /// default display. + /// + /// # Failures + /// + /// This function can raise a NulError when the bytes yielded contains an internal + /// 0 byte. + /// + fn new(handler: XErrorHandler) -> Result<XConnection, XError> { + let d = unsafe { xlib::XOpenDisplay(0x0 as *const i8) }; + + unsafe { xlib::XSetErrorHandler(handler) }; + + if d.is_null() { + Err(XError { + description: "Cannot open display!".to_owned(), + error_code: 0, + request_code: 0, + minor_code: 0, + }) + } else { + Ok(XConnection { + display: d, + last_error: RefCell::new(None), + }) + } + } +} + +impl Drop for XConnection { + #[inline] + fn drop(&mut self) { + unsafe { xlib::XCloseDisplay(self.display) }; + } +} + +unsafe impl Send for XConnection {} +unsafe impl Sync for XConnection {} diff --git a/src/safe_x11/mod.rs b/src/safe_x11/mod.rs index 03c54d8..3d08a4e 100644 --- a/src/safe_x11/mod.rs +++ b/src/safe_x11/mod.rs @@ -9,7 +9,6 @@ use x11::xlib::{ XDisplayWidth, XDisplayHeight, XDefaultScreen, XConnectionNumber, - Screen, Cursor, XDefaultRootWindow, XQueryTree, @@ -36,6 +35,7 @@ use std::fmt; use libc::c_int; pub mod window; +pub mod display; #[derive(Debug)] pub struct XSafeError<'a> { @@ -70,29 +70,6 @@ impl<'a> fmt::Display for XSafeError<'a> { } } -/// Open a display. If the string passed by parameter is `""`, it will open the -/// default display. -/// -/// # Failures -/// -/// This function can raise a NulError when the bytes yielded contains an internal -/// 0 byte. -/// -pub fn open_display(display: &str) -> Result<*mut Display, XSafeError> { - let d = if display == "" { - unsafe { xlib::XOpenDisplay(0x0 as *const i8) } - } else { - let cstr = try!(CString::new(display)); - unsafe { xlib::XOpenDisplay(cstr.as_ptr()) } - }; - - if d.is_null() { - Err(XSafeError::new("Cannot open display!")) - } else { - Ok(d) - } -} - pub fn close_display(display: *mut Display) { unsafe { xlib::XCloseDisplay(display); } } |