diff --git a/client/displayservers/X11/x11.c b/client/displayservers/X11/x11.c index fc0c6ec8..f26a0969 100644 --- a/client/displayservers/X11/x11.c +++ b/client/displayservers/X11/x11.c @@ -2103,19 +2103,9 @@ static void x11CapturePointer(void) static void x11UncapturePointer(void) { - const bool ungrab = !app_isFormatValid() || app_isCaptureOnlyMode(); - LG_LOCK(x11.pointerLock); atomic_store_explicit(&x11.captureActive, false, memory_order_release); - - /* we need to ungrab the pointer on the following conditions when exiting capture mode: - * - if the format is invalid as we do not know where the guest cursor is, - * which breaks edge detection as the cursor can not be warped out of the - * window when we release it. - * - if the user has opted to use captureInputOnly mode. - */ - if (ungrab) - x11UngrabPointerLocked(); + x11UngrabPointerLocked(); LG_UNLOCK(x11.pointerLock); } diff --git a/client/tests/CMakeLists.txt b/client/tests/CMakeLists.txt index dd163587..4dc5e96b 100644 --- a/client/tests/CMakeLists.txt +++ b/client/tests/CMakeLists.txt @@ -126,6 +126,7 @@ set(MOUSE_CASES capture-revoked capture-release capture-align + x11-capture-exit capture-fallback rotate-scale geometry diff --git a/client/tests/mouse_test.c b/client/tests/mouse_test.c index ef25d1bc..6bd6774a 100644 --- a/client/tests/mouse_test.c +++ b/client/tests/mouse_test.c @@ -67,6 +67,7 @@ static struct struct Trap conf; struct Trap lock; bool valid; + bool captureGrab; struct Ev ev[256]; unsigned int count; } @@ -152,6 +153,18 @@ static void capture(void) return; } + if (m.captureGrab) + { + m.conf.req = true; + if (!m.conf.hold) + m.conf.on = true; + m.lock.req = true; + if (!m.lock.hold) + m.lock.on = m.conf.on; + push(EV_CAPTURE, 0, 0, false); + return; + } + m.conf.req = false; if (!m.conf.hold) m.conf.on = false; @@ -171,6 +184,9 @@ static void uncapture(void) m.lock.req = false; if (!m.lock.hold) m.lock.on = false; + + if (m.captureGrab) + ungrab(); } static bool captured(void) @@ -592,6 +608,38 @@ static void testCapAlign(void) CHECK(!m.ev[warp].exit); } +static void testX11CapExit(void) +{ + reset(); + setLocal(50, 50); + m.support = LG_DS_WARP_SCREEN; + m.captureGrab = true; + m.conf.req = false; + m.conf.on = false; + + core_setGrabQuiet(true); + CHECK(m.conf.on); + CHECK(m.lock.on); + + g_cursor.guest.x += 10; + m.count = 0; + core_setGrabQuiet(false); + + const int uncapture = first(EV_UNCAPTURE); + const int ungrab = first(EV_UNGRAB); + const int warp = first(EV_WARP); + CHECK(uncapture >= 0); + CHECK(ungrab > uncapture); + CHECK(warp > ungrab); + CHECK(m.ev[warp].x == 60); + CHECK(m.ev[warp].y == 50); + CHECK(!m.ev[warp].exit); + CHECK(!m.conf.req); + CHECK(!m.conf.on); + CHECK(!m.lock.req); + CHECK(!m.lock.on); +} + static void testCapFallback(void) { reset(); @@ -853,6 +901,7 @@ static const struct Test tests[] = { { "capture-revoked" , testCapRevoke }, { "capture-release" , testCapRelease }, { "capture-align" , testCapAlign }, + { "x11-capture-exit", testX11CapExit }, { "capture-fallback", testCapFallback }, { "rotate-scale" , testRotateScale }, { "geometry" , testGeometry },