aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatias Linares <matiaslina@openmailbox.org>2016-05-25 13:18:18 -0300
committerMatias Linares <matiaslina@openmailbox.org>2016-05-25 13:18:18 -0300
commitda3fa00ccf4cde76d1d6489c6043d7e56d4f52c5 (patch)
tree49dbdb5ce9d0baed54ee41a64393b01b6953f2e6
parent77e4450afef9fb5d1acb8f2b690bd5e228f61d8e (diff)
downloaddotwm-da3fa00ccf4cde76d1d6489c6043d7e56d4f52c5.tar.gz
Add a lazy_static connection to the X server
-rw-r--r--Cargo.lock24
-rw-r--r--Cargo.toml2
-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
6 files changed, 117 insertions, 41 deletions
diff --git a/Cargo.lock b/Cargo.lock
index dc6741a..092fc2a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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)",
]
diff --git a/Cargo.toml b/Cargo.toml
index b479ece..5889c87 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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); }
}