From ab1e9bf2702f9cd2d525ddd392bb613a282d0fb2 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 10 Dec 2024 11:59:44 -0700 Subject: [PATCH] On windows, recreate renderer swap chain on restore from minimized (#21756) Closes #21688 Release Notes: - Windows: Fix freeze after window minimize and maximize --- crates/gpui/src/platform/blade/blade_renderer.rs | 14 +++++++++++++- crates/gpui/src/platform/windows/events.rs | 15 +++++++++++++-- crates/gpui/src/platform/windows/window.rs | 3 +++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/crates/gpui/src/platform/blade/blade_renderer.rs b/crates/gpui/src/platform/blade/blade_renderer.rs index 5c37caf2cbab0238d43abd31f364d6eb5ce150ef..860a86f2b6254d16b840731d220453add5d9fe46 100644 --- a/crates/gpui/src/platform/blade/blade_renderer.rs +++ b/crates/gpui/src/platform/blade/blade_renderer.rs @@ -431,13 +431,25 @@ impl BladeRenderer { } pub fn update_drawable_size(&mut self, size: Size) { + self.update_drawable_size_impl(size, false); + } + + /// Like `update_drawable_size` but skips the check that the size has changed. This is useful in + /// cases like restoring a window from minimization where the size is the same but the + /// renderer's swap chain needs to be recreated. + #[cfg_attr(any(target_os = "macos", target_os = "linux"), allow(dead_code))] + pub fn update_drawable_size_even_if_unchanged(&mut self, size: Size) { + self.update_drawable_size_impl(size, true); + } + + fn update_drawable_size_impl(&mut self, size: Size, always_resize: bool) { let gpu_size = gpu::Extent { width: size.width.0 as u32, height: size.height.0 as u32, depth: 1, }; - if gpu_size != self.surface_config.size { + if always_resize || gpu_size != self.surface_config.size { self.wait_for_gpu(); self.surface_config.size = gpu_size; self.gpu.resize(self.surface_config); diff --git a/crates/gpui/src/platform/windows/events.rs b/crates/gpui/src/platform/windows/events.rs index 27235d5d406d802e616f22ce304c5111cf512f0d..49c338c7c3a204a299434359d79589b51abf83a5 100644 --- a/crates/gpui/src/platform/windows/events.rs +++ b/crates/gpui/src/platform/windows/events.rs @@ -141,16 +141,27 @@ fn handle_size_msg( lparam: LPARAM, state_ptr: Rc, ) -> Option { + let mut lock = state_ptr.state.borrow_mut(); + + // Don't resize the renderer when the window is minimized, but record that it was minimized so + // that on restore the swap chain can be recreated via `update_drawable_size_even_if_unchanged`. if wparam.0 == SIZE_MINIMIZED as usize { + lock.is_minimized = Some(true); return Some(0); } + let may_have_been_minimized = lock.is_minimized.unwrap_or(true); + lock.is_minimized = Some(false); let width = lparam.loword().max(1) as i32; let height = lparam.hiword().max(1) as i32; - let mut lock = state_ptr.state.borrow_mut(); let new_size = size(DevicePixels(width), DevicePixels(height)); let scale_factor = lock.scale_factor; - lock.renderer.update_drawable_size(new_size); + if may_have_been_minimized { + lock.renderer + .update_drawable_size_even_if_unchanged(new_size); + } else { + lock.renderer.update_drawable_size(new_size); + } let new_size = new_size.to_pixels(scale_factor); lock.logical_size = new_size; if let Some(mut callback) = lock.callbacks.resize.take() { diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index 93671f9b89da75107dd0ab6d256c1d1cec4eada9..a920461d401e0165cc55cee6091f6648f0be9451 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -38,6 +38,7 @@ pub struct WindowsWindowState { pub fullscreen_restore_bounds: Bounds, pub border_offset: WindowBorderOffset, pub scale_factor: f32, + pub is_minimized: Option, pub callbacks: Callbacks, pub input_handler: Option, @@ -92,6 +93,7 @@ impl WindowsWindowState { size: logical_size, }; let border_offset = WindowBorderOffset::default(); + let is_minimized = None; let renderer = windows_renderer::windows_renderer(hwnd, transparent)?; let callbacks = Callbacks::default(); let input_handler = None; @@ -109,6 +111,7 @@ impl WindowsWindowState { fullscreen_restore_bounds, border_offset, scale_factor, + is_minimized, callbacks, input_handler, system_key_handled,