fix: reconcile focus-follows-cursor after workspace switch - #2737
Open
chris-010 wants to merge 1 commit into
Open
fix: reconcile focus-follows-cursor after workspace switch#2737chris-010 wants to merge 1 commit into
chris-010 wants to merge 1 commit into
Conversation
With "focus follows cursor" enabled, switching workspaces left keyboard focus on the newly-active workspace's previously-active window instead of the window under the pointer. Neither staying still nor moving the pointer within that window corrected it -- only a click did. Focus-follows-cursor is implemented solely as an edge-triggered pointer motion handler that compares the element under the old vs new pointer position. A workspace switch moves focus without any pointer motion, so the handler never runs, and the switch actions only call Shell::activate() and never consult focus_follows_cursor. Add State::reconcile_focus_to_pointer(), invoked from the four workspace-switch actions (Workspace, LastWorkspace, NextWorkspace, PreviousWorkspace) on success. When focus-follows-cursor is enabled and the pointer is ungrabbed, it focuses the window under the pointer on the destination workspace, and leaves focus untouched when the pointer is over empty space. It queries the destination workspace's layout directly via Workspace::toplevel_element_under rather than State::element_under: the switch animation (WorkspaceDelta::Shortcut) is still in progress when the action handler runs, and element_under honours the animation offset, so it would resolve the pointer to the outgoing workspace's window. Focusing that off-workspace window is then reverted by Common::refresh_focus to the new workspace's focus-stack top, defeating the reconcile. active_space() is already the destination workspace (the active index is updated synchronously), so its toplevel_element_under ignores the animation and yields the window actually under the pointer; set_focus() then makes it the workspace's focus-stack top, which refresh_focus subsequently keeps. MoveToWorkspace/SendToWorkspace are deliberately left untouched: the moved window should follow and stay focused. Fixes: pop-os/cosmic-epoch#3650 This change was drafted with AI assistance (Claude Code); I have reviewed it, understand it in full, and can respond to review. Signed-off-by: chris-010 <10660568+chris-010@users.noreply.github.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With "focus follows cursor" enabled, switching workspaces left keyboard focus on the newly-active workspace's previously-active window instead of the window under the pointer. Neither holding the pointer still nor moving it within that window corrected it — only a click did.
Focus-follows-cursor is implemented solely as an edge-triggered pointer motion handler that compares the element under the old vs. new pointer position. A workspace switch moves focus without any pointer motion, so the handler never runs, and the switch actions only call
Shell::activate(). A click works because the button handler is level-triggered.This adds
State::reconcile_focus_to_pointer(), invoked from the four workspace-switch actions (Workspace,LastWorkspace,NextWorkspace,PreviousWorkspace) on success. When focus-follows-cursor is enabled and the pointer is ungrabbed, it focuses the window under the pointer on the destination workspace, and leaves focus untouched when the pointer is over empty space.MoveToWorkspace/SendToWorkspaceare deliberately left alone — the moved window should follow and stay focused.Fixes: pop-os/cosmic-epoch#3650
Tested on real hardware (Pop!_OS 24.04, COSMIC, Wayland, ThinkPad T490) and in continuous daily use since 2026-07-15.
Why it queries the destination workspace directly, how this relates to #1366 and #2396, and the test runs
It queries the destination workspace's layout directly via
Workspace::toplevel_element_underrather thanState::element_under: the switch animation is still in progress when the action handler runs, andelement_underhonours the animation offset, so it would resolve the pointer to the outgoing workspace's window, whichCommon::refresh_focusthen reverts. The full reasoning is in the commit message.Related issues
focus_follows_cursoris enabled and touches neither pointer-motion delivery nor click routing.Test runs, with the patched build installed as
/usr/bin/cosmic-comp:Super+Ctrl+Up/Down(NextWorkspace/PreviousWorkspace) → focus follows the pointer.cursor_follows_focusboth disabled and enabled; a plain workspace switch performs no cursor warp.On the base, precisely. That runtime testing was done on a build of
bb584aa, the commit the installed package is built from. For this PR the change was rebased ontomaster(f97a852), where it applies cleanly andcargo check --releasecompletes without warnings; the runtime checks above were not repeated on that newer base.