From 8c4a6ddcb4468a250edd73b5ed2b0af194506cf1 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 14 Dec 2023 18:04:15 +0100 Subject: [PATCH] On Wayland, make `wl_subcompositor` protocol optional This protocol is only used for (optional) Client Side Decorations (where) the compositor still takes the burden of compositing various window parts together, via subsurfaces that all belong to a single window. If this core protocol is not available, as is the case on gamescope, disable CSD. --- CHANGELOG.md | 1 + src/platform_impl/linux/wayland/state.rs | 15 ++++++++++----- src/platform_impl/linux/wayland/window/state.rs | 11 ++++++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90da466bf2..33096f013b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Unreleased` header. misinterpreted during a drag and drop operation. - On X11, fix a bug where focusing the window would panic. - On macOS, fix `refresh_rate_millihertz`. +- On Wayland, disable Client Side Decorations when `wl_subcompositor` is not supported. # 0.29.4 diff --git a/src/platform_impl/linux/wayland/state.rs b/src/platform_impl/linux/wayland/state.rs index afc126bdc0..967ee93f17 100644 --- a/src/platform_impl/linux/wayland/state.rs +++ b/src/platform_impl/linux/wayland/state.rs @@ -50,7 +50,7 @@ pub struct WinitState { pub compositor_state: Arc, /// The state of the subcompositor. - pub subcompositor_state: Arc, + pub subcompositor_state: Option>, /// The seat state responsible for all sorts of input. pub seat_state: SeatState, @@ -124,12 +124,17 @@ impl WinitState { let registry_state = RegistryState::new(globals); let compositor_state = CompositorState::bind(globals, queue_handle).map_err(WaylandError::Bind)?; - let subcompositor_state = SubcompositorState::bind( + let subcompositor_state = match SubcompositorState::bind( compositor_state.wl_compositor().clone(), globals, queue_handle, - ) - .map_err(WaylandError::Bind)?; + ) { + Ok(c) => Some(c), + Err(e) => { + warn!("Subcompositor protocol not available, ignoring CSD: {e:?}"); + None + } + }; let output_state = OutputState::new(globals, queue_handle); let monitors = output_state.outputs().map(MonitorHandle::new).collect(); @@ -151,7 +156,7 @@ impl WinitState { Ok(Self { registry_state, compositor_state: Arc::new(compositor_state), - subcompositor_state: Arc::new(subcompositor_state), + subcompositor_state: subcompositor_state.map(Arc::new), output_state, seat_state, shm: Shm::bind(globals, queue_handle).map_err(WaylandError::Bind)?, diff --git a/src/platform_impl/linux/wayland/window/state.rs b/src/platform_impl/linux/wayland/window/state.rs index 0b04ce932e..bee813f1bf 100644 --- a/src/platform_impl/linux/wayland/window/state.rs +++ b/src/platform_impl/linux/wayland/window/state.rs @@ -254,7 +254,7 @@ impl WindowState { &mut self, configure: WindowConfigure, shm: &Shm, - subcompositor: &Arc, + subcompositor: &Option>, event_sink: &mut EventSink, ) -> LogicalSize { // NOTE: when using fractional scaling or wl_compositor@v6 the scaling @@ -265,10 +265,11 @@ impl WindowState { self.stateless_size = self.size; } - if configure.decoration_mode == DecorationMode::Client - && self.frame.is_none() - && !self.csd_fails - { + if let Some(subcompositor) = subcompositor.as_ref().filter(|_| { + configure.decoration_mode == DecorationMode::Client + && self.frame.is_none() + && !self.csd_fails + }) { match WinitFrame::new( &self.window, shm,