From a5b89bfe5a8deeb70344390ecf551b326de8c72a Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Wed, 20 Dec 2023 18:48:50 +0400 Subject: [PATCH] On Wayland, fix resize being sent on focus change Fixes #3263. --- CHANGELOG.md | 1 + src/platform_impl/linux/wayland/state.rs | 6 ++- .../linux/wayland/window/state.rs | 43 +++++++++++-------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb6ae1045..b62f88c96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Unreleased` header. - On Wayland, disable Client Side Decorations when `wl_subcompositor` is not supported. - On X11, fix `Xft.dpi` detection from Xresources. - On Windows, fix consecutive calls to `window.set_fullscreen(Some(Fullscreen::Borderless(None)))` resulting in losing previous window state when eventually exiting fullscreen using `window.set_fullscreen(None)`. +- On Wayland, fix resize being sent on focus change. # 0.29.4 diff --git a/src/platform_impl/linux/wayland/state.rs b/src/platform_impl/linux/wayland/state.rs index 967ee93f1..8e81c59a1 100644 --- a/src/platform_impl/linux/wayland/state.rs +++ b/src/platform_impl/linux/wayland/state.rs @@ -299,7 +299,11 @@ impl WindowHandler for WinitState { &mut self.events_sink, ); - self.window_compositor_updates[pos].size = Some(new_size); + // NOTE: Only update when the value is `Some` to not override consequent configures with + // the same sizes. + if new_size.is_some() { + self.window_compositor_updates[pos].size = new_size; + } } } diff --git a/src/platform_impl/linux/wayland/window/state.rs b/src/platform_impl/linux/wayland/window/state.rs index 73c0c92c5..7161be891 100644 --- a/src/platform_impl/linux/wayland/window/state.rs +++ b/src/platform_impl/linux/wayland/window/state.rs @@ -256,7 +256,7 @@ impl WindowState { shm: &Shm, subcompositor: &Option>, event_sink: &mut EventSink, - ) -> LogicalSize { + ) -> Option> { // NOTE: when using fractional scaling or wl_compositor@v6 the scaling // should be delivered before the first configure, thus apply it to // properly scale the physical sizes provided by the users. @@ -319,14 +319,9 @@ impl WindowState { match configure.new_size { (Some(width), Some(height)) => { let (width, height) = frame.subtract_borders(width, height); - ( - ( - width.map(|w| w.get()).unwrap_or(1), - height.map(|h| h.get()).unwrap_or(1), - ) - .into(), - false, - ) + let width = width.map(|w| w.get()).unwrap_or(1); + let height = height.map(|h| h.get()).unwrap_or(1); + ((width, height).into(), false) } (_, _) if stateless => (self.stateless_size, true), _ => (self.size, true), @@ -352,13 +347,27 @@ impl WindowState { .unwrap_or(new_size.height); } - // XXX Set the configure before doing a resize. + let new_state = configure.state; + let old_state = self + .last_configure + .as_ref() + .map(|configure| configure.state) + .unwrap_or(XdgWindowState::empty()); + + let state_change_requires_resize = !new_state + .symmetric_difference(old_state) + .difference(XdgWindowState::ACTIVATED | XdgWindowState::SUSPENDED) + .is_empty(); + + // NOTE: Set the configure before doing a resize, since we query it during it. self.last_configure = Some(configure); - // XXX Update the new size right away. - self.resize(new_size); - - new_size + if state_change_requires_resize || new_size != self.inner_size() { + self.resize(new_size); + Some(new_size) + } else { + None + } } /// Compute the bounds for the inner size of the surface. @@ -912,7 +921,7 @@ impl WindowState { /// Set the IME position. pub fn set_ime_cursor_area(&self, position: LogicalPosition, size: LogicalSize) { - // XXX This won't fly unless user will have a way to request IME window per seat, since + // FIXME: This won't fly unless user will have a way to request IME window per seat, since // the ime windows will be overlapping, but winit doesn't expose API to specify for // which seat we're setting IME position. let (x, y) = (position.x as i32, position.y as i32); @@ -943,7 +952,7 @@ impl WindowState { pub fn set_scale_factor(&mut self, scale_factor: f64) { self.scale_factor = scale_factor; - // XXX when fractional scaling is not used update the buffer scale. + // NOTE: When fractional scaling is not used update the buffer scale. if self.fractional_scale.is_none() { let _ = self.window.set_buffer_scale(self.scale_factor as _); } @@ -1091,7 +1100,7 @@ impl From for XdgResizeEdge { } } -// XXX rust doesn't allow from `Option`. +// NOTE: Rust doesn't allow `From>`. #[cfg(feature = "sctk-adwaita")] fn into_sctk_adwaita_config(theme: Option) -> sctk_adwaita::FrameConfig { match theme {