Skip to content

input/seatop_default: focus view on workspace switch - #9161

Open
smlx wants to merge 1 commit into
swaywm:masterfrom
smlx:fix-focus-output-switch
Open

input/seatop_default: focus view on workspace switch#9161
smlx wants to merge 1 commit into
swaywm:masterfrom
smlx:fix-focus-output-switch

Conversation

@smlx

@smlx smlx commented May 25, 2026

Copy link
Copy Markdown
Contributor

When focus_follows_mouse is enabled and the cursor moves from one
output to a layer surface (such as swaybar) on another output, Sway
would previously focus the workspace node.

This change updates workspace switching using either the mouse or
workspace_switch to use seat_get_focus_inactive_view first, ensuring
that the previously focused view on the target workspace receives focus.

Fixes: #8177

@smlx
smlx force-pushed the fix-focus-output-switch branch from 70c76c8 to 2090497 Compare May 25, 2026 14:49
@smlx smlx changed the title fix(input/seatop_default): fix focus on layer surface output switch input/seatop_default: fix focus on layer surface output switch May 25, 2026
@smlx

smlx commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Reproduction steps for the bug this fixes:

  1. have two outputs logically adjacent.
  2. have swaybar in the same position on both (e.g. top or bottom) so that swaybar surfaces are logically adjacent.
  3. open multiple tiled windows on both outputs.
  4. move mouse onto swaybar on one output, then directly onto swaybar on the other output.

On master: the workspace node is focused, so all tiled windows gain blue "active focus" decorations but none have keyboard focus.

With this patch: the previously focused window on that workspace is focused.

This is reproducible in a nested sway session.

Comment thread sway/input/seat.c
struct sway_node *fallback = NULL;
wl_list_for_each(current, &seat->focus_stack, link) {
// prioritize a focused descendant
if (node_has_ancestor(current->node, node)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need a fallback mechanism? Or would it be enough to change this to current->node == node || node_has_ancestor(current->node, node)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I tested both the fallback mechanism and your suggestion and compared it to i3, and neither matches i3's behaviour. I'll rework it.

When `focus_follows_mouse` is enabled and the cursor moves from one
output to a layer surface (such as swaybar) on another output, Sway
would previously focus the workspace node.

This change updates workspace switching using either the mouse or
`workspace_switch` to use `seat_get_focus_inactive_view` first, ensuring
that the previously focused view on the target workspace receives focus.
@smlx
smlx force-pushed the fix-focus-output-switch branch from 2090497 to 637728c Compare July 2, 2026 16:41
@smlx smlx changed the title input/seatop_default: fix focus on layer surface output switch input/seatop_default: focus view on workspace switch Jul 2, 2026
@smlx

smlx commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

I drastically changed the way this patch was implemented and simplified it. From observing i3's behaviour I was previously was trying to fall back to focused descendants.

However after more testing I now realise that i3 is quite aggressive about focusing views only, and not containers. So there is no need to change the way that seat_get_focus_inactive works. Instead now the patch just calls seat_get_focus_inactive_view first, and falls back to seat_get_focus_inactive during a workspace switch.

As far as I can tell, this matches i3's behaviour in this area exactly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

sway marks all windows active if

2 participants