Better events handling on X11

This commit is contained in:
Pierre Krieger 2014-07-28 15:06:38 +02:00
parent c1da2b1273
commit 67349d717a
2 changed files with 87 additions and 57 deletions

View file

@ -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);

View file

@ -141,70 +141,95 @@ impl Window {
}
pub fn poll_events(&self) -> Vec<Event> {
unimplemented!()
use std::mem;
let mut events = Vec::new();
loop {
use std::num::Bounded;
let mut xev = unsafe { mem::uninitialized() };
let res = unsafe { ffi::XCheckMaskEvent(self.display, Bounded::max_value(), &mut xev) };
if res == 0 {
let res = unsafe { ffi::XCheckTypedEvent(self.display, ffi::ClientMessage, &mut xev) };
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;
let mut xev = unsafe { mem::uninitialized() };
unsafe { ffi::XNextEvent(self.display, &mut xev) };
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) };
let mut events = Vec::new();
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));
},
_ => ()
// calling poll_events()
let ev = self.poll_events();
if ev.len() >= 1 {
return ev;
}
}
events
}
pub fn make_current(&self) {