From aeed8f256f1f763464dac6305684915e5feca50a Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Wed, 9 Apr 2025 19:04:45 +0200 Subject: [PATCH] xwayland: store and restore primary output --- src/config/mod.rs | 9 +++++++++ src/state.rs | 5 ++++- src/xwayland.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index d48b7f88..61dc42ac 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -163,6 +163,8 @@ pub struct OutputConfig { pub enabled: OutputState, #[serde(default, skip_serializing_if = "Option::is_none")] pub max_bpc: Option, + #[serde(default)] + pub xwayland_primary: bool, } impl Default for OutputConfig { @@ -175,6 +177,7 @@ impl Default for OutputConfig { position: (0, 0), enabled: OutputState::Enabled, max_bpc: None, + xwayland_primary: false, } } } @@ -590,6 +593,12 @@ impl Config { } else { // we don't have a config, so lets generate somewhat sane positions let mut w = 0; + if !outputs.iter().any(|o| o.config().xwayland_primary) { + // if we don't have a primary output for xwayland from a previous config, pick one + if let Some(primary) = outputs.iter().find(|o| o.mirroring().is_none()) { + primary.config_mut().xwayland_primary = true; + } + } for output in outputs.iter().filter(|o| o.mirroring().is_none()) { { let mut config = output.config_mut(); diff --git a/src/state.rs b/src/state.rs index bf8dfb41..c2e12306 100644 --- a/src/state.rs +++ b/src/state.rs @@ -382,7 +382,10 @@ impl BackendData { // Update layout for changes in resolution, scale, orientation shell.workspaces.recalculate(); - loop_handle.insert_idle(|state| state.common.update_xwayland_scale()); + loop_handle.insert_idle(move |state| { + state.common.update_xwayland_scale(); + state.common.update_xwayland_primary_output(); + }); Ok(()) } diff --git a/src/xwayland.rs b/src/xwayland.rs index f59e1654..10c28faa 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -128,6 +128,7 @@ impl State { data.notify_ready(); data.common.update_xwayland_scale(); + data.common.update_xwayland_primary_output(); } XWaylandEvent::Error => { if let Some(mut xwayland_state) = data.common.xwayland_state.take() { @@ -637,6 +638,24 @@ impl Common { } } } + + pub fn update_xwayland_primary_output(&mut self) { + let mut xwayland_primary_output = None; + for output in self.output_configuration_state.outputs() { + if output.config().xwayland_primary { + xwayland_primary_output = Some(output); + break; + } + } + + if let Some(xstate) = self.xwayland_state.as_mut() { + if let Some(xwm) = xstate.xwm.as_mut() { + if let Err(err) = xwm.set_randr_primary_output(xwayland_primary_output.as_ref()) { + warn!("Failed to set xwayland primary output: {}", err); + }; + } + } + } } impl XwmHandler for State { @@ -1115,6 +1134,17 @@ impl XwmHandler for State { } } + fn randr_primary_output_change(&mut self, _xwm: XwmId, output_name: Option) { + for output in self.common.output_configuration_state.outputs() { + output.config_mut().xwayland_primary = + output_name.as_deref().is_some_and(|o| o == output.name()); + } + self.common.output_configuration_state.update(); + self.common + .config + .write_outputs(self.common.output_configuration_state.outputs()); + } + fn disconnected(&mut self, _xwm: XwmId) { let xwayland_state = self.common.xwayland_state.as_mut().unwrap(); xwayland_state.xwm = None;