diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/android/mod.rs | 7 | ||||
-rw-r--r-- | src/cocoa/mod.rs | 6 | ||||
-rw-r--r-- | src/lib.rs | 19 | ||||
-rw-r--r-- | src/win32/mod.rs | 9 | ||||
-rw-r--r-- | src/window.rs | 18 | ||||
-rw-r--r-- | src/x11/window/mod.rs | 61 |
6 files changed, 73 insertions, 47 deletions
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 @@ -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")] @@ -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..7c93ad3 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: Mutex<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: Mutex::new(CursorState::Normal), }; // returning @@ -782,30 +785,42 @@ 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> { + let mut cursor_state = self.cursor_state.lock().unwrap(); - pub fn ungrab_cursor(&self) { - unsafe { - ffi::XUngrabPointer(self.x.display, ffi::CurrentTime); + match (state, *cursor_state) { + (CursorState::Normal, CursorState::Grab) => { + unsafe { + ffi::XUngrabPointer(self.x.display, ffi::CurrentTime); + *cursor_state = CursorState::Normal; + Ok(()) + } + }, + + (CursorState::Grab, CursorState::Normal) => { + unsafe { + *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!(), } } |