Fixes cursor behavior with windows

This commit is contained in:
Rengierof 2015-12-26 16:38:00 +02:00
parent f76aba3d37
commit 11e27889ae
4 changed files with 41 additions and 23 deletions

View file

@ -256,7 +256,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
CursorState::Normal => { CursorState::Normal => {
user32::SetCursor(user32::LoadCursorW( user32::SetCursor(user32::LoadCursorW(
ptr::null_mut(), ptr::null_mut(),
winapi::IDC_ARROW)); window_state.cursor));
}, },
CursorState::Grab | CursorState::Hide => { CursorState::Grab | CursorState::Hide => {
user32::SetCursor(ptr::null_mut()); user32::SetCursor(ptr::null_mut());

View file

@ -217,6 +217,7 @@ unsafe fn init(title: Vec<u16>, window: &WindowAttributes, pf_reqs: &PixelFormat
// Creating a mutex to track the current window state // Creating a mutex to track the current window state
let window_state = Arc::new(Mutex::new(WindowState { let window_state = Arc::new(Mutex::new(WindowState {
cursor: winapi::IDC_ARROW, // use arrow by default
cursor_state: CursorState::Normal, cursor_state: CursorState::Normal,
attributes: window.clone() attributes: window.clone()
})); }));

View file

@ -42,9 +42,13 @@ lazy_static! {
static ref WAKEUP_MSG_ID: u32 = unsafe { user32::RegisterWindowMessageA("Glutin::EventID".as_ptr() as *const i8) }; static ref WAKEUP_MSG_ID: u32 = unsafe { user32::RegisterWindowMessageA("Glutin::EventID".as_ptr() as *const i8) };
} }
/// Cursor
pub type Cursor = *const u16;
/// Contains information about states and the window for the callback. /// Contains information about states and the window for the callback.
#[derive(Clone)] #[derive(Clone)]
pub struct WindowState { pub struct WindowState {
pub cursor: Cursor,
pub cursor_state: CursorState, pub cursor_state: CursorState,
pub attributes: WindowAttributes pub attributes: WindowAttributes
} }
@ -261,41 +265,55 @@ impl Window {
#[inline] #[inline]
pub fn set_cursor(&self, _cursor: MouseCursor) { pub fn set_cursor(&self, _cursor: MouseCursor) {
unimplemented!() let cursor_id = match _cursor {
MouseCursor::Arrow | MouseCursor::Default => winapi::IDC_ARROW,
MouseCursor::Hand => winapi::IDC_HAND,
MouseCursor::Crosshair => winapi::IDC_CROSS,
MouseCursor::Text | MouseCursor::VerticalText => winapi::IDC_IBEAM,
MouseCursor::NotAllowed | MouseCursor::NoDrop => winapi::IDC_NO,
MouseCursor::EResize => winapi::IDC_SIZEWE,
MouseCursor::NResize => winapi::IDC_SIZENS,
MouseCursor::WResize => winapi::IDC_SIZEWE,
MouseCursor::SResize => winapi::IDC_SIZENS,
MouseCursor::EwResize | MouseCursor::ColResize => winapi::IDC_SIZEWE,
MouseCursor::NsResize | MouseCursor::RowResize => winapi::IDC_SIZENS,
MouseCursor::Wait | MouseCursor::Progress => winapi::IDC_WAIT,
MouseCursor::Help => winapi::IDC_HELP,
_ => winapi::IDC_ARROW, // use arrow for the missing cases.
};
unsafe {
let mut cur = self.window_state.lock().unwrap();
cur.cursor = mem::transmute(cursor_id);
}
} }
pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
let mut current_state = self.window_state.lock().unwrap().cursor_state; let mut current_state = self.window_state.lock().unwrap();
let foreground_thread_id = unsafe { user32::GetWindowThreadProcessId(self.window.0, ptr::null_mut()) }; let foreground_thread_id = unsafe { user32::GetWindowThreadProcessId(self.window.0, ptr::null_mut()) };
let current_thread_id = unsafe { kernel32::GetCurrentThreadId() }; let current_thread_id = unsafe { kernel32::GetCurrentThreadId() };
unsafe { user32::AttachThreadInput(foreground_thread_id, current_thread_id, 1) }; unsafe { user32::AttachThreadInput(foreground_thread_id, current_thread_id, 1) };
let res = match (state, current_state) { let res = match (state, current_state.cursor_state) {
(CursorState::Normal, CursorState::Normal) => Ok(()), (CursorState::Normal, CursorState::Normal) => Ok(()),
(CursorState::Hide, CursorState::Hide) => Ok(()), (CursorState::Hide, CursorState::Hide) => Ok(()),
(CursorState::Grab, CursorState::Grab) => Ok(()), (CursorState::Grab, CursorState::Grab) => Ok(()),
(CursorState::Hide, CursorState::Normal) => { (CursorState::Hide, CursorState::Normal) => {
unsafe { current_state.cursor_state = CursorState::Hide;
user32::SetCursor(ptr::null_mut());
current_state = CursorState::Hide;
Ok(()) Ok(())
}
}, },
(CursorState::Normal, CursorState::Hide) => { (CursorState::Normal, CursorState::Hide) => {
unsafe { current_state.cursor_state = CursorState::Normal;
user32::SetCursor(user32::LoadCursorW(ptr::null_mut(), winapi::IDC_ARROW));
current_state = CursorState::Normal;
Ok(()) Ok(())
}
}, },
(CursorState::Grab, CursorState::Normal) => { (CursorState::Grab, CursorState::Normal) | (CursorState::Grab, CursorState::Hide) => {
unsafe { unsafe {
user32::SetCursor(ptr::null_mut());
let mut rect = mem::uninitialized(); let mut rect = mem::uninitialized();
if user32::GetClientRect(self.window.0, &mut rect) == 0 { if user32::GetClientRect(self.window.0, &mut rect) == 0 {
return Err(format!("GetWindowRect failed")); return Err(format!("GetWindowRect failed"));
@ -305,18 +323,17 @@ impl Window {
if user32::ClipCursor(&rect) == 0 { if user32::ClipCursor(&rect) == 0 {
return Err(format!("ClipCursor failed")); return Err(format!("ClipCursor failed"));
} }
current_state = CursorState::Grab; current_state.cursor_state = CursorState::Grab;
Ok(()) Ok(())
} }
}, },
(CursorState::Normal, CursorState::Grab) => { (CursorState::Normal, CursorState::Grab) => {
unsafe { unsafe {
user32::SetCursor(user32::LoadCursorW(ptr::null_mut(), winapi::IDC_ARROW));
if user32::ClipCursor(ptr::null()) == 0 { if user32::ClipCursor(ptr::null()) == 0 {
return Err(format!("ClipCursor failed")); return Err(format!("ClipCursor failed"));
} }
current_state = CursorState::Normal; current_state.cursor_state = CursorState::Normal;
Ok(()) Ok(())
} }
}, },