aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/grabbing.rs12
-rw-r--r--src/android/mod.rs7
-rw-r--r--src/cocoa/mod.rs6
-rw-r--r--src/lib.rs17
-rw-r--r--src/win32/mod.rs9
-rw-r--r--src/window.rs18
-rw-r--r--src/x11/window/mod.rs58
7 files changed, 76 insertions, 51 deletions
diff --git a/examples/grabbing.rs b/examples/grabbing.rs
index 436dd9b..07e3873 100644
--- a/examples/grabbing.rs
+++ b/examples/grabbing.rs
@@ -1,3 +1,5 @@
+#![feature(std_misc)]
+
#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;
@@ -16,7 +18,6 @@ fn main() { println!("This example requires glutin to be compiled with the `wind
#[cfg(feature = "window")]
fn main() {
-
let window = glutin::Window::new().unwrap();
window.set_title("glutin - Cursor grabbing test");
unsafe { window.make_current() };
@@ -33,11 +34,12 @@ fn main() {
Event::KeyboardInput(ElementState::Pressed, _, _) => {
if grabbed {
grabbed = false;
- window.ungrab_cursor();
- }
- else {
+ window.set_cursor_state(glutin::CursorState::Normal)
+ .ok().expect("could not ungrab mouse cursor");
+ } else {
grabbed = true;
- window.grab_cursor().ok().expect("could not grab mouse cursor");
+ window.set_cursor_state(glutin::CursorState::Grab)
+ .ok().expect("could not grab mouse cursor");
}
},
_ => (),
diff --git a/src/android/mod.rs b/src/android/mod.rs
index 653ae39..79590f4 100644
--- a/src/android/mod.rs
+++ b/src/android/mod.rs
@@ -13,6 +13,7 @@ use std::collections::VecDeque;
use Api;
use BuilderAttribs;
+use CursorState;
use GlRequest;
use native_monitor::NativeMonitorId;
@@ -358,9 +359,9 @@ impl Window {
pub fn set_cursor(&self, _: MouseCursor) {
}
- pub fn grab_cursor(&self) -> Result<(), String> { Ok(()) }
-
- pub fn ungrab_cursor(&self) {}
+ pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
+ Ok(())
+ }
pub fn hidpi_factor(&self) -> f32 {
1.0
diff --git a/src/cocoa/mod.rs b/src/cocoa/mod.rs
index c150be0..5859591 100644
--- a/src/cocoa/mod.rs
+++ b/src/cocoa/mod.rs
@@ -1,7 +1,7 @@
#[cfg(feature = "headless")]
pub use self::headless::HeadlessContext;
-use {CreationError, Event, MouseCursor};
+use {CreationError, Event, MouseCursor, CursorState};
use CreationError::OsError;
use libc;
@@ -661,6 +661,10 @@ impl Window {
}
}
+ pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
+ unimplemented!();
+ }
+
pub fn hidpi_factor(&self) -> f32 {
unsafe {
NSWindow::backingScaleFactor(*self.window) as f32
diff --git a/src/lib.rs b/src/lib.rs
index bdf7975..3fdf4f3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -198,6 +198,23 @@ pub enum MouseCursor {
RowResize,
}
+/// Describes how glutin handles the cursor.
+#[derive(Debug, Copy)]
+pub enum CursorState {
+ /// Normal cursor behavior.
+ Normal,
+
+ /// The cursor will be invisible when over the window.
+ Hide,
+
+ /// 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.
+ ///
+ /// This is useful for first-person cameras for example.
+ Grab,
+}
+
/// Describes a possible format. Unused.
#[allow(missing_docs)]
#[derive(Debug, Clone)]
diff --git a/src/win32/mod.rs b/src/win32/mod.rs
index 9daf0c3..41004b3 100644
--- a/src/win32/mod.rs
+++ b/src/win32/mod.rs
@@ -4,6 +4,7 @@ use std::ffi::CString;
use std::sync::mpsc::Receiver;
use libc;
use {CreationError, Event, MouseCursor};
+use CursorState;
use BuilderAttribs;
@@ -255,12 +256,8 @@ impl Window {
unimplemented!()
}
- pub fn grab_cursor(&self) -> Result<(), String> {
- unimplemented!()
- }
-
- pub fn ungrab_cursor(&self) {
- unimplemented!()
+ pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
+ unimplemented!();
}
pub fn hidpi_factor(&self) -> f32 {
diff --git a/src/window.rs b/src/window.rs
index 22fd400..f45cd68 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -4,6 +4,7 @@ use std::default::Default;
use Api;
use BuilderAttribs;
use CreationError;
+use CursorState;
use Event;
use GlRequest;
use MouseCursor;
@@ -415,21 +416,12 @@ impl Window {
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.
+ /// Sets how glutin handles the cursor. See the documentation of `CursorState` for details.
+ ///
/// 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();
+ pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
+ self.window.set_cursor_state(state)
}
-
}
impl gl_common::GlFunctionsSource for Window {
diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs
index d576150..4c2fae8 100644
--- a/src/x11/window/mod.rs
+++ b/src/x11/window/mod.rs
@@ -11,6 +11,7 @@ use std::sync::{Arc, Mutex, Once, ONCE_INIT, Weak};
use std::sync::{StaticMutex, MUTEX_INIT};
use Api;
+use CursorState;
use GlRequest;
pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
@@ -282,6 +283,7 @@ pub struct Window {
current_size: Cell<(libc::c_int, libc::c_int)>,
/// Events that have been retreived with XLib but not dispatched with iterators yet
pending_events: Mutex<VecDeque<Event>>,
+ cursor_state: CursorState,
}
impl Window {
@@ -601,6 +603,7 @@ impl Window {
wm_delete_window: wm_delete_window,
current_size: Cell::new((0, 0)),
pending_events: Mutex::new(VecDeque::new()),
+ cursor_state: CursorState::Normal,
};
// returning
@@ -782,30 +785,39 @@ 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 set_cursor_state(&self, state: CursorState) -> Result<(), String> {
+ match (state, self.cursor_state) {
+ (CursorState::Normal, CursorState::Grab) => {
+ unsafe {
+ ffi::XUngrabPointer(self.x.display, ffi::CurrentTime);
+ self.cursor_state = CursorState::Normal;
+ }
+ },
- pub fn ungrab_cursor(&self) {
- unsafe {
- ffi::XUngrabPointer(self.x.display, ffi::CurrentTime);
+ (CursorState::Grab, CursorState::Normal) => {
+ unsafe {
+ self.cursor_state = CursorState::Grab;
+
+ 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!(),
+ }
+ }
+ },
+
+ _ => unimplemented!(),
}
}