diff --git a/crates/gpui/src/platform/windows/events.rs b/crates/gpui/src/platform/windows/events.rs index 1faf97a01b..1b00d5e59c 100644 --- a/crates/gpui/src/platform/windows/events.rs +++ b/crates/gpui/src/platform/windows/events.rs @@ -62,14 +62,16 @@ pub(crate) fn handle_msg( WM_NCMBUTTONUP => { handle_nc_mouse_up_msg(handle, MouseButton::Middle, wparam, lparam, state_ptr) } - WM_LBUTTONDOWN => handle_mouse_down_msg(MouseButton::Left, lparam, state_ptr), - WM_RBUTTONDOWN => handle_mouse_down_msg(MouseButton::Right, lparam, state_ptr), - WM_MBUTTONDOWN => handle_mouse_down_msg(MouseButton::Middle, lparam, state_ptr), - WM_XBUTTONDOWN => handle_xbutton_msg(wparam, lparam, handle_mouse_down_msg, state_ptr), - WM_LBUTTONUP => handle_mouse_up_msg(MouseButton::Left, lparam, state_ptr), - WM_RBUTTONUP => handle_mouse_up_msg(MouseButton::Right, lparam, state_ptr), - WM_MBUTTONUP => handle_mouse_up_msg(MouseButton::Middle, lparam, state_ptr), - WM_XBUTTONUP => handle_xbutton_msg(wparam, lparam, handle_mouse_up_msg, state_ptr), + WM_LBUTTONDOWN => handle_mouse_down_msg(handle, MouseButton::Left, lparam, state_ptr), + WM_RBUTTONDOWN => handle_mouse_down_msg(handle, MouseButton::Right, lparam, state_ptr), + WM_MBUTTONDOWN => handle_mouse_down_msg(handle, MouseButton::Middle, lparam, state_ptr), + WM_XBUTTONDOWN => { + handle_xbutton_msg(handle, wparam, lparam, handle_mouse_down_msg, state_ptr) + } + WM_LBUTTONUP => handle_mouse_up_msg(handle, MouseButton::Left, lparam, state_ptr), + WM_RBUTTONUP => handle_mouse_up_msg(handle, MouseButton::Right, lparam, state_ptr), + WM_MBUTTONUP => handle_mouse_up_msg(handle, MouseButton::Middle, lparam, state_ptr), + WM_XBUTTONUP => handle_xbutton_msg(handle, wparam, lparam, handle_mouse_up_msg, state_ptr), WM_MOUSEWHEEL => handle_mouse_wheel_msg(handle, wparam, lparam, state_ptr), WM_MOUSEHWHEEL => handle_mouse_horizontal_wheel_msg(handle, wparam, lparam, state_ptr), WM_SYSKEYDOWN => handle_syskeydown_msg(wparam, lparam, state_ptr), @@ -409,10 +411,12 @@ fn handle_char_msg( } fn handle_mouse_down_msg( + handle: HWND, button: MouseButton, lparam: LPARAM, state_ptr: Rc, ) -> Option { + unsafe { SetCapture(handle) }; let mut lock = state_ptr.state.borrow_mut(); if let Some(mut callback) = lock.callbacks.input.take() { let x = lparam.signed_loword() as f32; @@ -443,10 +447,12 @@ fn handle_mouse_down_msg( } fn handle_mouse_up_msg( + _handle: HWND, button: MouseButton, lparam: LPARAM, state_ptr: Rc, ) -> Option { + unsafe { ReleaseCapture().log_err() }; let mut lock = state_ptr.state.borrow_mut(); if let Some(mut callback) = lock.callbacks.input.take() { let x = lparam.signed_loword() as f32; @@ -475,9 +481,10 @@ fn handle_mouse_up_msg( } fn handle_xbutton_msg( + handle: HWND, wparam: WPARAM, lparam: LPARAM, - handler: impl Fn(MouseButton, LPARAM, Rc) -> Option, + handler: impl Fn(HWND, MouseButton, LPARAM, Rc) -> Option, state_ptr: Rc, ) -> Option { let nav_dir = match wparam.hiword() { @@ -485,7 +492,7 @@ fn handle_xbutton_msg( XBUTTON2 => NavigationDirection::Forward, _ => return Some(1), }; - handler(MouseButton::Navigate(nav_dir), lparam, state_ptr) + handler(handle, MouseButton::Navigate(nav_dir), lparam, state_ptr) } fn handle_mouse_wheel_msg( @@ -919,7 +926,7 @@ fn handle_nc_mouse_down_msg( } let mut lock = state_ptr.state.borrow_mut(); - let result = if let Some(mut callback) = lock.callbacks.input.take() { + if let Some(mut callback) = lock.callbacks.input.take() { let scale_factor = lock.scale_factor; let mut cursor_point = POINT { x: lparam.signed_loword().into(), @@ -943,13 +950,25 @@ fn handle_nc_mouse_down_msg( }; state_ptr.state.borrow_mut().callbacks.input = Some(callback); - result + if result.is_some() { + return result; + } } else { - None + drop(lock); }; // Since these are handled in handle_nc_mouse_up_msg we must prevent the default window proc - result.or_else(|| matches!(wparam.0 as u32, HTMINBUTTON | HTMAXBUTTON | HTCLOSE).then_some(0)) + if button == MouseButton::Left { + match wparam.0 as u32 { + HTMINBUTTON => state_ptr.state.borrow_mut().nc_button_pressed = Some(HTMINBUTTON), + HTMAXBUTTON => state_ptr.state.borrow_mut().nc_button_pressed = Some(HTMAXBUTTON), + HTCLOSE => state_ptr.state.borrow_mut().nc_button_pressed = Some(HTCLOSE), + _ => return None, + }; + Some(0) + } else { + None + } } fn handle_nc_mouse_up_msg( @@ -991,24 +1010,41 @@ fn handle_nc_mouse_up_msg( drop(lock); } - if button == MouseButton::Left { + let last_pressed = state_ptr.state.borrow_mut().nc_button_pressed.take(); + if button == MouseButton::Left && last_pressed.is_some() { + let last_button = last_pressed.unwrap(); + let mut handled = false; match wparam.0 as u32 { - HTMINBUTTON => unsafe { - ShowWindowAsync(handle, SW_MINIMIZE).ok().log_err(); - }, - HTMAXBUTTON => unsafe { - if state_ptr.state.borrow().is_maximized() { - ShowWindowAsync(handle, SW_NORMAL).ok().log_err(); - } else { - ShowWindowAsync(handle, SW_MAXIMIZE).ok().log_err(); + HTMINBUTTON => { + if last_button == HTMINBUTTON { + unsafe { ShowWindowAsync(handle, SW_MINIMIZE).ok().log_err() }; + handled = true; } - }, - HTCLOSE => unsafe { - PostMessageW(handle, WM_CLOSE, WPARAM::default(), LPARAM::default()).log_err(); - }, - _ => return None, + } + HTMAXBUTTON => { + if last_button == HTMAXBUTTON { + if state_ptr.state.borrow().is_maximized() { + unsafe { ShowWindowAsync(handle, SW_NORMAL).ok().log_err() }; + } else { + unsafe { ShowWindowAsync(handle, SW_MAXIMIZE).ok().log_err() }; + } + handled = true; + } + } + HTCLOSE => { + if last_button == HTCLOSE { + unsafe { + PostMessageW(handle, WM_CLOSE, WPARAM::default(), LPARAM::default()) + .log_err() + }; + handled = true; + } + } + _ => {} }; - return Some(0); + if handled { + return Some(0); + } } None diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index 21230d0356..99ff1cda9a 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -45,6 +45,7 @@ pub struct WindowsWindowState { pub click_state: ClickState, pub system_settings: WindowsSystemSettings, pub current_cursor: HCURSOR, + pub nc_button_pressed: Option, pub display: WindowsDisplay, fullscreen: Option, @@ -82,6 +83,7 @@ impl WindowsWindowState { let input_handler = None; let click_state = ClickState::new(); let system_settings = WindowsSystemSettings::new(); + let nc_button_pressed = None; let fullscreen = None; Self { @@ -95,6 +97,7 @@ impl WindowsWindowState { click_state, system_settings, current_cursor, + nc_button_pressed, display, fullscreen, hwnd,