fix: pointer constraints, xwayland positioning, and physics tick - #8
fix: pointer constraints, xwayland positioning, and physics tick#8sevenluckz wants to merge 14 commits into
Conversation
|
Thanks — I went through all three commits and built the branch against wlroots 0.20. It compiles clean and merges cleanly on current 1. fwm does draw the pointer itself, but it takes the image from the client ( 2. Both the comment in One gap this leaves, which is not a regression and does not need to be in this PR — 3. The part I agree with entirely: the early But the same change now also runs focus-follows-pointer on every motion event under a lock. The cursor is frozen, yes — the windows are not. fwm's windows drift and get thrown around on their own, and when one lands under the frozen cursor, Could you keep the constraint bookkeeping and leave focus alone: if (view && !locked) server_focus_view(server, view);Same class of thing, lower stakes, up to you: Ping me when you've marked it ready and I'll merge. Nice digging — you found two places where the comments and the code had drifted apart. |
Translate the world coordinates to screen coordinates before sending them to wlr_xwayland_surface_configure. Otherwise, X11 clients on any desktop besides the first one think they are positioned outside the X11 root window, resulting in dead clicks and failed hit-testing.
As noted in review, the pointer constraint lock prevented motion events from being sent to clients, but it still allowed fwm's focus-follows-pointer logic to trigger if a window slid under the cursor. This could cause the focused client to lose focus during interactions like mouse-look. This patch bypasses focus evaluation and drag/hover interactions while the pointer is locked, ensuring the locked client retains focus.
…to fix detached dropdown menus
492f670 to
06b8942
Compare
|
Hey, this is all I have for the moment! I've hopefully solved the focus issue you mentioned, and I also added logic to track the cursor in relation to the window when it's locked (and instantly drop the lock if the window goes off-screen). I also moved the Finally, I added more position updates for Xwayland while its windows are moving to fix an issue I noticed where detached UI elements (like dropdown menus) were not updating their positions dynamically. |
|
Thanks for this — I built the branch against wlroots 0.20 and it compiles clean, all 7 ctest targets pass. Replacing the manual boundary drop with Three things I'd like fixed before merging, all in the constraint/physics commits: 1. The The early-out keys on Cache the computed 2. The cursor warp during glides isn't gated on LOCKED ( The condition is just Also worth a comment: 3. Breaking the lock off-screen does more than break the lock ( Besides deactivating the constraint it force-sets the Minor, not a blocker and pre-existing: the region offset is computed from One process note: the PR title reads as a cursor fix, but only |
The cache introduced for view_sync_position tracked the static 'world' coordinate of the view rather than the dynamic 'screen' coordinate. When the camera panned to a new desktop, the screen coordinates changed, but since the world coordinate remained identical, the update was skipped. This resulted in Xwayland retaining stale coordinates for the main window, causing popups (like context menus) to appear on entirely wrong physical monitors. To solve this systematically and prevent translating coordinates twice, the caching logic has been consolidated directly into view_set_size. Additionally, we explicitly treat server_world_to_screen failures as "not cached" by bypassing the early-out and invalidating the cache (setting it to -999999) when the window is parked off-screen. This ensures that the raw world position is always correctly sent as a fallback, and when the window comes back on-screen, Xwayland is guaranteed to receive the fresh screen coordinates immediately.
iluaii
left a comment
There was a problem hiding this comment.
Marking this as changes-requested so the status is visible in the UI — my earlier feedback went out as plain comments, so GitHub never flagged the PR and it may well have been lost in your inbox. Nothing new here, this is just the checklist from #8 (comment):
src/view.c:168— cache the computedsx/syrather thanview->x/y, and treat aserver_world_to_screen()failure as "not cached". As written the early-out skips the reconfigure after a camera move, which is the case the coordinate fix exists for.src/server_tick.c:1157— gate the cursor warp onconstraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED; a CONFINED constraint shouldn't drag the pointer along.src/server_tick.c:1170— on breaking the lock,constraints_follow_focus(server, NULL)is enough; drop the forceddefaultxcursor and thewlr_seat_pointer_clear_focus().
No rush on my end, and no need to rebase or reshape anything. The standing offer also holds: if you'd rather land something now, I'll take d7fc7c8 (fallback cursor) on its own and we can keep the constraint work in this PR.
Remove explicit cursor and focus clearing when breaking constraints off-screen. constraints_follow_focus(server, NULL) alone already deactivates the constraint, and the next motion event restores focus and the correct cursor image on its own.
The constraint region is in surface coordinates, but we were computing the region offset from cv->x/cv->y (the window origin). For XDG surfaces with CSD geometry insets, we now subtract the geometry offset to properly map world coordinates to surface coordinates.
wlr_pointer_constraint_v1_send_deactivated can cause the constraint to be destroyed immediately, which triggers the destroy listener and removes the link. Calling wl_list_remove afterwards results in a double-remove and memory corruption. Unlink the listener first.
Remove early return when pointer coordinates fall outside the confined region. Now that the constraint listener double-free crash is fixed, we can safely let the pointer move out so focus can update and break the constraint properly.
|
I've pushed updates to address your feedback:
Minor (CSD Geometry Insets): Updated I've also included fixes for related edge cases found during testing:
|
iluaii
left a comment
There was a problem hiding this comment.
Thanks — all three checklist items are addressed, and I rebuilt the branch against wlroots 0.20.2: it merges cleanly onto current main, compiles without warnings, and all 10 ctest targets pass.
Confirming what's now settled:
src/view.c:156— the cache keys on the computedsx/syand aserver_world_to_screen()failure invalidates it, so a camera move does reach X now.server_world_to_screentoleratesNULLout-params (src/server_output.c:483), so theNULL, NULLprobe in the tick is fine too.src/server_tick.c:1164— gated onLOCKED, with the world-vs-layout caveat written down.src/server_tick.c:1175— down toconstraints_follow_focus(server, NULL)alone.
And the CSD inset is handled via xdg_toplevel->base->current.geometry, which is what I meant.
38d8cc8 is a genuine find and the fix is the right one — the header says it outright: "Deactivate the constraint. May destroy the constraint." With lifetime == ONESHOT, wlr_pointer_constraint_v1_send_deactivated() destroys the object synchronously, handle_constraint_destroy removes the listener, and constraint_set_active then removes it a second time. Unhooking before the signal is correct.
Two things left, then I'll merge.
1. Off-screen X11 windows now get a configure every tick (src/view.c:156, src/server_tick.c:1162)
view_sync_position() runs unconditionally for every unpinned body in the physics tick, which includes every window sitting on a desktop no monitor is showing. For those server_world_to_screen() fails, so the cache is stamped with -999999, the early-out can never hit, and wlr_xwayland_surface_configure() goes out at 60 Hz per window — carrying raw world coordinates, which is the value the early-out was there to suppress in the first place. Clients that relayout on ConfigureNotify (Chrome, anything AWT) will do it 60 times a second while parked on another desktop.
Cheap fix: keep a bool last_sync_onscreen alongside the coordinates, cache whatever was actually sent in both cases, and compare all of it. That also retires the -999999 sentinel.
2. The comment under locked says the opposite of what the code does (src/server_pointer.c:145)
/* Mouse-look: the cursor does not move at all, but we still need
* to send motion events with constant coordinates. */The code deliberately skips wlr_seat_pointer_notify_enter/motion while locked, which is right — the client is getting relative motion from the relative-pointer protocol, and absolute motion under a lock is exactly what we're suppressing. The reason to fall through is hit-testing and constraints_follow_focus. Could you reword it to say that?
Neither of these needs a reshape, and no rush.
Two non-blockers for the record, no action needed here:
- If
wlr_region_confine()ever returns false the pointer is freed, but should it still be over the same surface,constraints_follow_focusre-arms the same constraint while every subsequent motion also starts outside the region — so confinement stays broken until focus actually leaves. In practice the pointer is inside the region at activation, so this only bites after aset_regionwhile the pointer is elsewhere. I'll open an issue rather than grow this PR. af1900dduplicatesa8ec5a6, which landed onmainafter you branched. Identical change, merges clean, ends up a no-op — nothing to do, I'll just drop it from the squash message.- Seven of the added lines carry trailing whitespace.
|
Heads up:
It is worth resolving by hand rather than by taking a side, because the two changes meet on the same question. if (server_drag_motion(server, lx, ly, &now)) return;
if (pointer_grab_deliver(server, lx, ly, event->time_msec)) return;
pointer_update_focus(server, lx, ly, event->time_msec);Your Also note No rush, and nothing about the review changes — the two items from my last comment still stand (the 60 Hz configure storm for off-screen X11 windows, and the comment at what is now a different line number in |
This PR addresses Xwayland coordinate sync issues and hardens the compositor's core pointer constraint logic.
1. Xwayland default cursor
Fetches the
defaultxcursor buffer and sets it viawlr_xwayland_set_cursorto prevent the legacy X11 fallback cursor.2. Xwayland Positioning/Physics Tick
Translates world coordinates to screen coordinates during
view_set_sizeto restore hit-testing on non-primary desktops.Xwayland coordinates are also continuously synced (
view_sync_position) during physics glides and drags to prevent detached popups and dropdowns. To support desktop switching, this synchronization caches the computedsx/syscreen coordinates, naturally treating coordinate translation failures as un-cached.3. Pointer Constraints & Crash Fixes
Hardens both
LOCKEDandCONFINEDpointer constraints:returnwith alockedboolean check to keep the cursor visually frozen and suppress motion events while still allowing focus/hit-testing to process.wlr_region_confineto strictly clamp the pointer.LOCKEDconstraints).constraints_follow_focus(server, NULL)without forcing the seat's pointer focus.SIGSEGVinserver_seat.ccaused by a doublewl_list_remove. The constraint listener is now unhooked before sending the deactivated signal to prevent memory corruption.