output_configuration: Allow setting xwayland primary output

This commit is contained in:
Victoria Brekenfeld 2025-04-09 20:10:13 +02:00 committed by Victoria Brekenfeld
parent 2e7d051816
commit 2a3bd84e22
4 changed files with 46 additions and 2 deletions

View file

@ -6,6 +6,7 @@ use tracing::{error, warn};
use crate::{
config::{OutputConfig, OutputState},
state::State,
utils::prelude::OutputExt,
wayland::protocols::output_configuration::{
delegate_output_configuration, ModeConfiguration, OutputConfiguration,
OutputConfigurationHandler, OutputConfigurationState,
@ -25,6 +26,17 @@ impl OutputConfigurationHandler for State {
fn apply_configuration(&mut self, conf: Vec<(Output, OutputConfiguration)>) -> bool {
self.output_configuration(false, conf)
}
fn request_xwayland_primary(&mut self, primary_output: Option<Output>) {
for output in self.common.output_configuration_state.outputs() {
output.config_mut().xwayland_primary =
primary_output.as_ref().is_some_and(|o| *o == output);
}
self.common.update_xwayland_primary_output();
self.common
.config
.write_outputs(self.common.output_configuration_state.outputs());
}
}
impl State {

View file

@ -21,7 +21,7 @@ use cosmic_protocols::output_management::v1::server::{
zcosmic_output_manager_v1::{self, ZcosmicOutputManagerV1},
};
use crate::wayland::protocols::output_configuration::*;
use crate::{config::OutputState as EnabledState, wayland::protocols::output_configuration::*};
impl<D> GlobalDispatch<ZcosmicOutputManagerV1, OutputMngrGlobalData, D>
for OutputConfigurationState<D>
@ -109,6 +109,25 @@ where
} => {
data_init.init(extended, config_head.downgrade());
}
zcosmic_output_manager_v1::Request::SetXwaylandPrimary { head } => {
let Some(head) = head else {
state.request_xwayland_primary(None);
return;
};
let inner = state.output_configuration_state();
if let Some(head_data) = inner.instances.iter_mut().find_map(|instance| {
instance
.heads
.iter()
.find(|instance| instance.extension_obj.as_ref() == Some(&head))
}) {
let output = head_data.output.clone();
if output.config().enabled == EnabledState::Enabled {
state.request_xwayland_primary(Some(output));
}
}
}
_ => {}
}
}

View file

@ -58,6 +58,8 @@ pub trait OutputConfigurationHandler: Sized {
fn test_configuration(&mut self, conf: Vec<(Output, OutputConfiguration)>) -> bool;
fn apply_configuration(&mut self, conf: Vec<(Output, OutputConfiguration)>) -> bool;
fn request_xwayland_primary(&mut self, output: Option<Output>);
}
pub struct OutputMngrGlobalData {
@ -189,7 +191,7 @@ where
);
let extension_global = dh.create_global::<D, ZcosmicOutputManagerV1, _>(
2,
3,
OutputMngrGlobalData {
filter: Box::new(client_filter),
},
@ -505,6 +507,14 @@ where
instance.obj.model(physical.model);
}
}
if let Some(extension_obj) = instance.extension_obj.as_ref() {
if inner.enabled
&& extension_obj.version() >= zcosmic_output_head_v1::EVT_XWAYLAND_PRIMARY_SINCE
{
extension_obj.xwayland_primary(output.config().xwayland_primary as u32);
}
}
}
fn remove_global_with_timer<D: 'static>(

View file

@ -652,9 +652,12 @@ impl Common {
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);
return;
};
}
}
self.output_configuration_state.update();
}
}