xwm: Support sticky requests for unmapped windows

This commit is contained in:
Victoria Brekenfeld 2026-05-18 17:28:27 +02:00 committed by Victoria Brekenfeld
parent 6e4551a200
commit 85630236fa
3 changed files with 39 additions and 17 deletions

View file

@ -249,6 +249,7 @@ pub struct PendingWindow {
pub seat: Seat<State>, pub seat: Seat<State>,
pub fullscreen: Option<Output>, pub fullscreen: Option<Output>,
pub maximized: bool, pub maximized: bool,
pub sticky: bool,
} }
#[derive(Debug)] #[derive(Debug)]
@ -2684,23 +2685,19 @@ impl Shell {
seat, seat,
fullscreen: output, fullscreen: output,
maximized: should_be_maximized, maximized: should_be_maximized,
sticky: mut should_be_sticky,
} = self.pending_windows.remove(pos); } = self.pending_windows.remove(pos);
let parent_is_sticky = if let Some(toplevel) = window.0.toplevel() { if !should_be_sticky
if let Some(parent) = toplevel.parent() { && let Some(toplevel) = window.0.toplevel()
if let Some(elem) = self.element_for_surface(&parent) { && let Some(parent) = toplevel.parent()
self.workspaces && let Some(elem) = self.element_for_surface(&parent)
.sets {
.values() should_be_sticky = self
.any(|set| set.sticky_layer.mapped().any(|m| m == elem)) .workspaces
} else { .sets
false .values()
} .any(|set| set.sticky_layer.mapped().any(|m| m == elem));
} else {
false
}
} else {
false
}; };
let pending_activation = self.pending_activations.remove(&(&window).into()); let pending_activation = self.pending_activations.remove(&(&window).into());
@ -2814,7 +2811,7 @@ impl Shell {
.map(mapped.clone(), Some(focus_stack.iter()), None); .map(mapped.clone(), Some(focus_stack.iter()), None);
} }
if parent_is_sticky { if should_be_sticky {
self.toggle_sticky(&seat, &mapped); self.toggle_sticky(&seat, &mapped);
} }
@ -2824,7 +2821,7 @@ impl Shell {
let new_target = if (workspace_output == seat.active_output() let new_target = if (workspace_output == seat.active_output()
&& active_handle == workspace_handle) && active_handle == workspace_handle)
|| parent_is_sticky || should_be_sticky
{ {
// TODO: enforce focus stealing prevention by also checking the same rules as for the else case. // TODO: enforce focus stealing prevention by also checking the same rules as for the else case.
Some(KeyboardFocusTarget::from(mapped.clone())) Some(KeyboardFocusTarget::from(mapped.clone()))
@ -2955,6 +2952,7 @@ impl Shell {
seat: seat.clone(), seat: seat.clone(),
fullscreen: None, fullscreen: None,
maximized: false, maximized: false,
sticky: false,
}); });
} }
} }

View file

@ -51,6 +51,7 @@ impl XdgShellHandler for State {
seat, seat,
fullscreen: None, fullscreen: None,
maximized: false, maximized: false,
sticky: false,
}) })
} }
// We will position the window after the first commit, when we know its size hints // We will position the window after the first commit, when we know its size hints

View file

@ -815,6 +815,7 @@ impl XwmHandler for State {
seat, seat,
fullscreen: None, fullscreen: None,
maximized: false, maximized: false,
sticky: false,
}) })
} }
} }
@ -1167,6 +1168,28 @@ impl XwmHandler for State {
} }
} }
fn stick_request(&mut self, _xwm: XwmId, window: X11Surface) {
let mut shell = self.common.shell.write();
if let Some(pending) = shell
.pending_windows
.iter_mut()
.find(|pending| pending.surface.x11_surface() == Some(&window))
{
pending.sticky = true;
}
}
fn unstick_request(&mut self, _xwm: XwmId, window: X11Surface) {
let mut shell = self.common.shell.write();
if let Some(pending) = shell
.pending_windows
.iter_mut()
.find(|pending| pending.surface.x11_surface() == Some(&window))
{
pending.sticky = false;
}
}
fn active_window_request( fn active_window_request(
&mut self, &mut self,
_xwm: XwmId, _xwm: XwmId,