aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortomaka <pierre.krieger1708@gmail.com>2015-03-26 16:48:40 +0100
committertomaka <pierre.krieger1708@gmail.com>2015-03-26 16:48:40 +0100
commitd6ebaaaf5cbb1839e74c3c7c0573b1f842c59e6b (patch)
tree1e09474e9664d06ca0bb5539afe849348bba8c51
parent506c2bca27abbdec446a6683c665025ba4350ae8 (diff)
parent77d033d672d5bcd6e3e933da682467e53414e934 (diff)
downloadglutin-d6ebaaaf5cbb1839e74c3c7c0573b1f842c59e6b.tar.gz
glutin-d6ebaaaf5cbb1839e74c3c7c0573b1f842c59e6b.zip
Merge pull request #227 from aepsil0n/grab-cursor
Implement grabbing of the mouse pointer for X11
-rw-r--r--examples/grabbing.rs50
-rw-r--r--src/android/mod.rs4
-rw-r--r--src/win32/mod.rs8
-rw-r--r--src/window.rs16
-rw-r--r--src/x11/ffi.rs15
-rw-r--r--src/x11/window/mod.rs27
6 files changed, 120 insertions, 0 deletions
diff --git a/examples/grabbing.rs b/examples/grabbing.rs
new file mode 100644
index 0000000..436dd9b
--- /dev/null
+++ b/examples/grabbing.rs
@@ -0,0 +1,50 @@
+#[cfg(target_os = "android")]
+#[macro_use]
+extern crate android_glue;
+
+extern crate glutin;
+
+use glutin::{Event, ElementState};
+
+mod support;
+
+#[cfg(target_os = "android")]
+android_start!(main);
+
+#[cfg(not(feature = "window"))]
+fn main() { println!("This example requires glutin to be compiled with the `window` feature"); }
+
+#[cfg(feature = "window")]
+fn main() {
+
+ let window = glutin::Window::new().unwrap();
+ window.set_title("glutin - Cursor grabbing test");
+ unsafe { window.make_current() };
+
+ let context = support::load(&window);
+ let mut grabbed = false;
+
+ while !window.is_closed() {
+ context.draw_frame((0.0, 1.0, 0.0, 1.0));
+ window.swap_buffers();
+
+ for event in window.poll_events() {
+ match event {
+ Event::KeyboardInput(ElementState::Pressed, _, _) => {
+ if grabbed {
+ grabbed = false;
+ window.ungrab_cursor();
+ }
+ else {
+ grabbed = true;
+ window.grab_cursor().ok().expect("could not grab mouse cursor");
+ }
+ },
+ _ => (),
+ }
+
+ }
+
+ }
+}
+
diff --git a/src/android/mod.rs b/src/android/mod.rs
index 71dae54..653ae39 100644
--- a/src/android/mod.rs
+++ b/src/android/mod.rs
@@ -358,6 +358,10 @@ impl Window {
pub fn set_cursor(&self, _: MouseCursor) {
}
+ pub fn grab_cursor(&self) -> Result<(), String> { Ok(()) }
+
+ pub fn ungrab_cursor(&self) {}
+
pub fn hidpi_factor(&self) -> f32 {
1.0
}
diff --git a/src/win32/mod.rs b/src/win32/mod.rs
index 380342e..9daf0c3 100644
--- a/src/win32/mod.rs
+++ b/src/win32/mod.rs
@@ -255,6 +255,14 @@ impl Window {
unimplemented!()
}
+ pub fn grab_cursor(&self) -> Result<(), String> {
+ unimplemented!()
+ }
+
+ pub fn ungrab_cursor(&self) {
+ unimplemented!()
+ }
+
pub fn hidpi_factor(&self) -> f32 {
1.0
}
diff --git a/src/window.rs b/src/window.rs
index d670e04..22fd400 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -414,6 +414,22 @@ impl Window {
pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
self.window.set_cursor_position(x, y)
}
+
+ /// Grabs the mouse cursor. The cursor's motion will be confined to this
+ /// window and the window has exclusive access to further events regarding
+ /// the cursor.
+ /// Fails if it is not possible to grab the window for some reason, e.g.
+ /// when another window has already done so.
+ /// Has no effect on Android.
+ pub fn grab_cursor(&self) -> Result<(), String> {
+ self.window.grab_cursor()
+ }
+
+ /// Release a previously grabbed mouse cursor.
+ pub fn ungrab_cursor(&self) {
+ self.window.ungrab_cursor();
+ }
+
}
impl gl_common::GlFunctionsSource for Window {
diff --git a/src/x11/ffi.rs b/src/x11/ffi.rs
index 1d91cab..e33ea24 100644
--- a/src/x11/ffi.rs
+++ b/src/x11/ffi.rs
@@ -42,6 +42,17 @@ pub const Button5: libc::c_uint = 5;
pub const InputOutput: libc::c_uint = 1;
pub const InputOnly: libc::c_uint = 2;
+pub const CurrentTime: Time = 0;
+
+pub const GrabModeSync: libc::c_int = 0;
+pub const GrabModeAsync: libc::c_int = 1;
+
+pub const GrabSuccess: libc::c_int = 0;
+pub const AlreadyGrabbed: libc::c_int = 1;
+pub const GrabInvalidTime: libc::c_int = 2;
+pub const GrabNotViewable: libc::c_int = 3;
+pub const GrabFrozen: libc::c_int = 4;
+
pub const CWBackPixmap: libc::c_ulong = (1<<0);
pub const CWBackPixel: libc::c_ulong = (1<<1);
pub const CWBorderPixmap: libc::c_ulong = (1<<2);
@@ -1470,6 +1481,10 @@ extern "C" {
pub fn XcursorLibraryLoadCursor(dpy: *mut Display, name: *const libc::c_char) -> Cursor;
pub fn XDefineCursor(dby: *mut Display, w: Window, cursor: Cursor);
+ pub fn XGrabPointer(dpy: *mut Display, w: Window, owner_events: bool, event_mask: libc::c_long,
+ pointer_mode: libc::c_int, keyboard_mode: libc::c_int, confine_to: Window, cursor: Cursor,
+ time: Time) -> libc::c_int;
+ pub fn XUngrabPointer(dpy: *mut Display, time: Time);
}
/*
diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs
index 385a913..d576150 100644
--- a/src/x11/window/mod.rs
+++ b/src/x11/window/mod.rs
@@ -782,6 +782,33 @@ impl Window {
}
}
+ pub fn grab_cursor(&self) -> Result<(), String> {
+ unsafe {
+ match ffi::XGrabPointer(
+ self.x.display, self.x.window, false,
+ ffi::ButtonPressMask | ffi::ButtonReleaseMask | ffi::EnterWindowMask |
+ ffi::LeaveWindowMask | ffi::PointerMotionMask | ffi::PointerMotionHintMask |
+ ffi::Button1MotionMask | ffi::Button2MotionMask | ffi::Button3MotionMask |
+ ffi::Button4MotionMask | ffi::Button5MotionMask | ffi::ButtonMotionMask |
+ ffi::KeymapStateMask,
+ ffi::GrabModeAsync, ffi::GrabModeAsync,
+ self.x.window, 0, ffi::CurrentTime
+ ) {
+ ffi::GrabSuccess => Ok(()),
+ ffi::AlreadyGrabbed | ffi::GrabInvalidTime |
+ ffi::GrabNotViewable | ffi::GrabFrozen
+ => Err("cursor could not be grabbed".to_string()),
+ _ => unreachable!(),
+ }
+ }
+ }
+
+ pub fn ungrab_cursor(&self) {
+ unsafe {
+ ffi::XUngrabPointer(self.x.display, ffi::CurrentTime);
+ }
+ }
+
pub fn hidpi_factor(&self) -> f32 {
1.0
}