summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile15
-rw-r--r--src/event.rs8
-rw-r--r--src/main.rs9
-rw-r--r--src/safe_x11/Makefile7
-rw-r--r--src/safe_x11/event.rs33
-rw-r--r--src/safe_x11/mod.rs14
-rw-r--r--src/safe_x11/safex11.c32
-rw-r--r--src/safe_x11/safex11.h7
9 files changed, 107 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index 44279aa..b844a08 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
target
dotwm.sock
+*.so
+*.o
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7050f6d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+all:
+ make -C src/safe_x11/
+ mkdir -p target/debug
+ cp src/safe_x11/libsafex11.so target/debug
+ cargo build
+
+release:
+ make -C src/safe_x11/ release
+ mkdir -p target/release
+ cp src/safe_x11/libsafex11.so target/release
+ cargo build --release
+
+clean:
+ make -C src/safe_x11/ clean
+ cargo clean
diff --git a/src/event.rs b/src/event.rs
index 6c4c375..5a5b1b9 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -12,12 +12,12 @@ use x11::xlib::{
XMapEvent,
XConfigureEvent,
};
-
use x11::xlib;
use x11::xlib::Display;
+use libc::c_int;
use std::fmt;
-use safe_x11::next_xevent;
+use safe_x11::event::next_xevent;
pub enum Event {
Key(XKeyEvent, bool),
@@ -55,8 +55,8 @@ impl fmt::Debug for Event {
}
}
-pub fn next_event(display: *mut Display) -> Event {
- let ev = next_xevent(display);
+pub fn next_event(display: *mut Display, fd: c_int) -> Event {
+ let ev = next_xevent(display, fd);
match ev.get_type() {
2 => Event::Key(xlib::XKeyEvent::from(ev), true),
diff --git a/src/main.rs b/src/main.rs
index e652dca..8bf3caa 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -14,6 +14,7 @@ use dotwm::DotWM;
use command::*;
use event::{Event,next_event};
use socket::{configure_wm, listen_socket};
+use safe_x11::event as x11_event;
use std::collections::HashMap;
@@ -29,6 +30,7 @@ fn main() {
println!("Creating dotwm");
let mut dotwm = DotWM::new();
let mut bindings: BindingHash = HashMap::new();
+ let x11_fd = x11_event::x11_fd(dotwm.display);
add_binding(&mut dotwm,&mut bindings, keysym::XK_Return, xlib::Mod4Mask, exec,
&["xterm"]);
@@ -65,14 +67,15 @@ fn main() {
}
}
});
-
configure_wm(&mut dotwm, &receiver);
// Main loop
loop {
+ println!("Listening socket");
listen_socket(&mut dotwm, &receiver);
// Event handling.
- let event = next_event(dotwm.display);
+ println!("Waiting event");
+ let event = next_event(dotwm.display, x11_fd);
println!("Event {:?}", event);
match event {
Event::Key(mut e, true) => {
@@ -100,7 +103,7 @@ fn main() {
dotwm.change_focus_of(idx);
}
},
- _ => (),
+ _ => println!("Unknown event"),
}
collect_zombies();
}
diff --git a/src/safe_x11/Makefile b/src/safe_x11/Makefile
new file mode 100644
index 0000000..4ea8a63
--- /dev/null
+++ b/src/safe_x11/Makefile
@@ -0,0 +1,7 @@
+all:
+ $(CC) -c -fPIC safex11.c -o safex11.o -lX11
+ $(CC) -shared -o libsafex11.so safex11.o -lX11
+
+clean:
+ rm safex11.o
+ rm *.so*
diff --git a/src/safe_x11/event.rs b/src/safe_x11/event.rs
new file mode 100644
index 0000000..2519bad
--- /dev/null
+++ b/src/safe_x11/event.rs
@@ -0,0 +1,33 @@
+use x11::xlib::{
+ XConnectionNumber,
+ Display,
+ XEvent,
+};
+
+use std::mem::uninitialized;
+
+use libc::c_int;
+
+#[link(name = "safex11")]
+extern {
+ /// Get an XEvent if there're one on the queue or wait a little before continue.
+ fn select_next_event(display: *mut Display, x11_fd: c_int, ev: *mut XEvent) -> c_int;
+}
+
+/// Get the file descriptor for the XServer
+pub fn x11_fd(display: *mut Display) -> c_int {
+ unsafe { XConnectionNumber(display) }
+}
+
+/// Get the next event from the xserver. This call will not block forever
+/// (like XNextEvent), instead it will wait for a certain time (1 second
+/// for now, but it can change) so we're not blocking the socket interface
+/// on the main thread.
+pub fn next_xevent(display: *mut Display, fd: c_int) -> XEvent {
+ unsafe {
+ let mut last_event: XEvent = uninitialized();
+ let retval = select_next_event(display, fd, &mut last_event) as i32;
+ last_event
+ }
+}
+
diff --git a/src/safe_x11/mod.rs b/src/safe_x11/mod.rs
index e587021..06c7b3c 100644
--- a/src/safe_x11/mod.rs
+++ b/src/safe_x11/mod.rs
@@ -13,9 +13,6 @@ use x11::xlib::{
// Windows
Window,
-
- // Events
- XEvent,
};
use x11::xlib::XKeyEvent;
@@ -28,6 +25,7 @@ use std::slice;
use std::fmt;
pub mod window;
+pub mod event;
#[derive(Debug)]
pub struct XSafeError<'a> {
@@ -137,16 +135,6 @@ pub fn grab_key(display: *mut Display, key: u32, modifiers: u32, owner_events: b
}
}
-/// Get the next event from the xserver. This call will block until a
-/// event spawns.
-pub fn next_xevent(display: *mut Display) -> XEvent {
- unsafe {
- let mut last_event: XEvent = uninitialized();
- xlib::XNextEvent(display, &mut last_event);
- last_event
- }
-}
-
// Window code.
/// Get a list from the active windows. This doesn't generate a hierarchical
diff --git a/src/safe_x11/safex11.c b/src/safe_x11/safex11.c
new file mode 100644
index 0000000..e4f87d8
--- /dev/null
+++ b/src/safe_x11/safex11.c
@@ -0,0 +1,32 @@
+#include "safex11.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xutil.h>
+
+int select_next_event(Display *display, int x11_fd, XEvent *retval)
+{
+ fd_set in_fds;
+ struct timeval tv;
+ XEvent ev;
+ /* check if there're some events on the queue first of all. */
+ if(XPending(display) > 0)
+ goto EVENT_QUEUED;
+
+ FD_ZERO(&in_fds);
+ FD_SET(x11_fd, &in_fds);
+
+ /* one second */
+ tv.tv_usec = 0;
+ tv.tv_sec = 1;
+
+ /* Wait for X Event or a Timer */
+ if(select(x11_fd+1, &in_fds, 0, 0, &tv))
+ goto EVENT_QUEUED;
+
+ return 0;
+
+EVENT_QUEUED:
+ XNextEvent(display, &ev);
+ *retval = ev;
+ return 1;
+}
diff --git a/src/safe_x11/safex11.h b/src/safe_x11/safex11.h
new file mode 100644
index 0000000..bbf4e80
--- /dev/null
+++ b/src/safe_x11/safex11.h
@@ -0,0 +1,7 @@
+#ifndef _WM_EVENT_H_
+#define _WM_EVENT_H_
+#include <X11/Xlib.h>
+
+int select_next_event(Display *display, int x11_fd, XEvent *retval);
+
+#endif