From bb418efcc7d5bf38dcb37251ebd1350abb05aba3 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 26 Mar 2015 17:32:40 +0100 Subject: Partially implement cursor state on win32 --- src/win32/init.rs | 5 ++++- src/win32/mod.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 4 deletions(-) (limited to 'src/win32') diff --git a/src/win32/init.rs b/src/win32/init.rs index 08d54c0..c5e18cc 100644 --- a/src/win32/init.rs +++ b/src/win32/init.rs @@ -15,11 +15,13 @@ use Api; use BuilderAttribs; use CreationError; use CreationError::OsError; +use CursorState; use GlRequest; use PixelFormat; use std::ffi::CString; use std::sync::mpsc::channel; +use std::sync::Mutex; use libc; use super::gl; @@ -250,6 +252,7 @@ unsafe fn init(title: Vec, builder: BuilderAttribs<'static>, gl_library: gl_library, events_receiver: events_receiver, is_closed: AtomicBool::new(false), + cursor_state: Mutex::new(CursorState::Normal), }) } @@ -265,7 +268,7 @@ unsafe fn register_window_class() -> Vec { cbWndExtra: 0, hInstance: kernel32::GetModuleHandleW(ptr::null()), hIcon: ptr::null_mut(), - hCursor: ptr::null_mut(), + hCursor: ptr::null_mut(), // must be null in order for cursor state to work properly hbrBackground: ptr::null_mut(), lpszMenuName: ptr::null(), lpszClassName: class_name.as_ptr(), diff --git a/src/win32/mod.rs b/src/win32/mod.rs index 41004b3..113bea1 100644 --- a/src/win32/mod.rs +++ b/src/win32/mod.rs @@ -1,6 +1,8 @@ use std::sync::atomic::AtomicBool; +use std::mem; use std::ptr; use std::ffi::CString; +use std::sync::Mutex; use std::sync::mpsc::Receiver; use libc; use {CreationError, Event, MouseCursor}; @@ -43,6 +45,9 @@ pub struct Window { /// True if a `Closed` event has been received. is_closed: AtomicBool, + + /// The current cursor state. + cursor_state: Mutex, } unsafe impl Send for Window {} @@ -148,7 +153,6 @@ impl Window { /// See the docs in the crate root file. pub fn get_inner_size(&self) -> Option<(u32, u32)> { - use std::mem; let mut rect: winapi::RECT = unsafe { mem::uninitialized() }; if unsafe { user32::GetClientRect(self.window.0, &mut rect) } == 0 { @@ -163,7 +167,6 @@ impl Window { /// See the docs in the crate root file. pub fn get_outer_size(&self) -> Option<(u32, u32)> { - use std::mem; let mut rect: winapi::RECT = unsafe { mem::uninitialized() }; if unsafe { user32::GetWindowRect(self.window.0, &mut rect) } == 0 { @@ -257,7 +260,57 @@ impl Window { } pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { - unimplemented!(); + let mut current_state = self.cursor_state.lock().unwrap(); + + match (state, *current_state) { + (CursorState::Normal, CursorState::Normal) => Ok(()), + (CursorState::Hide, CursorState::Hide) => Ok(()), + (CursorState::Grab, CursorState::Grab) => Ok(()), + + (CursorState::Hide, CursorState::Normal) => { + unsafe { + user32::SetCursor(ptr::null_mut()); + *current_state = CursorState::Hide; + Ok(()) + } + }, + + (CursorState::Normal, CursorState::Hide) => { + unsafe { + user32::SetCursor(user32::LoadCursorW(ptr::null_mut(), winapi::IDC_ARROW)); + *current_state = CursorState::Normal; + Ok(()) + } + }, + + (CursorState::Grab, CursorState::Normal) => { + unsafe { + user32::SetCursor(ptr::null_mut()); + let mut rect = mem::uninitialized(); + if user32::GetWindowRect(self.window.0, &mut rect) == 0 { + return Err(format!("GetWindowRect failed")); + } + if user32::ClipCursor(&rect) == 0 { + return Err(format!("ClipCursor failed")); + } + *current_state = CursorState::Grab; + Ok(()) + } + }, + + (CursorState::Normal, CursorState::Grab) => { + unsafe { + user32::SetCursor(user32::LoadCursorW(ptr::null_mut(), winapi::IDC_ARROW)); + if user32::ClipCursor(ptr::null()) == 0 { + return Err(format!("ClipCursor failed")); + } + *current_state = CursorState::Normal; + Ok(()) + } + }, + + _ => unimplemented!(), + } } pub fn hidpi_factor(&self) -> f32 { -- cgit v1.2.3