Skip to content

xwayland: map a held pointer through the monitor under the cursor - #16579

Closed
donutinit wants to merge 1 commit into
hyprwm:mainfrom
donutinit:xwayland-pointer-across-monitors
Closed

donutinit wants to merge 1 commit into
hyprwm:mainfrom
donutinit:xwayland-pointer-across-monitors

Conversation

@donutinit

Copy link
Copy Markdown

I use a music player to manage my sound-effect collection, on i3wm I dragged and dropped files from the player to DaVinci Resolve. When I tried to do that on wayland Davinci's windows flickered strangely, the solution was to launch the music player in Xwayland; but it came with a catch, i could only drag and drop from the same monitor. With some thinkering I figured out that the problem was that Xwayland was treating the window/displays positioning different as the hyprland config.

I traced it to mouseMoveUnified in InputManager.cpp: while a button is held the pointer focus stays on the X11 window where the press started, and the coords sent to X were the cursor's offset from that window, scaled for that window's monitor. Xwayland lays out the monitors in its own space (a row in monitor order, with per-monitor scales under force_zero_scaling), so once the cursor crossed to another monitor X saw the pointer somewhere else, sometimes off-screen, and that's why dnd only worked on the same monitor.

Now when the cursor is outside the held window it gets mapped through the monitor it's actually on. For that I added globalToBuffer(pos, origin) to the window backends (WindowBackend.hpp, X11Backend.cpp, WaylandBackend.cpp): on X11 it converts the cursor and the window origin to Xwayland coords and takes the difference, on Wayland it's just pos - origin. Inside the window it works like before.

I also fixed the monitor lookup in waylandToXWaylandCoords (XWaylandManager.cpp): with force_zero_scaling it compared logical coords against each monitor's physical size, now it uses the logical size.

For testing I added xwaylandPointerFollowsCursorAcrossMonitors to hyprtester, with a plugin helper, hl.plugin.test.expect_xwayland_pointer. It creates two monitors in the opposite order of their position so Xwayland's layout doesn't match Hyprland's, opens xeyes on the right one, holds a click, moves to the left one and checks that X sees the pointer where the cursor really is, with and without force_zero_scaling.

Did you use AI in any way shape or form in the making of this PR? If so, detail how you used it. (Undisclosed AI use is a violation of the AI Policy and is punishable)

Yes, it helped me to understand how does wayland interact with xwayland. And it guided me A LOT in the steps of troubleshooting what was causing the problem. I am quite new to window managers and I fucking struggled a lot lmao

Is it ready for merging, or does it need work?

Ready to merge

While a button is held, the pointer focus stays on the X11 surface the press
started on, and its surface-local coords were extrapolated from that surface's
monitor. X11 lays monitors out in its own space (a row in monitor order, with
per-monitor scales under force_zero_scaling), so once the cursor crossed onto
another monitor the X server saw the pointer somewhere else, e.g. off-screen,
which broke drag and drop between X11 apps on different monitors.

When the cursor is outside the held surface, map it through the monitor it is
actually on and take the difference in X11 space. Also match the monitor lookup
in waylandToXWaylandCoords against the logical size, as its input is logical.
@github-actions

Copy link
Copy Markdown

Hi @donutinit,

Thanks for your contribution! Unfortunately, Hyprland and hypr* no longer
accept contributions from unvouched contributors.

To get vouched, please see our contributing guide at wiki.hypr.land/Contributing-and-Debugging

This PR has been closed automatically and will not be re-opened.

@github-actions github-actions Bot closed this Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant