From b2686424ea0df9acb40f4cd823930d20c18f6318 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Tue, 22 Nov 2022 10:07:17 +0100 Subject: [PATCH] seat: Workaround old active outputs on hotplug --- src/backend/kms/mod.rs | 20 ++++++++++++++--- src/backend/winit.rs | 8 ++++++- src/backend/x11.rs | 9 ++++++-- src/config/mod.rs | 23 +++++++++++++++----- src/shell/focus/mod.rs | 4 ++++ src/shell/mod.rs | 10 ++++++++- src/state.rs | 3 ++- src/wayland/handlers/output_configuration.rs | 3 +++ src/wayland/handlers/screencopy.rs | 3 +++ 9 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 4eedaf78..4b9d37ee 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -33,6 +33,7 @@ use smithay::{ udev::{all_gpus, primary_gpu, UdevBackend, UdevEvent}, }, desktop::utils::OutputPresentationFeedback, + input::Seat, output::{Mode as OutputMode, Output, PhysicalProperties, Subpixel}, reexports::{ calloop::{ @@ -255,10 +256,12 @@ pub fn init_backend( } } + let seats = data.state.common.seats().cloned().collect::>(); data.state.common.config.read_outputs( &mut data.state.common.output_configuration_state, &mut data.state.backend, &mut data.state.common.shell, + seats.into_iter(), &data.state.common.event_loop_handle, ); for surface in data @@ -534,10 +537,12 @@ impl State { self.common .output_configuration_state .add_heads(wl_outputs.iter()); + let seats = self.common.seats().cloned().collect::>(); self.common.config.read_outputs( &mut self.common.output_configuration_state, &mut self.backend, &mut self.common.shell, + seats.into_iter(), &self.common.event_loop_handle, ); @@ -600,13 +605,17 @@ impl State { self.common .output_configuration_state .add_heads(outputs_added.iter()); + let seats = self.common.seats().cloned().collect::>(); for output in outputs_removed { - self.common.shell.remove_output(&output); + self.common + .shell + .remove_output(&output, seats.iter().cloned()); } self.common.config.read_outputs( &mut self.common.output_configuration_state, &mut self.backend, &mut self.common.shell, + seats.into_iter(), &self.common.event_loop_handle, ); @@ -638,14 +647,18 @@ impl State { .output_configuration_state .remove_heads(outputs_removed.iter()); + let seats = self.common.seats().cloned().collect::>(); if self.backend.kms().session.is_active() { for output in outputs_removed { - self.common.shell.remove_output(&output); + self.common + .shell + .remove_output(&output, seats.iter().cloned()); } self.common.config.read_outputs( &mut self.common.output_configuration_state, &mut self.backend, &mut self.common.shell, + seats.into_iter(), &self.common.event_loop_handle, ); } else { @@ -880,6 +893,7 @@ impl KmsState { pub fn apply_config_for_output( &mut self, output: &Output, + seats: impl Iterator>, shell: &mut Shell, test_only: bool, loop_handle: &LoopHandle<'_, Data>, @@ -902,7 +916,7 @@ impl KmsState { if !output_config.enabled { if !test_only { - shell.remove_output(output); + shell.remove_output(output, seats); if surface.surface.take().is_some() { // just drop it surface.pending = false; diff --git a/src/backend/winit.rs b/src/backend/winit.rs index e70c5404..b8bf4cb1 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -211,7 +211,11 @@ pub fn init_backend( } Err(winit::WinitError::WindowClosed) => { let output = data.state.backend.winit().output.clone(); - data.state.common.shell.remove_output(&output); + let seats = data.state.common.seats().cloned().collect::>(); + data.state + .common + .shell + .remove_output(&output, seats.into_iter()); if let Some(token) = token.take() { event_loop_handle.remove(token); } @@ -237,10 +241,12 @@ pub fn init_backend( .output_configuration_state .add_heads(std::iter::once(&output)); state.common.shell.add_output(&output); + let seats = state.common.seats().cloned().collect::>(); state.common.config.read_outputs( &mut state.common.output_configuration_state, &mut state.backend, &mut state.common.shell, + seats.iter().cloned(), &state.common.event_loop_handle, ); diff --git a/src/backend/x11.rs b/src/backend/x11.rs index 1b8b148d..a993418b 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -296,16 +296,18 @@ pub fn init_backend( .output_configuration_state .add_heads(std::iter::once(&output)); state.common.shell.add_output(&output); + let seats = state.common.seats().cloned().collect::>(); state.common.config.read_outputs( &mut state.common.output_configuration_state, &mut state.backend, &mut state.common.shell, + seats.iter().cloned(), &state.common.event_loop_handle, ); event_loop .handle() - .insert_source(backend, |event, _, data| match event { + .insert_source(backend, move |event, _, data| match event { X11Event::CloseRequested { window_id } => { // TODO: drain_filter let mut outputs_removed = Vec::new(); @@ -326,7 +328,10 @@ pub fn init_backend( .surfaces .retain(|s| s.window.id() != window_id); for output in outputs_removed.into_iter() { - data.state.common.shell.remove_output(&output); + data.state + .common + .shell + .remove_output(&output, seats.iter().cloned()); } } X11Event::Resized { diff --git a/src/config/mod.rs b/src/config/mod.rs index 289ff43e..c78eecdb 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -6,6 +6,7 @@ use crate::{ wayland::protocols::output_configuration::OutputConfigurationState, }; use serde::{Deserialize, Serialize}; +use smithay::input::Seat; pub use smithay::{ backend::input::KeyState, input::keyboard::{keysyms as KeySyms, Keysym, ModifiersState}, @@ -282,8 +283,10 @@ impl Config { output_state: &mut OutputConfigurationState, backend: &mut BackendData, shell: &mut Shell, + seats: impl Iterator>, loop_handle: &LoopHandle<'_, Data>, ) { + let seats = seats.collect::>(); let outputs = output_state.outputs().collect::>(); let mut infos = outputs .iter() @@ -314,9 +317,13 @@ impl Config { .get::>() .unwrap() .borrow_mut() = output_config; - if let Err(err) = - backend.apply_config_for_output(&output, false, shell, loop_handle) - { + if let Err(err) = backend.apply_config_for_output( + &output, + false, + shell, + seats.iter().cloned(), + loop_handle, + ) { slog_scope::warn!( "Failed to set new config for output {}: {}", output.name(), @@ -345,9 +352,13 @@ impl Config { .get::>() .unwrap() .borrow_mut() = output_config; - if let Err(err) = - backend.apply_config_for_output(&output, false, shell, loop_handle) - { + if let Err(err) = backend.apply_config_for_output( + &output, + false, + shell, + seats.iter().cloned(), + loop_handle, + ) { slog_scope::error!( "Failed to reset config for output {}: {}", output.name(), diff --git a/src/shell/focus/mod.rs b/src/shell/focus/mod.rs index 6adb1245..611101b3 100644 --- a/src/shell/focus/mod.rs +++ b/src/shell/focus/mod.rs @@ -167,6 +167,10 @@ impl Common { let seats = state.common.seats().cloned().collect::>(); for seat in seats { let output = seat.active_output(); + if !state.common.shell.outputs.contains(&output) { + seat.set_active_output(&state.common.shell.outputs[0]); + continue; + } let last_known_focus = ActiveFocus::get(&seat); if let Some(target) = last_known_focus { diff --git a/src/shell/mod.rs b/src/shell/mod.rs index a6d8fe10..53d9b4b4 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -448,7 +448,15 @@ impl Shell { } } - pub fn remove_output(&mut self, output: &Output) { + pub fn remove_output(&mut self, output: &Output, seats: impl Iterator>) { + if let Some(first_output) = self.outputs.get(0) { + for seat in seats { + if &seat.active_output() == output { + seat.set_active_output(first_output); + } + } + } + if !self.outputs.contains(output) { return; } diff --git a/src/state.rs b/src/state.rs index 991900c2..a1a7d6a4 100644 --- a/src/state.rs +++ b/src/state.rs @@ -141,11 +141,12 @@ impl BackendData { output: &Output, test_only: bool, shell: &mut Shell, + seats: impl Iterator>, loop_handle: &LoopHandle<'_, Data>, ) -> Result<(), anyhow::Error> { let result = match self { BackendData::Kms(ref mut state) => { - state.apply_config_for_output(output, shell, test_only, loop_handle) + state.apply_config_for_output(output, seats, shell, test_only, loop_handle) } BackendData::Winit(ref mut state) => state.apply_config_for_output(output, test_only), BackendData::X11(ref mut state) => state.apply_config_for_output(output, test_only), diff --git a/src/wayland/handlers/output_configuration.rs b/src/wayland/handlers/output_configuration.rs index 48594321..92981de0 100644 --- a/src/wayland/handlers/output_configuration.rs +++ b/src/wayland/handlers/output_configuration.rs @@ -81,10 +81,12 @@ impl State { } } + let seats = self.common.seats().cloned().collect::>(); if let Err(err) = self.backend.apply_config_for_output( output, test_only, &mut self.common.shell, + seats.iter().cloned(), &self.common.event_loop_handle, ) { slog_scope::warn!( @@ -106,6 +108,7 @@ impl State { output, false, &mut self.common.shell, + seats.iter().cloned(), &self.common.event_loop_handle, ) { slog_scope::error!( diff --git a/src/wayland/handlers/screencopy.rs b/src/wayland/handlers/screencopy.rs index 9bab636b..ba065160 100644 --- a/src/wayland/handlers/screencopy.rs +++ b/src/wayland/handlers/screencopy.rs @@ -1018,6 +1018,9 @@ impl State { if !session.alive() { return; } + if !data.state.common.shell.outputs.contains(&output) { + return; + } match render_workspace_to_buffer( &mut data.state, &session,