atagen

monolith

public
Star0
Watch0

Commit a3c328d09aeb

tarball

atagen <boss@atagen.co>2026-10-19 10:50 UTC

1 file changed+10-0
activation: drop tokens nobody redeemed

Smithay keeps every xdg-activation token until told otherwise and nothing ever did, so each launch and each token a client asked for stayed in memory for the life of the session.
Modified file: crates/monolith/src/activation.rs+10 additions
@@ -14,6 +14,9 @@ use std::time::Duration;
1414 /// Tokens older than this may still place a window but not focus it.
1515 const FRESH: Duration = Duration::from_secs(10);
1616
17+/// Tokens nobody redeemed by now are dropped.
18+const KEEP: Duration = Duration::from_secs(600);
19+
1720 struct Context {
1821 output: Option<OutputId>,
1922 tag: TagId,
@@ -27,6 +30,7 @@ impl XdgActivationHandler for State {
2730 }
2831
2932 fn token_created(&mut self, _token: XdgActivationToken, data: XdgActivationTokenData) -> bool {
33+ self.expire_tokens();
3034 let keyboard = self.input.seat.get_keyboard();
3135 let focused = keyboard
3236 .as_ref()
@@ -73,6 +77,11 @@ impl XdgActivationHandler for State {
7377 }
7478
7579 impl State {
80+ fn expire_tokens(&mut self) {
81+ let tokens = &mut self.protocols.activation_state;
82+ tokens.retain_tokens(|_, data| data.timestamp.elapsed() < KEEP);
83+ }
84+
7685 /// Where a launch starting now should put its window.
7786 pub fn launch_context(&self) -> (Option<OutputId>, TagId) {
7887 let output = self.wm.layout.active_output();
@@ -83,6 +92,7 @@ impl State {
8392 /// A token for a program monolith starts, carrying the launch context
8493 /// in case its window comes from a process that is not its descendant.
8594 pub fn launch_token(&mut self) -> String {
95+ self.expire_tokens();
8696 let (output, tag) = self.launch_context();
8797 let data = XdgActivationTokenData::default();
8898 data.user_data.insert_if_missing(|| Context {