seat: Workaround old active outputs on hotplug

This commit is contained in:
Victoria Brekenfeld 2022-11-22 10:07:17 +01:00
parent 9c41c80345
commit b2686424ea
9 changed files with 69 additions and 14 deletions

View file

@ -33,6 +33,7 @@ use smithay::{
udev::{all_gpus, primary_gpu, UdevBackend, UdevEvent}, udev::{all_gpus, primary_gpu, UdevBackend, UdevEvent},
}, },
desktop::utils::OutputPresentationFeedback, desktop::utils::OutputPresentationFeedback,
input::Seat,
output::{Mode as OutputMode, Output, PhysicalProperties, Subpixel}, output::{Mode as OutputMode, Output, PhysicalProperties, Subpixel},
reexports::{ reexports::{
calloop::{ calloop::{
@ -255,10 +256,12 @@ pub fn init_backend(
} }
} }
let seats = data.state.common.seats().cloned().collect::<Vec<_>>();
data.state.common.config.read_outputs( data.state.common.config.read_outputs(
&mut data.state.common.output_configuration_state, &mut data.state.common.output_configuration_state,
&mut data.state.backend, &mut data.state.backend,
&mut data.state.common.shell, &mut data.state.common.shell,
seats.into_iter(),
&data.state.common.event_loop_handle, &data.state.common.event_loop_handle,
); );
for surface in data for surface in data
@ -534,10 +537,12 @@ impl State {
self.common self.common
.output_configuration_state .output_configuration_state
.add_heads(wl_outputs.iter()); .add_heads(wl_outputs.iter());
let seats = self.common.seats().cloned().collect::<Vec<_>>();
self.common.config.read_outputs( self.common.config.read_outputs(
&mut self.common.output_configuration_state, &mut self.common.output_configuration_state,
&mut self.backend, &mut self.backend,
&mut self.common.shell, &mut self.common.shell,
seats.into_iter(),
&self.common.event_loop_handle, &self.common.event_loop_handle,
); );
@ -600,13 +605,17 @@ impl State {
self.common self.common
.output_configuration_state .output_configuration_state
.add_heads(outputs_added.iter()); .add_heads(outputs_added.iter());
let seats = self.common.seats().cloned().collect::<Vec<_>>();
for output in outputs_removed { 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( self.common.config.read_outputs(
&mut self.common.output_configuration_state, &mut self.common.output_configuration_state,
&mut self.backend, &mut self.backend,
&mut self.common.shell, &mut self.common.shell,
seats.into_iter(),
&self.common.event_loop_handle, &self.common.event_loop_handle,
); );
@ -638,14 +647,18 @@ impl State {
.output_configuration_state .output_configuration_state
.remove_heads(outputs_removed.iter()); .remove_heads(outputs_removed.iter());
let seats = self.common.seats().cloned().collect::<Vec<_>>();
if self.backend.kms().session.is_active() { if self.backend.kms().session.is_active() {
for output in outputs_removed { 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( self.common.config.read_outputs(
&mut self.common.output_configuration_state, &mut self.common.output_configuration_state,
&mut self.backend, &mut self.backend,
&mut self.common.shell, &mut self.common.shell,
seats.into_iter(),
&self.common.event_loop_handle, &self.common.event_loop_handle,
); );
} else { } else {
@ -880,6 +893,7 @@ impl KmsState {
pub fn apply_config_for_output( pub fn apply_config_for_output(
&mut self, &mut self,
output: &Output, output: &Output,
seats: impl Iterator<Item = Seat<State>>,
shell: &mut Shell, shell: &mut Shell,
test_only: bool, test_only: bool,
loop_handle: &LoopHandle<'_, Data>, loop_handle: &LoopHandle<'_, Data>,
@ -902,7 +916,7 @@ impl KmsState {
if !output_config.enabled { if !output_config.enabled {
if !test_only { if !test_only {
shell.remove_output(output); shell.remove_output(output, seats);
if surface.surface.take().is_some() { if surface.surface.take().is_some() {
// just drop it // just drop it
surface.pending = false; surface.pending = false;

View file

@ -211,7 +211,11 @@ pub fn init_backend(
} }
Err(winit::WinitError::WindowClosed) => { Err(winit::WinitError::WindowClosed) => {
let output = data.state.backend.winit().output.clone(); let output = data.state.backend.winit().output.clone();
data.state.common.shell.remove_output(&output); let seats = data.state.common.seats().cloned().collect::<Vec<_>>();
data.state
.common
.shell
.remove_output(&output, seats.into_iter());
if let Some(token) = token.take() { if let Some(token) = token.take() {
event_loop_handle.remove(token); event_loop_handle.remove(token);
} }
@ -237,10 +241,12 @@ pub fn init_backend(
.output_configuration_state .output_configuration_state
.add_heads(std::iter::once(&output)); .add_heads(std::iter::once(&output));
state.common.shell.add_output(&output); state.common.shell.add_output(&output);
let seats = state.common.seats().cloned().collect::<Vec<_>>();
state.common.config.read_outputs( state.common.config.read_outputs(
&mut state.common.output_configuration_state, &mut state.common.output_configuration_state,
&mut state.backend, &mut state.backend,
&mut state.common.shell, &mut state.common.shell,
seats.iter().cloned(),
&state.common.event_loop_handle, &state.common.event_loop_handle,
); );

View file

@ -296,16 +296,18 @@ pub fn init_backend(
.output_configuration_state .output_configuration_state
.add_heads(std::iter::once(&output)); .add_heads(std::iter::once(&output));
state.common.shell.add_output(&output); state.common.shell.add_output(&output);
let seats = state.common.seats().cloned().collect::<Vec<_>>();
state.common.config.read_outputs( state.common.config.read_outputs(
&mut state.common.output_configuration_state, &mut state.common.output_configuration_state,
&mut state.backend, &mut state.backend,
&mut state.common.shell, &mut state.common.shell,
seats.iter().cloned(),
&state.common.event_loop_handle, &state.common.event_loop_handle,
); );
event_loop event_loop
.handle() .handle()
.insert_source(backend, |event, _, data| match event { .insert_source(backend, move |event, _, data| match event {
X11Event::CloseRequested { window_id } => { X11Event::CloseRequested { window_id } => {
// TODO: drain_filter // TODO: drain_filter
let mut outputs_removed = Vec::new(); let mut outputs_removed = Vec::new();
@ -326,7 +328,10 @@ pub fn init_backend(
.surfaces .surfaces
.retain(|s| s.window.id() != window_id); .retain(|s| s.window.id() != window_id);
for output in outputs_removed.into_iter() { 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 { X11Event::Resized {

View file

@ -6,6 +6,7 @@ use crate::{
wayland::protocols::output_configuration::OutputConfigurationState, wayland::protocols::output_configuration::OutputConfigurationState,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smithay::input::Seat;
pub use smithay::{ pub use smithay::{
backend::input::KeyState, backend::input::KeyState,
input::keyboard::{keysyms as KeySyms, Keysym, ModifiersState}, input::keyboard::{keysyms as KeySyms, Keysym, ModifiersState},
@ -282,8 +283,10 @@ impl Config {
output_state: &mut OutputConfigurationState<State>, output_state: &mut OutputConfigurationState<State>,
backend: &mut BackendData, backend: &mut BackendData,
shell: &mut Shell, shell: &mut Shell,
seats: impl Iterator<Item = Seat<State>>,
loop_handle: &LoopHandle<'_, Data>, loop_handle: &LoopHandle<'_, Data>,
) { ) {
let seats = seats.collect::<Vec<_>>();
let outputs = output_state.outputs().collect::<Vec<_>>(); let outputs = output_state.outputs().collect::<Vec<_>>();
let mut infos = outputs let mut infos = outputs
.iter() .iter()
@ -314,9 +317,13 @@ impl Config {
.get::<RefCell<OutputConfig>>() .get::<RefCell<OutputConfig>>()
.unwrap() .unwrap()
.borrow_mut() = output_config; .borrow_mut() = output_config;
if let Err(err) = if let Err(err) = backend.apply_config_for_output(
backend.apply_config_for_output(&output, false, shell, loop_handle) &output,
{ false,
shell,
seats.iter().cloned(),
loop_handle,
) {
slog_scope::warn!( slog_scope::warn!(
"Failed to set new config for output {}: {}", "Failed to set new config for output {}: {}",
output.name(), output.name(),
@ -345,9 +352,13 @@ impl Config {
.get::<RefCell<OutputConfig>>() .get::<RefCell<OutputConfig>>()
.unwrap() .unwrap()
.borrow_mut() = output_config; .borrow_mut() = output_config;
if let Err(err) = if let Err(err) = backend.apply_config_for_output(
backend.apply_config_for_output(&output, false, shell, loop_handle) &output,
{ false,
shell,
seats.iter().cloned(),
loop_handle,
) {
slog_scope::error!( slog_scope::error!(
"Failed to reset config for output {}: {}", "Failed to reset config for output {}: {}",
output.name(), output.name(),

View file

@ -167,6 +167,10 @@ impl Common {
let seats = state.common.seats().cloned().collect::<Vec<_>>(); let seats = state.common.seats().cloned().collect::<Vec<_>>();
for seat in seats { for seat in seats {
let output = seat.active_output(); 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); let last_known_focus = ActiveFocus::get(&seat);
if let Some(target) = last_known_focus { if let Some(target) = last_known_focus {

View file

@ -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<Item = Seat<State>>) {
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) { if !self.outputs.contains(output) {
return; return;
} }

View file

@ -141,11 +141,12 @@ impl BackendData {
output: &Output, output: &Output,
test_only: bool, test_only: bool,
shell: &mut Shell, shell: &mut Shell,
seats: impl Iterator<Item = Seat<State>>,
loop_handle: &LoopHandle<'_, Data>, loop_handle: &LoopHandle<'_, Data>,
) -> Result<(), anyhow::Error> { ) -> Result<(), anyhow::Error> {
let result = match self { let result = match self {
BackendData::Kms(ref mut state) => { 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::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), BackendData::X11(ref mut state) => state.apply_config_for_output(output, test_only),

View file

@ -81,10 +81,12 @@ impl State {
} }
} }
let seats = self.common.seats().cloned().collect::<Vec<_>>();
if let Err(err) = self.backend.apply_config_for_output( if let Err(err) = self.backend.apply_config_for_output(
output, output,
test_only, test_only,
&mut self.common.shell, &mut self.common.shell,
seats.iter().cloned(),
&self.common.event_loop_handle, &self.common.event_loop_handle,
) { ) {
slog_scope::warn!( slog_scope::warn!(
@ -106,6 +108,7 @@ impl State {
output, output,
false, false,
&mut self.common.shell, &mut self.common.shell,
seats.iter().cloned(),
&self.common.event_loop_handle, &self.common.event_loop_handle,
) { ) {
slog_scope::error!( slog_scope::error!(

View file

@ -1018,6 +1018,9 @@ impl State {
if !session.alive() { if !session.alive() {
return; return;
} }
if !data.state.common.shell.outputs.contains(&output) {
return;
}
match render_workspace_to_buffer( match render_workspace_to_buffer(
&mut data.state, &mut data.state,
&session, &session,