diff --git a/src/api/win32/callback.rs b/src/api/win32/callback.rs index 2d10699d..e2b74121 100644 --- a/src/api/win32/callback.rs +++ b/src/api/win32/callback.rs @@ -6,7 +6,6 @@ use std::sync::{Arc, Mutex}; use std::ffi::OsString; use std::os::windows::ffi::OsStringExt; -use WindowAttributes; use CursorState; use Event; use super::event; @@ -24,9 +23,14 @@ thread_local!(pub static CONTEXT_STASH: RefCell> = RefCe pub struct ThreadLocalData { pub win: winapi::HWND, pub sender: Sender, - pub window_state: Arc> + pub window_state: Arc>, + pub mouse_in_window: bool } +/// Equivalent to the windows api [MINMAXINFO](https://msdn.microsoft.com/en-us/library/windows/desktop/ms632605%28v=vs.85%29.aspx) +/// struct. Used because winapi-rs doesn't have this declared. +#[repr(C)] +#[allow(dead_code)] struct MinMaxInfo { reserved: winapi::POINT, // Do not use/change max_size: winapi::POINT, @@ -122,15 +126,40 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, winapi::WM_MOUSEMOVE => { use events::Event::MouseMoved; + CONTEXT_STASH.with(|context_stash| { + let mut context_stash = context_stash.borrow_mut(); + if let Some(context_stash) = context_stash.as_mut() { + context_stash.mouse_in_window = true; + } + }); let x = winapi::GET_X_LPARAM(lparam) as i32; let y = winapi::GET_Y_LPARAM(lparam) as i32; + let mut mouse_track = winapi::TRACKMOUSEEVENT { + cbSize: mem::size_of::() as winapi::DWORD, + dwFlags: winapi::TME_HOVER | winapi::TME_LEAVE, + hwndTrack: window, + dwHoverTime: winapi::HOVER_DEFAULT + }; + user32::TrackMouseEvent(&mut mouse_track); + send_event(window, MouseMoved((x, y))); 0 }, + winapi::WM_MOUSELEAVE => { + CONTEXT_STASH.with(|context_stash| { + let mut context_stash = context_stash.borrow_mut(); + if let Some(context_stash) = context_stash.as_mut() { + context_stash.mouse_in_window = false; + } + }); + + 0 + }, + winapi::WM_MOUSEWHEEL => { use events::Event::MouseWheel; use events::MouseScrollDelta::LineDelta; @@ -264,31 +293,36 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_SETCURSOR => { - CONTEXT_STASH.with(|context_stash| { + let call_def_window_proc = CONTEXT_STASH.with(|context_stash| { let cstash = context_stash.borrow(); - let cstash = cstash.as_ref(); - // there's a very bizarre borrow checker bug - // possibly related to rust-lang/rust/#23338 - let _cursor_state = if let Some(cstash) = cstash { + let mut call_def_window_proc = false; + if let Some(cstash) = cstash.as_ref() { if let Ok(window_state) = cstash.window_state.lock() { - match window_state.cursor_state { - CursorState::Normal => { - user32::SetCursor(user32::LoadCursorW( - ptr::null_mut(), - window_state.cursor)); - }, - CursorState::Grab | CursorState::Hide => { - user32::SetCursor(ptr::null_mut()); + if cstash.mouse_in_window { + match window_state.cursor_state { + CursorState::Normal => { + user32::SetCursor(user32::LoadCursorW( + ptr::null_mut(), + window_state.cursor)); + }, + CursorState::Grab | CursorState::Hide => { + user32::SetCursor(ptr::null_mut()); + } } + } else { + call_def_window_proc = true; } } - } else { - return - }; + } -// let &ThreadLocalData { ref cursor_state, .. } = stored; + call_def_window_proc }); - 0 + + if call_def_window_proc { + user32::DefWindowProcW(window, msg, wparam, lparam) + } else { + 0 + } }, winapi::WM_DROPFILES => { @@ -311,7 +345,7 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT, }, winapi::WM_GETMINMAXINFO => { - let mut mmi = lparam as *mut MinMaxInfo; + let mmi = lparam as *mut MinMaxInfo; //(*mmi).max_position = winapi::POINT { x: -8, y: -8 }; // The upper left corner of the window if it were maximized on the primary monitor. //(*mmi).max_size = winapi::POINT { x: .., y: .. }; // The dimensions of the primary monitor. diff --git a/src/api/win32/init.rs b/src/api/win32/init.rs index 79482a3f..bc563847 100644 --- a/src/api/win32/init.rs +++ b/src/api/win32/init.rs @@ -169,7 +169,8 @@ unsafe fn init(title: Vec, window: &WindowAttributes) -> Result