aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatias Linares <matiaslina@openmailbox.org>2015-11-22 20:02:10 -0300
committerMatias Linares <matiaslina@openmailbox.org>2015-11-22 20:02:10 -0300
commit83b7d0cb4f30c95ce6f27d2c0944727d75eb6e5e (patch)
tree255c9e3f5e0703676382fda1157bdb5daf14bc62
parent47fc031feeddc955e6c7c43410613c75e3370e96 (diff)
downloaddotwm-83b7d0cb4f30c95ce6f27d2c0944727d75eb6e5e.tar.gz
Death to the threads.
All the socket stuff is done syncing it with select calls so we can get either a X11 event or a Socket event. Also cleanup the C mess, it's done all in rust now :).
-rw-r--r--Makefile15
-rw-r--r--src/event.rs55
-rw-r--r--src/main.rs45
-rw-r--r--src/safe_x11/Makefile7
-rw-r--r--src/safe_x11/event.rs33
-rw-r--r--src/safe_x11/mod.rs24
-rw-r--r--src/safe_x11/safex11.c32
-rw-r--r--src/safe_x11/safex11.h7
-rw-r--r--src/socket/mod.rs8
9 files changed, 102 insertions, 124 deletions
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 7050f6d..0000000
--- a/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-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 5a5b1b9..f683c63 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -11,13 +11,29 @@ use x11::xlib::{
XUnmapEvent,
XMapEvent,
XConfigureEvent,
+
+ XPending,
};
use x11::xlib;
use x11::xlib::Display;
+
+use unix_socket::UnixStream;
+use unix_socket::UnixListener;
+
use libc::c_int;
+use libc::{
+ FD_SET,
+ FD_ZERO,
+ FD_ISSET,
+ select,
+ fd_set,
+};
use std::fmt;
+use std::ptr;
+use std::mem::uninitialized;
+use std::cmp::max;
-use safe_x11::event::next_xevent;
+use safe_x11::next_xevent;
pub enum Event {
Key(XKeyEvent, bool),
@@ -31,6 +47,7 @@ pub enum Event {
Unmap(XUnmapEvent),
Map(XMapEvent),
Configure(XConfigureEvent),
+ Socket(UnixStream),
NoEvent
}
@@ -48,6 +65,7 @@ impl fmt::Debug for Event {
&Event::Unmap(ev) => format!("Unmap({})", XEvent::from(ev).get_type()),
&Event::Map(ev) => format!("Map({})", XEvent::from(ev).get_type()),
&Event::Configure(ev) => format!("Configure({})", XEvent::from(ev).get_type()),
+ &Event::Socket(_) => format!("Socket()"),
&Event::NoEvent => format!("NoEvent"),
};
@@ -55,8 +73,39 @@ impl fmt::Debug for Event {
}
}
-pub fn next_event(display: *mut Display, fd: c_int) -> Event {
- let ev = next_xevent(display, fd);
+pub unsafe fn select_event(display: *mut Display, x11fd: c_int, socket_fd: c_int,
+ listener: &UnixListener) -> Event {
+ // Return right now if there're some XEvent on the queue
+ if XPending(display) > 0 {
+ return next_event(display);
+ }
+
+ let mut read_fdset: fd_set = uninitialized();
+
+ FD_ZERO(&mut read_fdset);
+ FD_SET(x11fd, &mut read_fdset);
+ FD_SET(socket_fd, &mut read_fdset);
+
+ select(max(x11fd, socket_fd) + 1,
+ &mut read_fdset, ptr::null_mut(), ptr::null_mut(),
+ ptr::null_mut());
+
+ if FD_ISSET(x11fd, &mut read_fdset) {
+ next_event(display)
+ } else if FD_ISSET(socket_fd, &mut read_fdset) {
+ let mut listener_iter = listener.incoming();
+ if let Some(Ok(stream)) = listener_iter.nth(0) {
+ return Event::Socket(stream)
+ } else {
+ Event::NoEvent
+ }
+ } else {
+ Event::NoEvent
+ }
+}
+
+pub fn next_event(display: *mut Display) -> Event {
+ let ev = next_xevent(display);
match ev.get_type() {
2 => Event::Key(xlib::XKeyEvent::from(ev), true),
diff --git a/src/main.rs b/src/main.rs
index d871288..cd64f87 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -12,9 +12,8 @@ pub mod socket;
use dotwm::DotWM;
use command::*;
-use event::{Event,next_event};
-use socket::listen_socket;
-use safe_x11::event as x11_event;
+use event::{Event,select_event};
+use socket::parser;
use std::collections::HashMap;
@@ -22,15 +21,15 @@ use x11::xlib;
use x11::xlib::XEvent;
use x11::keysym;
-use std::thread;
-use std::sync::mpsc::channel;
+use std::os::unix::io::AsRawFd;
+use std::io::{Read,Write};
use unix_socket::UnixListener;
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);
+ let x11_fd = safe_x11::x11_fd(dotwm.display);
// Resize
add_binding(&mut dotwm,&mut bindings, keysym::XK_h, xlib::Mod4Mask | xlib::ControlMask,
@@ -42,33 +41,18 @@ fn main() {
add_binding(&mut dotwm,&mut bindings, keysym::XK_l, xlib::Mod4Mask | xlib::ControlMask,
resize_win, &["10", "0"]);
+ add_binding(&mut dotwm,&mut bindings, keysym::XK_Return, xlib::Mod4Mask, exec, &["xterm"]);
add_binding(&mut dotwm,&mut bindings, keysym::XK_Tab, xlib::Mod4Mask, focus_next, &[]);
add_binding(&mut dotwm, &mut bindings, keysym::XK_q, xlib::Mod4Mask | xlib::ShiftMask, quit_dotwm, &[]);
- let (transmission, receiver) = channel();
-
- thread::spawn(move || {
- println!("Creating socket");
- let listener = UnixListener::bind("./dotwm.sock").unwrap();
-
- for stream in listener.incoming() {
- match stream {
- Ok(stream) => transmission.send(stream).unwrap() ,
- Err(e) => println!("{}", e),
- }
- }
- });
+ let listener = UnixListener::bind("./dotwm.sock").unwrap();
+ let socket_fd = listener.as_raw_fd();
exec_cmd("./autostart", &[]).unwrap();
// Main loop
loop {
- println!("Listening socket");
- listen_socket(&mut dotwm, &mut bindings, &receiver);
- // Event handling.
- println!("Waiting event");
- let event = next_event(dotwm.display, x11_fd);
- println!("Event {:?}", event);
+ let event = unsafe { select_event(dotwm.display, x11_fd, socket_fd, &listener) };
match event {
Event::Key(mut e, true) => {
let keysym = unsafe { xlib::XLookupKeysym(&mut e, 0) as u32 };
@@ -81,7 +65,6 @@ fn main() {
// be handled by the wm.
let map_event = xlib::XMapEvent::from(e);
if map_event.override_redirect == 0 {
- println!("Adding window");
dotwm.add_window(map_event.window);
} else {
println!("Map event 0 :(");
@@ -95,6 +78,16 @@ fn main() {
dotwm.change_focus_of(idx);
}
},
+ Event::Socket(stream) => {
+ let mut s = stream.try_clone().unwrap();
+ let mut buf = String::new();
+ s.read_to_string(&mut buf).unwrap();
+
+ for line in buf.lines() {
+ let result = parser::parse(&mut dotwm, &mut bindings, &line);
+ let _ = write!(s, "{}", result);
+ }
+ },
_ => println!("Unknown event"),
}
collect_zombies();
diff --git a/src/safe_x11/Makefile b/src/safe_x11/Makefile
deleted file mode 100644
index 4ea8a63..0000000
--- a/src/safe_x11/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-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
deleted file mode 100644
index 8a4bc32..0000000
--- a/src/safe_x11/event.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-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();
- 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 06c7b3c..0283966 100644
--- a/src/safe_x11/mod.rs
+++ b/src/safe_x11/mod.rs
@@ -6,11 +6,15 @@
use x11::xlib;
use x11::xlib::{
Display,
+ XConnectionNumber,
Screen,
Cursor,
XDefaultRootWindow,
XQueryTree,
+ XEvent,
+ XNextEvent,
+
// Windows
Window,
};
@@ -23,9 +27,9 @@ use std::error;
use std::mem::uninitialized;
use std::slice;
use std::fmt;
+use libc::c_int;
pub mod window;
-pub mod event;
#[derive(Debug)]
pub struct XSafeError<'a> {
@@ -89,6 +93,24 @@ pub fn close_display(display: *mut Display) {
unsafe { xlib::XCloseDisplay(display); }
}
+/// 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) -> XEvent {
+ unsafe {
+ let mut last_event: XEvent = uninitialized();
+ XNextEvent(display, &mut last_event);
+ last_event
+ }
+}
+
+
/// Grab pointer buttons.
///
/// # Example
diff --git a/src/safe_x11/safex11.c b/src/safe_x11/safex11.c
deleted file mode 100644
index e4f87d8..0000000
--- a/src/safe_x11/safex11.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#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
deleted file mode 100644
index bbf4e80..0000000
--- a/src/safe_x11/safex11.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _WM_EVENT_H_
-#define _WM_EVENT_H_
-#include <X11/Xlib.h>
-
-int select_next_event(Display *display, int x11_fd, XEvent *retval);
-
-#endif
diff --git a/src/socket/mod.rs b/src/socket/mod.rs
index 804f7ac..e260284 100644
--- a/src/socket/mod.rs
+++ b/src/socket/mod.rs
@@ -10,6 +10,14 @@ use unix_socket::UnixStream;
use dotwm::DotWM;
use command::*;
+pub fn next_socket_event(rx: &Receiver<UnixStream>) -> Option<UnixStream> {
+ match rx.try_recv() {
+ Ok(stream) => Some(stream),
+ Err(TryRecvError::Empty) => None,
+ Err(TryRecvError::Disconnected) => panic!("Socket disconnected"),
+ }
+}
+
/// Listen a socket parsing and executing all the commands.
pub fn listen_socket(dotwm: &mut DotWM, bindings: &mut BindingHash, rx: &Receiver<UnixStream>) {
loop {