[client] wayland: lock confine-related code to avoid race

This should fix the occasional Wayland protocol errors that arise when
the UI thread and the cursor thread race.

Example of error that is fixed:

    zwp_pointer_constraints_v1@11: error 1: a pointer constraint with a wl_pointer of the same wl_seat is already on this surface
This commit is contained in:
Quantum 2021-06-06 01:28:22 -04:00 committed by Geoffrey McRae
parent f07e4839b1
commit 4b99bba200
2 changed files with 87 additions and 61 deletions

View File

@ -301,12 +301,15 @@ bool waylandInputInit(void)
&relativePointerListener, NULL); &relativePointerListener, NULL);
} }
LG_LOCK_INIT(wlWm.confineLock);
return true; return true;
} }
void waylandInputFree(void) void waylandInputFree(void)
{ {
waylandUngrabPointer(); waylandUngrabPointer();
LG_LOCK_FREE(wlWm.confineLock);
wl_pointer_destroy(wlWm.pointer); wl_pointer_destroy(wlWm.pointer);
wl_keyboard_destroy(wlWm.keyboard); wl_keyboard_destroy(wlWm.keyboard);
wl_seat_destroy(wlWm.seat); wl_seat_destroy(wlWm.seat);
@ -326,21 +329,27 @@ void waylandGrabPointer(void)
&relativePointerListener, NULL); &relativePointerListener, NULL);
} }
INTERLOCKED_SECTION(wlWm.confineLock,
{
if (!wlWm.confinedPointer) if (!wlWm.confinedPointer)
{ {
wlWm.confinedPointer = zwp_pointer_constraints_v1_confine_pointer( wlWm.confinedPointer = zwp_pointer_constraints_v1_confine_pointer(
wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL, wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
} }
});
} }
void waylandUngrabPointer(void) void waylandUngrabPointer(void)
{ {
INTERLOCKED_SECTION(wlWm.confineLock,
{
if (wlWm.confinedPointer) if (wlWm.confinedPointer)
{ {
zwp_confined_pointer_v1_destroy(wlWm.confinedPointer); zwp_confined_pointer_v1_destroy(wlWm.confinedPointer);
wlWm.confinedPointer = NULL; wlWm.confinedPointer = NULL;
} }
});
if (!wlWm.warpSupport) if (!wlWm.warpSupport)
{ {
@ -366,6 +375,8 @@ void waylandCapturePointer(void)
return; return;
} }
INTERLOCKED_SECTION(wlWm.confineLock,
{
if (wlWm.confinedPointer) if (wlWm.confinedPointer)
{ {
zwp_confined_pointer_v1_destroy(wlWm.confinedPointer); zwp_confined_pointer_v1_destroy(wlWm.confinedPointer);
@ -375,10 +386,13 @@ void waylandCapturePointer(void)
wlWm.lockedPointer = zwp_pointer_constraints_v1_lock_pointer( wlWm.lockedPointer = zwp_pointer_constraints_v1_lock_pointer(
wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL, wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
});
} }
void waylandUncapturePointer(void) void waylandUncapturePointer(void)
{ {
INTERLOCKED_SECTION(wlWm.confineLock,
{
if (wlWm.lockedPointer) if (wlWm.lockedPointer)
{ {
zwp_locked_pointer_v1_destroy(wlWm.lockedPointer); zwp_locked_pointer_v1_destroy(wlWm.lockedPointer);
@ -395,12 +409,14 @@ void waylandUncapturePointer(void)
if (!wlWm.warpSupport || !app_isFormatValid() || app_isCaptureOnlyMode()) if (!wlWm.warpSupport || !app_isFormatValid() || app_isCaptureOnlyMode())
{ {
waylandUngrabPointer(); waylandUngrabPointer();
return;
} }
else
{
wlWm.confinedPointer = zwp_pointer_constraints_v1_confine_pointer( wlWm.confinedPointer = zwp_pointer_constraints_v1_confine_pointer(
wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL, wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
}
});
} }
void waylandGrabKeyboard(void) void waylandGrabKeyboard(void)
@ -423,9 +439,17 @@ void waylandUngrabKeyboard(void)
void waylandWarpPointer(int x, int y, bool exiting) void waylandWarpPointer(int x, int y, bool exiting)
{ {
if (!wlWm.pointerInSurface || wlWm.lockedPointer) if (!wlWm.pointerInSurface)
return; return;
INTERLOCKED_SECTION(wlWm.confineLock,
{
if (!wlWm.lockedPointer)
{
LG_UNLOCK(wlWm.confineLock);
return;
}
if (x < 0) x = 0; if (x < 0) x = 0;
else if (x >= wlWm.width) x = wlWm.width - 1; else if (x >= wlWm.width) x = wlWm.width - 1;
if (y < 0) y = 0; if (y < 0) y = 0;
@ -452,6 +476,7 @@ void waylandWarpPointer(int x, int y, bool exiting)
wl_surface_commit(wlWm.surface); wl_surface_commit(wlWm.surface);
wl_region_destroy(region); wl_region_destroy(region);
});
} }
void waylandRealignPointer(void) void waylandRealignPointer(void)

View File

@ -141,6 +141,7 @@ struct WaylandDSState
struct zwp_locked_pointer_v1 * lockedPointer; struct zwp_locked_pointer_v1 * lockedPointer;
bool showPointer; bool showPointer;
uint32_t pointerEnterSerial; uint32_t pointerEnterSerial;
LG_Lock confineLock;
struct zwp_idle_inhibit_manager_v1 * idleInhibitManager; struct zwp_idle_inhibit_manager_v1 * idleInhibitManager;
struct zwp_idle_inhibitor_v1 * idleInhibitor; struct zwp_idle_inhibitor_v1 * idleInhibitor;