From fee2065b64b7468d61ffa1edd3fd78b9c6ef5823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B0=8F=E7=99=BD?= <364772080@qq.com> Date: Sat, 20 Apr 2024 05:40:21 +0800 Subject: [PATCH] windows: Fix main thread blocking when resizing or moving window (#10758) Connection: Fix #10703 https://github.com/zed-industries/zed/assets/14981363/59abfab7-ebb2-4da7-ad13-0a9e42f9c1d3 Release Notes: - N/A --- crates/gpui/src/platform/windows/platform.rs | 12 +++++-- crates/gpui/src/platform/windows/window.rs | 34 +++++++++++++++++++- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index 41baf4fe67..72772e871b 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -78,6 +78,13 @@ impl WindowsPlatformInner { .find(|entry| *entry == &hwnd) .and_then(|hwnd| try_get_window_inner(*hwnd)) } + + #[inline] + pub fn run_foreground_tasks(&self) { + for runnable in self.main_receiver.drain() { + runnable.run(); + } + } } #[derive(Default)] @@ -182,10 +189,9 @@ impl WindowsPlatform { Self { inner } } + #[inline] fn run_foreground_tasks(&self) { - for runnable in self.inner.main_receiver.drain() { - runnable.run(); - } + self.inner.run_foreground_tasks(); } fn redraw_all(&self) { diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index 2cc6b06eed..77b80eed2e 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -253,6 +253,9 @@ impl WindowsWindowInner { WM_CREATE => self.handle_create_msg(lparam), WM_MOVE => self.handle_move_msg(lparam), WM_SIZE => self.handle_size_msg(lparam), + WM_ENTERSIZEMOVE | WM_ENTERMENULOOP => self.handle_size_move_loop(), + WM_EXITSIZEMOVE | WM_EXITMENULOOP => self.handle_size_move_loop_exit(), + WM_TIMER => self.handle_timer_msg(wparam), WM_NCCALCSIZE => self.handle_calc_client_size(wparam, lparam), WM_DPICHANGED => self.handle_dpi_changed_msg(wparam, lparam), WM_NCHITTEST => self.handle_hit_test_msg(msg, wparam, lparam), @@ -342,10 +345,38 @@ impl WindowsWindowInner { let logical_size = logical_size(new_physical_size, scale_factor); callback(logical_size, scale_factor); } - self.invalidate_client_area(); Some(0) } + fn handle_size_move_loop(&self) -> Option { + unsafe { + let ret = SetTimer(self.hwnd, SIZE_MOVE_LOOP_TIMER_ID, USER_TIMER_MINIMUM, None); + if ret == 0 { + log::error!( + "unable to create timer: {}", + std::io::Error::last_os_error() + ); + } + } + None + } + + fn handle_size_move_loop_exit(&self) -> Option { + unsafe { + KillTimer(self.hwnd, SIZE_MOVE_LOOP_TIMER_ID).log_err(); + } + None + } + + fn handle_timer_msg(&self, wparam: WPARAM) -> Option { + if wparam.0 == SIZE_MOVE_LOOP_TIMER_ID { + self.platform_inner.run_foreground_tasks(); + self.handle_paint_msg(); + return Some(0); + } + None + } + fn handle_paint_msg(&self) -> Option { let mut paint_struct = PAINTSTRUCT::default(); let _hdc = unsafe { BeginPaint(self.hwnd, &mut paint_struct) }; @@ -1883,6 +1914,7 @@ const DRAGDROP_GET_FILES_COUNT: u32 = 0xFFFFFFFF; const DOUBLE_CLICK_INTERVAL: Duration = Duration::from_millis(500); // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics const DOUBLE_CLICK_SPATIAL_TOLERANCE: i32 = 4; +const SIZE_MOVE_LOOP_TIMER_ID: usize = 1; #[cfg(test)] mod tests {