windows: Fix scrolling bug (#12431)

Closes #12369 



https://github.com/zed-industries/zed/assets/14981363/14df820e-9be3-4b89-882b-a083ea42d59e



Release Notes:

- N/A
This commit is contained in:
张小白 2024-06-14 01:48:20 +08:00 committed by GitHub
parent 3c0310273b
commit 22dc88ed3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 68 additions and 29 deletions

View File

@ -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<WindowsWindowStatePtr>,
) -> Option<isize> {
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<WindowsWindowStatePtr>,
) -> Option<isize> {
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<WindowsWindowStatePtr>) -> Option<isize>,
handler: impl Fn(HWND, MouseButton, LPARAM, Rc<WindowsWindowStatePtr>) -> Option<isize>,
state_ptr: Rc<WindowsWindowStatePtr>,
) -> Option<isize> {
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

View File

@ -45,6 +45,7 @@ pub struct WindowsWindowState {
pub click_state: ClickState,
pub system_settings: WindowsSystemSettings,
pub current_cursor: HCURSOR,
pub nc_button_pressed: Option<u32>,
pub display: WindowsDisplay,
fullscreen: Option<StyleAndBounds>,
@ -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,