Fix edge scroll hang when the cursor leaves the window on Wayland - #125
Fix edge scroll hang when the cursor leaves the window on Wayland#125dustinspace217 wants to merge 1 commit into
Conversation
Under Wayland/XWayland, GetCursorPos freezes at the last position the cursor had over the game window once it moves to another monitor or a native Wayland surface, so the edge scroll loop in check_scroll() never saw the cursor leave the scroll zone and spun forever, leaving the game scrolling and unresponsive while the real cursor moved freely. Track whether the cursor is inside the window with WM_MOUSELEAVE (armed via TrackMouseEvent), skip edge scrolling when it is not, and bound each scroll burst so the loop always yields back to the message pump that delivers those messages.
|
It is good the generated code/pull requests are labeled as such. The commenting style is a bit verbose compared to the rest of the project, however there are some actual issues related to how the comments refer specifically to the Wayland platform, but the mod also needs to support all other platforms. For example when testing on Windows, the default smooth_scrolling implementation is really consistent in the way the scrolling accelerates or decelarates based on how close the cursor is to the edge of the window defined by scroll_area. This patched version seems inconsistent in the way the scrolling accelerates, sometimes it is really slow compared to the default version, sometimes it is fast but decelerates after some delay, and it is not clear what internal mechanic affects this speed. Due to these issues the patched version would need additional changes and testing to avoid at least these regressions on other platforms. Alternatively if your environment does not support the mouse updates needed to make this work, it is always possible to disable smooth_scrolling as it is only a bonus feature that does not have any effects beyond user interface improvements, assuming the default game scrolling still works without issues on Wayland. |
What?
Fixes the edge-scroll hang under Wayland/XWayland: pushing the cursor to a screen edge to scroll the map could lock the game into scrolling forever, ignoring every other input, until you clicked back inside the window.
Why?
On Wayland this bites hard. When you edge-scroll and the cursor slides off the game's window — onto another monitor or a native Wayland window — the map keeps scrolling on its own and the game stops responding to anything else. The cursor itself is visibly free, moving around the desktop; it's only the game that's stuck, still reading a mouse position that no longer means anything. On a multi-monitor setup you hit it constantly, because the edge you're scrolling toward is usually the edge you're about to cross. It's the same hang the PRACX author described back in 2016 in DrazharLn/pracx#3 — on X it was a soft UI stall, but under Wayland it's a full freeze.
How?
The old edge-scroll loop kept going as long as
GetCursorPosstill reported the cursor inside the edge zone. On WaylandGetCursorPosfreezes at the last position the cursor had over the window once it leaves — Wayland has no way to query the global pointer position, so a client only knows where the pointer is while it's over its own surface — so that exit condition never clears. I switched the "is the cursor still here?" test from polling that frozen position to aWM_MOUSELEAVEflag (armed withTrackMouseEvent), which Wine still delivers correctly off-surface, and capped each scroll burst so the loop always yields back to the message pump that processes it.Testing?
thinker.dllwith the MinGW cross-toolchain on Fedora 44, running the GOG copy of SMACX under Wine-GE (GE-Proton8-26) on KDE Plasma 6 / Wayland, NVIDIA.Anything Else?
I used Claude Code (Opus 4.8) to help track this down and write the fix — reading the Wine and Thinker source to pin the root cause, then confirming
WM_MOUSELEAVEactually fires off-surface on this setup before building anything. Happy to adjust if you'd rather the leave-detection or the burst cap were done differently.