Skip to content

Conversation

IvanDovgal
Copy link

Prevent focus hijack by XWayland override-redirect tooltips when a Wayland-native window is focused

🐛 Bug Description

This PR fixes an issue in Sway's XWayland focus handling where override-redirect windows (e.g. tooltips from JetBrains IDEs) can steal keyboard focus even when:

  • The currently focused window is a Wayland-native client
  • The user simply moves the mouse pointer over an XWayland window
  • A tooltip appears (typically as an unmanaged override-redirect window)

When this happens, the tooltip grabs focus, but cannot process keyboard input, leading to complete keyboard input loss until the user manually re-focuses another window.

🎯 Root Cause

Sway calls seat_set_focus_surface() unconditionally for unmanaged override-redirect windows that "want focus" (tooltip, dropdown etc..), regardless of whether the current client is related.

This violates ICCCM expectations and breaks focus isolation across clients.

🛠 Fix Summary

This PR introduces a helper: try_focus_unmanaged_local()
It only allows focusing an unmanaged override-redirect surface if the currently focused view has the same PID.
This effectively emulates the ICCCM "LOCAL" input model, where popups/tooltips are only focusable when their parent is active.

✅ Result

  • Tooltips no longer hijack focus when a Wayland-native window is focused
  • Keyboard input remains with the correct window
  • Override-redirect tooltips still work properly when their XWayland parent is active

🧪 Demo and Reproduction

To demonstrate and test this bug, see:

🔗 https://github.com/user-attachments/assets/72fb3929-1ffc-45e1-b3d9-cea58904eae0

🔗 https://github.com/IvanDovgal/override-redirect-bug-demo

This repo includes:

  • A GTK-based Wayland main window
  • An override-redirect X11 tooltip created using python-xlib
  • A minimal example that reproduces the bug and verifies the fix

🔒 Safe Change

This change only affects override-redirect windows, and only in unmanaged XWayland handling. Managed windows and compliant input models are untouched.


Please let me know if anything should be adjusted or clarified!

@kennylevinsen
Copy link
Member

Thanks for the fix!

This effectively emulates the ICCCM "LOCAL" input model, where popups/tooltips are only focusable when their parent is active.

I wonder if we shouldn't first check which ICCCM model is applicable. In your test application, adding a wlr_xwayland_surface_icccm_input_model for the OR window returns WLR_ICCCM_INPUT_MODEL_PASSIVE.

I imagine an OR window with the "none" input model should never receive focus.

@kennylevinsen
Copy link
Member

Note on git history:

  1. Please remove the [FIX] prefix from the commit.
  2. Please avoid merge commits, as we will be rebase-merging this to master if/when all is good and do not want merge commits there. To update your branch, use a rebase.

@IvanDovgal IvanDovgal force-pushed the fix-unmanaged-focus-stealing branch 2 times, most recently from 80e1ca8 to 6d33892 Compare May 6, 2025 17:28
@IvanDovgal IvanDovgal changed the title [FIX] xwayland: avoid focus hijack by override-redirect windows acros… xwayland: avoid focus hijack by override-redirect windows acros… May 6, 2025
@IvanDovgal
Copy link
Author

@kennylevinsen Thanks for your feedback, I've updated the pr as per your request

@IvanDovgal IvanDovgal force-pushed the fix-unmanaged-focus-stealing branch from 6d33892 to 33718c4 Compare May 9, 2025 12:50
@emersion
Copy link
Member

Would this break e.g. dmenu?

@IvanDovgal
Copy link
Author

Would this break e.g. dmenu?

Seems like it breaks initial focus of dmenu. We can fix problem with jetbrains's tooltips if we just will not pass focus to surfaces with iccm_none. What do you think?

@zDEFz
Copy link

zDEFz commented Jun 10, 2025

Having a good experience with this PR.
Needed to ping wlroots https://gitlab.freedesktop.org/wlroots/wlroots.git#branch=0.19

Update: 2 days after - today, I face a weird issue...
Some windows never being removed or something?

image
image

But I think I had variations of this issue, before adding the patch.

@IvanDovgal IvanDovgal closed this Oct 19, 2025
@IvanDovgal IvanDovgal force-pushed the fix-unmanaged-focus-stealing branch from cc1b2c5 to b7eb617 Compare October 19, 2025 18:28
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.

4 participants