From 925c75cef9abca8ae3197ad86c9e26841fd0bbd1 Mon Sep 17 00:00:00 2001 From: nico4348 Date: Fri, 17 Apr 2026 16:22:21 -0500 Subject: [PATCH] Fix focus loss when destroying a standalone toplevel When a focused xdg-toplevel without a parent surface is destroyed, keyboard focus was cleared with set_focus(None) instead of falling back to focus_history. With focus_follows_mouse enabled and the pointer over empty canvas, this leaves the session with no focused window until the user crosses the pointer onto another surface. Mirror the fallback already used by the XWayland widget path: prefer parent focus, otherwise pick the most recent previous window from focus_history. Fixes #40 --- src/handlers/xdg_shell.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 39245d3..6f5603c 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -193,7 +193,16 @@ impl XdgShellHandler for DriftWm { .is_some_and(|f| f.0 == wl_surface) { let serial = smithay::utils::SERIAL_COUNTER.next_serial(); - keyboard.set_focus(self, parent_focus, serial); + // Standalone toplevels have no parent — fall back to the most + // recent previous window so focus does not vanish (important + // with focus_follows_mouse when the pointer is over empty canvas). + let fallback = parent_focus.or_else(|| { + self.focus_history + .iter() + .find(|w| w != &window) + .and_then(|w| w.wl_surface().map(|s| FocusTarget(s.into_owned()))) + }); + keyboard.set_focus(self, fallback, serial); } // If the destroyed window was fullscreen, restore viewport let fs_output = self.fullscreen.iter()