From 5da38341bc54f24c8cad41f1b63405d8cc955fe7 Mon Sep 17 00:00:00 2001 From: Matias Linares Date: Sun, 22 Nov 2015 02:58:41 -0300 Subject: next_xevent don't block anymore! Now the next_xevent (from the safex11) will not block forever. So we can listen the socket without doing some thread stuff. --- src/event.rs | 8 ++++---- src/main.rs | 9 ++++++--- src/safe_x11/Makefile | 7 +++++++ src/safe_x11/event.rs | 33 +++++++++++++++++++++++++++++++++ src/safe_x11/mod.rs | 14 +------------- src/safe_x11/safex11.c | 32 ++++++++++++++++++++++++++++++++ src/safe_x11/safex11.h | 7 +++++++ 7 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 src/safe_x11/Makefile create mode 100644 src/safe_x11/event.rs create mode 100644 src/safe_x11/safex11.c create mode 100644 src/safe_x11/safex11.h (limited to 'src') 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 +#include +#include + +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 + +int select_next_event(Display *display, int x11_fd, XEvent *retval); + +#endif -- cgit v1.2.3-70-g09d2