feat: add config option for xdg activation behavior

This commit is contained in:
Robin Nehls 2026-05-22 17:06:49 +02:00 committed by Victoria Brekenfeld
parent 56f84fba2d
commit 2f7c34f29a
3 changed files with 58 additions and 6 deletions

View file

@ -101,6 +101,7 @@ pub struct CosmicCompConfig {
pub appearance_settings: AppearanceConfig,
/// Hide the cursor after this many seconds of pointer inactivity (None disables)
pub cursor_hide_timeout: Option<u32>,
pub activation_policy: ActivationPolicy,
}
impl Default for CosmicCompConfig {
@ -138,6 +139,7 @@ impl Default for CosmicCompConfig {
accessibility_zoom: ZoomConfig::default(),
appearance_settings: AppearanceConfig::default(),
cursor_hide_timeout: None,
activation_policy: ActivationPolicy::default(),
}
}
}
@ -227,6 +229,14 @@ pub enum EavesdroppingKeyboardMode {
All,
}
#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default, PartialEq, Eq)]
pub enum ActivationPolicy {
#[default]
Focus,
FocusIfActiveWorkspace,
Urgent,
}
#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum XwaylandDescaling {

View file

@ -45,8 +45,8 @@ mod types;
use cosmic::config::CosmicTk;
pub use cosmic_comp_config::EdidProduct;
use cosmic_comp_config::{
AppearanceConfig, CosmicCompConfig, KeyboardConfig, TileBehavior, XkbConfig, XwaylandDescaling,
XwaylandEavesdropping, ZoomConfig,
ActivationPolicy, AppearanceConfig, CosmicCompConfig, KeyboardConfig, TileBehavior, XkbConfig,
XwaylandDescaling, XwaylandEavesdropping, ZoomConfig,
input::{DeviceState as InputDeviceState, InputConfig, TouchpadOverride},
output::comp::{
OutputConfig, OutputInfo, OutputState, OutputsConfig, TransformDef, load_outputs,
@ -966,6 +966,12 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
}
}
}
"activation_policy" => {
let new = get_config::<ActivationPolicy>(&config, "activation_policy");
if new != state.common.config.cosmic_conf.activation_policy {
state.common.config.cosmic_conf.activation_policy = new;
}
}
_ => {}
}
}

View file

@ -5,6 +5,7 @@ use crate::{
state::State,
wayland::protocols::workspace::{State as WState, WorkspaceHandle},
};
use cosmic_comp_config::ActivationPolicy;
use smithay::{
input::Seat,
reexports::wayland_server::protocol::wl_surface::WlSurface,
@ -115,10 +116,45 @@ impl XdgActivationHandler for State {
}
}
ActivationContext::Workspace(_) => {
self.activate_surface(
&surface,
Some((ActivationKey::Wayland(surface.clone()), *context)),
);
match self.common.config.cosmic_conf.activation_policy {
ActivationPolicy::Focus => {
self.activate_surface(
&surface,
Some((ActivationKey::Wayland(surface.clone()), *context)),
);
}
ActivationPolicy::FocusIfActiveWorkspace => {
let shell = self.common.shell.write();
let Some((target_workspace, _)) = shell.workspace_for_surface(&surface)
else {
// surface not found, maybe log warning?
return;
};
let seat = shell.seats.last_active().clone();
let current_output = seat.active_output();
let current_workspace = shell.active_space(&current_output).unwrap().handle;
if target_workspace == current_workspace {
std::mem::drop(shell);
self.activate_surface(
&surface,
Some((ActivationKey::Wayland(surface.clone()), *context)),
);
} else {
let mut workspace_guard = self.common.workspace_state.update();
workspace_guard.add_workspace_state(&target_workspace, WState::Urgent);
}
}
ActivationPolicy::Urgent => {
let shell = self.common.shell.write();
if let Some((workspace, _output)) = shell.workspace_for_surface(&surface) {
let mut workspace_guard = self.common.workspace_state.update();
workspace_guard.add_workspace_state(&workspace, WState::Urgent);
}
}
}
}
}
}