srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/core/src/manager/focus.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2024-11-30 23:03:00 +0200
committersrdusr <[email protected]>2024-11-30 23:03:00 +0200
commit583063c3094ca0cf9f6cceba92d710b238547f6b (patch)
treea1ff8f181027892f4a45846b67898beb136a9312 /crates/core/src/manager/focus.rs
parent87f5c04b2593dc49409644e69e7962b73d26b9d8 (diff)
downloadsrdwm-583063c3094ca0cf9f6cceba92d710b238547f6b.tar.gz
srdwm-583063c3094ca0cf9f6cceba92d710b238547f6b.zip
Accumulate core-crate additions: capture requests, focus/workspace fixes, test coverage
Bundles several related changes to crates/core built up over this session rather than committed incrementally: - WindowManager::request_capture_workspace/drain_capture_requests (new manager/capture.rs) - backend-agnostic queuing for an off-screen workspace render, see the wayland-side commit for why this exists. - focus_window now switches workspace as a side effect when the target isn't on the current one, matching Hyprland's focuswindow convention (manager/focus.rs). - Assorted window/rules/theme field additions and their test coverage. Left less granular than the repo's usual one-purpose-per-commit convention deliberately: these accumulated across a long session without being committed as they landed, and are too entangled line-by-line to safely split apart now without risking mis-attributing changes to the wrong commit message.
Diffstat (limited to 'crates/core/src/manager/focus.rs')
-rw-r--r--crates/core/src/manager/focus.rs29
1 files changed, 28 insertions, 1 deletions
diff --git a/crates/core/src/manager/focus.rs b/crates/core/src/manager/focus.rs
index c281d7c..6dae20a 100644
--- a/crates/core/src/manager/focus.rs
+++ b/crates/core/src/manager/focus.rs
@@ -17,7 +17,34 @@ impl WindowManager {
}
pub fn focus_window(&mut self, id: WindowId) {
- if self.windows.contains_key(&id) {
+ if let Some(workspace) = self.windows.get(&id).map(|w| w.workspace) {
+ // Switch to the target's workspace first if it isn't already
+ // the active one - without this, focusing a window elsewhere
+ // (Alt-Tab, a dock icon, anything that ends up calling this)
+ // marked it focused while leaving it genuinely off-screen:
+ // `visible_windows`/rendering both gate on `workspace ==
+ // current_workspace`, so keyboard focus landed on a window the
+ // user could not see, while whatever was actually on screen
+ // kept looking focused-ish. Reported live (relayed from the
+ // AGS peer session, who measured it directly over IPC):
+ // `srd dispatch focus` on a window from a different workspace
+ // left `current_workspace` unchanged and the target `visible:
+ // false`. Every caller of `focus_window` gets this for free
+ // rather than each one remembering to switch workspaces
+ // itself first - matches the convention the AGS shell was
+ // already built against (Hyprland's `focuswindow` switches
+ // workspace as a side effect of focusing). Guarded on
+ // `w.workspace != self.current_workspace` specifically, not
+ // just always calling `switch_workspace`: that function's own
+ // `auto_back_and_forth` handling treats being asked to
+ // "switch" to the *already*-current workspace as a deliberate
+ // toggle-to-previous gesture, which an ordinary redundant
+ // focus call (the common case: re-focusing whatever is
+ // already focused and already visible) must not trigger as a
+ // surprise workspace jump.
+ if workspace != self.current_workspace {
+ self.switch_workspace(workspace);
+ }
self.focused = Some(id);
self.raise_window(id);
}