aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/x11/window.rs
diff options
context:
space:
mode:
authortomaka <pierre.krieger1708@gmail.com>2015-07-18 19:03:13 +0200
committertomaka <pierre.krieger1708@gmail.com>2015-07-18 19:03:13 +0200
commit7d1d035d9ad5d262a67c6857596caefe957dcfda (patch)
treee1d1181d0a1d5a69730338d3d800cd30dde9d1b9 /src/api/x11/window.rs
parentc1ebb8cf310947d7771c51c4949acedb19c41ee0 (diff)
parentd960753360fdc70e94ce2633db1e03d5ddc7b657 (diff)
downloadglutin-7d1d035d9ad5d262a67c6857596caefe957dcfda.tar.gz
glutin-7d1d035d9ad5d262a67c6857596caefe957dcfda.zip
Merge pull request #510 from robertknight/x11_xinput2
Use XInput2 for event handling
Diffstat (limited to 'src/api/x11/window.rs')
-rw-r--r--src/api/x11/window.rs163
1 files changed, 72 insertions, 91 deletions
diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs
index 15e27ce..b13a94a 100644
--- a/src/api/x11/window.rs
+++ b/src/api/x11/window.rs
@@ -2,6 +2,7 @@ use {Event, BuilderAttribs, MouseCursor};
use CreationError;
use CreationError::OsError;
use libc;
+use std::borrow::Borrow;
use std::{mem, ptr};
use std::cell::Cell;
use std::sync::atomic::AtomicBool;
@@ -20,7 +21,8 @@ use api::egl::Context as EglContext;
use platform::MonitorID as PlatformMonitorID;
-use super::{events, ffi};
+use super::input::XInputEventHandler;
+use super::{ffi};
use super::{MonitorID, XConnection};
// XOpenIM doesn't seem to be thread-safe
@@ -106,33 +108,69 @@ impl WindowProxy {
}
}
+// XEvents of type GenericEvent store their actual data
+// in an XGenericEventCookie data structure. This is a wrapper
+// to extract the cookie from a GenericEvent XEvent and release
+// the cookie data once it has been processed
+struct GenericEventCookie<'a> {
+ display: &'a XConnection,
+ cookie: ffi::XGenericEventCookie
+}
+
+impl<'a> GenericEventCookie<'a> {
+ fn from_event<'b>(display: &'b XConnection, event: ffi::XEvent) -> Option<GenericEventCookie<'b>> {
+ unsafe {
+ let mut cookie: ffi::XGenericEventCookie = From::from(event);
+ if (display.xlib.XGetEventData)(display.display, &mut cookie) == ffi::True {
+ Some(GenericEventCookie{display: display, cookie: cookie})
+ } else {
+ None
+ }
+ }
+ }
+}
+
+impl<'a> Drop for GenericEventCookie<'a> {
+ fn drop(&mut self) {
+ unsafe {
+ let xlib = &self.display.xlib;
+ (xlib.XFreeEventData)(self.display.display, &mut self.cookie);
+ }
+ }
+}
+
pub struct PollEventsIterator<'a> {
- window: &'a Window,
+ window: &'a Window
}
impl<'a> Iterator for PollEventsIterator<'a> {
type Item = Event;
fn next(&mut self) -> Option<Event> {
- if let Some(ev) = self.window.pending_events.lock().unwrap().pop_front() {
- return Some(ev);
- }
+ let xlib = &self.window.x.display.xlib;
loop {
+ if let Some(ev) = self.window.pending_events.lock().unwrap().pop_front() {
+ return Some(ev);
+ }
+
let mut xev = unsafe { mem::uninitialized() };
- let res = unsafe { (self.window.x.display.xlib.XCheckMaskEvent)(self.window.x.display.display, -1, &mut xev) };
+ let res = unsafe { (xlib.XCheckMaskEvent)(self.window.x.display.display, -1, &mut xev) };
if res == 0 {
- let res = unsafe { (self.window.x.display.xlib.XCheckTypedEvent)(self.window.x.display.display, ffi::ClientMessage, &mut xev) };
+ let res = unsafe { (xlib.XCheckTypedEvent)(self.window.x.display.display, ffi::ClientMessage, &mut xev) };
if res == 0 {
- return None;
+ let res = unsafe { (xlib.XCheckTypedEvent)(self.window.x.display.display, ffi::GenericEvent, &mut xev) };
+ if res == 0 {
+ return None;
+ }
}
}
match xev.get_type() {
ffi::KeymapNotify => {
- unsafe { (self.window.x.display.xlib.XRefreshKeyboardMapping)(mem::transmute(&xev)); }
+ unsafe { (xlib.XRefreshKeyboardMapping)(mem::transmute(&xev)); }
},
ffi::ClientMessage => {
@@ -164,93 +202,34 @@ impl<'a> Iterator for PollEventsIterator<'a> {
return Some(Refresh);
},
- ffi::MotionNotify => {
- use events::Event::MouseMoved;
- let event: &ffi::XMotionEvent = unsafe { mem::transmute(&xev) };
- return Some(MouseMoved((event.x as i32, event.y as i32)));
- },
-
- ffi::KeyPress | ffi::KeyRelease => {
- use events::Event::{KeyboardInput, ReceivedCharacter};
- use events::ElementState::{Pressed, Released};
- let event: &mut ffi::XKeyEvent = unsafe { mem::transmute(&mut xev) };
-
- if event.type_ == ffi::KeyPress {
- let raw_ev: *mut ffi::XKeyEvent = event;
- unsafe { (self.window.x.display.xlib.XFilterEvent)(mem::transmute(raw_ev), self.window.x.window) };
- }
-
- let state = if xev.get_type() == ffi::KeyPress { Pressed } else { Released };
-
- let mut kp_keysym = 0;
-
- let written = unsafe {
- use std::str;
-
- let mut buffer: [u8; 16] = [mem::uninitialized(); 16];
- let raw_ev: *mut ffi::XKeyEvent = event;
- let count = (self.window.x.display.xlib.Xutf8LookupString)(self.window.x.ic, mem::transmute(raw_ev),
- mem::transmute(buffer.as_mut_ptr()),
- buffer.len() as libc::c_int, &mut kp_keysym, ptr::null_mut());
-
- str::from_utf8(&buffer[..count as usize]).unwrap_or("").to_string()
- };
-
- {
- let mut pending = self.window.pending_events.lock().unwrap();
- for chr in written.chars() {
- pending.push_back(ReceivedCharacter(chr));
- }
+ ffi::KeyPress | ffi::KeyRelease => {
+ let mut event: &mut ffi::XKeyEvent = unsafe { mem::transmute(&mut xev) };
+ let events = self.window.input_handler.lock().unwrap().translate_key_event(&mut event);
+ for event in events {
+ self.window.pending_events.lock().unwrap().push_back(event);
}
-
- let mut keysym = unsafe {
- (self.window.x.display.xlib.XKeycodeToKeysym)(self.window.x.display.display, event.keycode as ffi::KeyCode, 0)
- };
-
- if (ffi::XK_KP_Space as libc::c_ulong <= keysym) && (keysym <= ffi::XK_KP_9 as libc::c_ulong) {
- keysym = kp_keysym
- };
-
- let vkey = events::keycode_to_element(keysym as libc::c_uint);
-
- return Some(KeyboardInput(state, event.keycode as u8, vkey));
},
- ffi::ButtonPress | ffi::ButtonRelease => {
- use events::Event::{MouseInput, MouseWheel};
- use events::ElementState::{Pressed, Released};
- use events::MouseButton::{Left, Right, Middle};
- use events::MouseScrollDelta::{LineDelta};
-
- let event: &ffi::XButtonEvent = unsafe { mem::transmute(&xev) };
-
- let state = if xev.get_type() == ffi::ButtonPress { Pressed } else { Released };
-
- let button = match event.button {
- ffi::Button1 => Some(Left),
- ffi::Button2 => Some(Middle),
- ffi::Button3 => Some(Right),
- ffi::Button4 => {
- let delta = LineDelta(0.0, 1.0);
- self.window.pending_events.lock().unwrap().push_back(MouseWheel(delta));
- None
- }
- ffi::Button5 => {
- let delta = LineDelta(0.0, -1.0);
- self.window.pending_events.lock().unwrap().push_back(MouseWheel(delta));
- None
+ ffi::GenericEvent => {
+ if let Some(cookie) = GenericEventCookie::from_event(self.window.x.display.borrow(), xev) {
+ match cookie.cookie.evtype {
+ ffi::XI_DeviceChanged...ffi::XI_LASTEVENT => {
+ match self.window.input_handler.lock() {
+ Ok(mut handler) => {
+ match handler.translate_event(&cookie.cookie) {
+ Some(event) => self.window.pending_events.lock().unwrap().push_back(event),
+ None => {}
+ }
+ },
+ Err(_) => {}
+ }
+ },
+ _ => {}
}
- _ => None
- };
-
- match button {
- Some(button) =>
- return Some(MouseInput(state, button)),
- None => ()
- };
- },
+ }
+ }
- _ => ()
+ _ => {}
};
}
}
@@ -296,6 +275,7 @@ pub struct Window {
/// Events that have been retreived with XLib but not dispatched with iterators yet
pending_events: Mutex<VecDeque<Event>>,
cursor_state: Mutex<CursorState>,
+ input_handler: Mutex<XInputEventHandler>
}
impl Window {
@@ -608,6 +588,7 @@ impl Window {
pixel_format: pixel_format,
pending_events: Mutex::new(VecDeque::new()),
cursor_state: Mutex::new(CursorState::Normal),
+ input_handler: Mutex::new(XInputEventHandler::new(display, window, ic))
};
// returning