From 3d692870e25521871067e9756804127bd80f584d Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 26 Mar 2015 17:04:01 +0100 Subject: [PATCH 1/3] Change grab_cursor and ungrab_cursor to set_cursor_state --- examples/grabbing.rs | 12 +++++---- src/android/mod.rs | 7 +++--- src/cocoa/mod.rs | 6 ++++- src/lib.rs | 17 +++++++++++++ src/win32/mod.rs | 9 +++---- src/window.rs | 18 ++++---------- src/x11/window/mod.rs | 58 ++++++++++++++++++++++++++----------------- 7 files changed, 76 insertions(+), 51 deletions(-) diff --git a/examples/grabbing.rs b/examples/grabbing.rs index 436dd9b2..07e38735 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 653ae39a..79590f44 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 c150be0b..58595912 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 bdf79752..3fdf4f33 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 9daf0c3a..41004b35 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 22fd4000..f45cd68e 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() + pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { + self.window.set_cursor_state(state) } - - /// 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/window/mod.rs b/src/x11/window/mod.rs index d5761509..4c2fae83 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>, + 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!(), } } From aaa1c76841f2b895785e0c34ecd8d0c99e16ab23 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 26 Mar 2015 17:33:49 +0100 Subject: [PATCH 2/3] Fix compilation on x11 --- src/x11/window/mod.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs index 4c2fae83..7c93ad33 100644 --- a/src/x11/window/mod.rs +++ b/src/x11/window/mod.rs @@ -283,7 +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>, - cursor_state: CursorState, + cursor_state: Mutex, } impl Window { @@ -603,7 +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, + cursor_state: Mutex::new(CursorState::Normal), }; // returning @@ -786,17 +786,20 @@ impl Window { } pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { - match (state, self.cursor_state) { + let mut cursor_state = self.cursor_state.lock().unwrap(); + + match (state, *cursor_state) { (CursorState::Normal, CursorState::Grab) => { unsafe { ffi::XUngrabPointer(self.x.display, ffi::CurrentTime); - self.cursor_state = CursorState::Normal; + *cursor_state = CursorState::Normal; + Ok(()) } }, (CursorState::Grab, CursorState::Normal) => { unsafe { - self.cursor_state = CursorState::Grab; + *cursor_state = CursorState::Grab; match ffi::XGrabPointer( self.x.display, self.x.window, false, From b27306f97221bb7db52775321abbe3daa0ae9ccb Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 28 Mar 2015 11:07:41 +0100 Subject: [PATCH 3/3] Fix compilation on win32 --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3fdf4f33..7f404c36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,7 @@ extern crate libc; #[cfg(target_os = "windows")] extern crate winapi; #[cfg(target_os = "windows")] -extern crate kernel32_sys as kernel32; +extern crate kernel32; #[cfg(target_os = "windows")] extern crate gdi32_sys as gdi32; #[cfg(target_os = "windows")]