aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dotwm.rs3
-rw-r--r--src/main.rs3
-rw-r--r--src/safe_x11/display.rs101
-rw-r--r--src/safe_x11/mod.rs25
4 files changed, 104 insertions, 28 deletions
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); }
}