srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/core/src/manager
diff options
context:
space:
mode:
Diffstat (limited to 'crates/core/src/manager')
-rw-r--r--crates/core/src/manager/focus.rs16
-rw-r--r--crates/core/src/manager/tests.rs21
2 files changed, 37 insertions, 0 deletions
diff --git a/crates/core/src/manager/focus.rs b/crates/core/src/manager/focus.rs
index 6dae20a..f1473cf 100644
--- a/crates/core/src/manager/focus.rs
+++ b/crates/core/src/manager/focus.rs
@@ -45,6 +45,22 @@ impl WindowManager {
if workspace != self.current_workspace {
self.switch_workspace(workspace);
}
+ // A minimized window's dock icon (or Alt-Tab entry, or any
+ // other `focus_window` caller) has to un-minimize it too, not
+ // just focus it - without this, clicking a minimized app's
+ // dock icon left it focused (keyboard input, `srd clients`'
+ // own `focused: true`) while still `minimized: true`, still
+ // excluded from `visible_windows`/rendering. Reads exactly like
+ // the click did nothing, since the one visible thing "focused"
+ // usually implies (the window coming to the front) never
+ // happens. Every desktop's taskbar/dock has this behavior for
+ // free; this compositor's `Activate` (zwlr-foreign-toplevel)
+ // and `"focus"` IPC handlers both route through here already,
+ // so they get it too rather than each needing their own
+ // explicit restore call.
+ if let Some(w) = self.windows.get_mut(&id) {
+ w.minimized = false;
+ }
self.focused = Some(id);
self.raise_window(id);
}
diff --git a/crates/core/src/manager/tests.rs b/crates/core/src/manager/tests.rs
index 1c80304..aa2fb1a 100644
--- a/crates/core/src/manager/tests.rs
+++ b/crates/core/src/manager/tests.rs
@@ -429,6 +429,27 @@
}
#[test]
+ fn focusing_a_minimized_window_also_restores_it() {
+ // Regression: `focus_window` marked a window focused without
+ // clearing `minimized` - a dock icon's click (foreign-toplevel
+ // `Activate`, or the plain `"focus"` IPC command) both route
+ // through here, so clicking a minimized app's dock icon left it
+ // `focused: true` but still `minimized: true`, still excluded from
+ // `visible_windows`/rendering. Reads exactly like the click did
+ // nothing, since the window never actually reappears.
+ let mut wm = wm_with_monitor();
+ let id = wm.alloc_window_id();
+ wm.add_window(Window::new(id, "a"));
+ wm.minimize_window(id);
+ assert!(wm.window(id).unwrap().minimized, "sanity: actually minimized first");
+
+ wm.focus_window(id);
+ assert!(!wm.window(id).unwrap().minimized, "focusing a minimized window must restore it");
+ assert_eq!(wm.focused_id(), Some(id));
+ assert!(wm.visible_windows().any(|w| w.id == id));
+ }
+
+ #[test]
fn refocusing_an_already_visible_window_does_not_trigger_auto_back_and_forth() {
// The fix above must not call `switch_workspace` unconditionally --
// `switch_workspace`'s own `auto_back_and_forth` handling treats