aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/x11/ffi.rs5
-rw-r--r--src/x11/mod.rs133
2 files changed, 84 insertions, 54 deletions
diff --git a/src/x11/ffi.rs b/src/x11/ffi.rs
index 553c62e..4a72ca3 100644
--- a/src/x11/ffi.rs
+++ b/src/x11/ffi.rs
@@ -1311,6 +1311,10 @@ pub struct XButtonEvent {
#[link(name = "X11")]
extern "C" {
pub fn XCloseDisplay(display: *mut Display);
+ pub fn XCheckMaskEvent(display: *mut Display, event_mask: libc::c_long,
+ event_return: *mut XEvent) -> Bool;
+ pub fn XCheckTypedEvent(display: *mut Display, event_type: libc::c_int,
+ event_return: *mut XEvent) -> Bool;
pub fn XCreateColormap(display: *mut Display, w: Window,
visual: *mut Visual, alloc: libc::c_int) -> Colormap;
pub fn XCreateWindow(display: *mut Display, parent: Window, x: libc::c_int,
@@ -1329,6 +1333,7 @@ extern "C" {
pub fn XMapWindow(display: *mut Display, w: Window);
pub fn XNextEvent(display: *mut Display, event_return: *mut XEvent);
pub fn XOpenDisplay(display_name: *const libc::c_char) -> *mut Display;
+ pub fn XPeekEvent(display: *mut Display, event_return: *mut XEvent);
pub fn XSetWMProtocols(display: *mut Display, w: Window, protocols: *mut Atom,
count: libc::c_int) -> Status;
pub fn XStoreName(display: *mut Display, w: Window, window_name: *const libc::c_char);
diff --git a/src/x11/mod.rs b/src/x11/mod.rs
index a917fc1..cbb40d5 100644
--- a/src/x11/mod.rs
+++ b/src/x11/mod.rs
@@ -141,72 +141,97 @@ impl Window {
}
pub fn poll_events(&self) -> Vec<Event> {
- unimplemented!()
- }
-
- pub fn wait_events(&self) -> Vec<Event> {
use std::mem;
-
- let mut xev = unsafe { mem::uninitialized() };
- unsafe { ffi::XNextEvent(self.display, &mut xev) };
-
+
let mut events = Vec::new();
- match xev.type_ {
- ffi::ClientMessage => {
- use Closed;
- use std::sync::atomics::Relaxed;
+ loop {
+ use std::num::Bounded;
- let client_msg: &ffi::XClientMessageEvent = unsafe { mem::transmute(&xev) };
+ let mut xev = unsafe { mem::uninitialized() };
+ let res = unsafe { ffi::XCheckMaskEvent(self.display, Bounded::max_value(), &mut xev) };
- if client_msg.l[0] == self.wm_delete_window as libc::c_long {
- self.should_close.store(true, Relaxed);
- events.push(Closed);
- }
- },
-
- ffi::ResizeRequest => {
- use SizeChanged;
- let rs_event: &ffi::XResizeRequestEvent = unsafe { mem::transmute(&xev) };
- events.push(SizeChanged(rs_event.width as uint, rs_event.height as uint));
- },
-
- ffi::MotionNotify => {
- use CursorPositionChanged;
- let event: &ffi::XMotionEvent = unsafe { mem::transmute(&xev) };
- events.push(CursorPositionChanged(event.x as uint, event.y as uint));
- },
-
- ffi::KeyPress | ffi::KeyRelease => {
- use {Pressed, Released};
- let event: &ffi::XKeyEvent = unsafe { mem::transmute(&xev) };
-
- let keysym = unsafe { ffi::XKeycodeToKeysym(self.display, event.keycode as ffi::KeyCode, 0) };
-
- match events::keycode_to_element(keysym as libc::c_uint) {
- Some(elem) if xev.type_ == ffi::KeyPress => {
- events.push(Pressed(elem));
- },
- Some(elem) if xev.type_ == ffi::KeyRelease => {
- events.push(Released(elem));
- },
- _ => ()
- }
- //
- },
+ if res == 0 {
+ let res = unsafe { ffi::XCheckTypedEvent(self.display, ffi::ClientMessage, &mut xev) };
- ffi::ButtonPress | ffi::ButtonRelease => {
- use {Pressed, Released};
- let event: &ffi::XButtonEvent = unsafe { mem::transmute(&xev) };
- //events.push(CursorPositionChanged(event.x as uint, event.y as uint));
- },
+ if res == 0 {
+ break
+ }
+ }
- _ => ()
+ match xev.type_ {
+ ffi::ClientMessage => {
+ use Closed;
+ use std::sync::atomics::Relaxed;
+
+ let client_msg: &ffi::XClientMessageEvent = unsafe { mem::transmute(&xev) };
+
+ if client_msg.l[0] == self.wm_delete_window as libc::c_long {
+ self.should_close.store(true, Relaxed);
+ events.push(Closed);
+ }
+ },
+
+ ffi::ResizeRequest => {
+ use SizeChanged;
+ let rs_event: &ffi::XResizeRequestEvent = unsafe { mem::transmute(&xev) };
+ events.push(SizeChanged(rs_event.width as uint, rs_event.height as uint));
+ },
+
+ ffi::MotionNotify => {
+ use CursorPositionChanged;
+ let event: &ffi::XMotionEvent = unsafe { mem::transmute(&xev) };
+ events.push(CursorPositionChanged(event.x as uint, event.y as uint));
+ },
+
+ ffi::KeyPress | ffi::KeyRelease => {
+ use {Pressed, Released};
+ let event: &ffi::XKeyEvent = unsafe { mem::transmute(&xev) };
+
+ let keysym = unsafe { ffi::XKeycodeToKeysym(self.display, event.keycode as ffi::KeyCode, 0) };
+
+ match events::keycode_to_element(keysym as libc::c_uint) {
+ Some(elem) if xev.type_ == ffi::KeyPress => {
+ events.push(Pressed(elem));
+ },
+ Some(elem) if xev.type_ == ffi::KeyRelease => {
+ events.push(Released(elem));
+ },
+ _ => ()
+ }
+ //
+ },
+
+ ffi::ButtonPress | ffi::ButtonRelease => {
+ use {Pressed, Released};
+ let event: &ffi::XButtonEvent = unsafe { mem::transmute(&xev) };
+ //events.push(CursorPositionChanged(event.x as uint, event.y as uint));
+ },
+
+ _ => ()
+ }
}
events
}
+ pub fn wait_events(&self) -> Vec<Event> {
+ use std::mem;
+
+ loop {
+ // this will block until an event arrives, but doesn't remove
+ // it from the queue
+ let mut xev = unsafe { mem::uninitialized() };
+ unsafe { ffi::XPeekEvent(self.display, &mut xev) };
+
+ // calling poll_events()
+ let ev = self.poll_events();
+ if ev.len() >= 1 {
+ return ev;
+ }
+ }
+ }
+
pub fn make_current(&self) {
let res = unsafe { ffi::glXMakeCurrent(self.display, self.window, self.context) };
if res == 0 {