mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 00:31:31 +00:00
[client] cursor: restore Wayland edge synchronization
Keep guest-to-host pointer synchronization active while an attempted surface exit is blocked by the edge of a Wayland output. Continue forwarding relative motion and wait for wl_pointer.leave before marking the cursor outside the window. Distinguish whole-surface releases from exits into letterbox space so the expected asynchronous release callback cannot disable the feedback loop before the pointer is confined again. Treat Wayland pointer capability loss as a real leave so an unrelated inactive callback cannot be mistaken for the intentional release.
This commit is contained in:
@@ -66,6 +66,7 @@ target_link_libraries(mouse-tests
|
||||
)
|
||||
set(MOUSE_CASES
|
||||
inset-exit
|
||||
surface-exit
|
||||
exit-delay
|
||||
exit-guest
|
||||
exit-cancel
|
||||
|
||||
@@ -329,6 +329,83 @@ static void setConf(bool active)
|
||||
core_handleGrabEvent(active);
|
||||
}
|
||||
|
||||
static void setSurfaceEdge(double x, double y)
|
||||
{
|
||||
reset();
|
||||
g_state.windowW = 100;
|
||||
g_state.windowH = 80;
|
||||
g_state.dstRect = (LG_RendererRect) {
|
||||
.valid = true,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.w = 100,
|
||||
.h = 80,
|
||||
};
|
||||
setLocal(x, y);
|
||||
}
|
||||
|
||||
static void testSurfaceExit(void)
|
||||
{
|
||||
setSurfaceEdge(99, 40);
|
||||
|
||||
core_handleMouseNormal(1, 0);
|
||||
|
||||
const int drop = first(EV_UNGRAB);
|
||||
const int warp = first(EV_WARP);
|
||||
const int move = first(EV_MOTION);
|
||||
CHECK(drop >= 0);
|
||||
CHECK(warp > drop);
|
||||
CHECK(move > warp);
|
||||
CHECK(m.ev[warp].x == 100);
|
||||
CHECK(m.ev[warp].y == 40);
|
||||
CHECK(m.ev[move].x == 1);
|
||||
CHECK(m.ev[move].y == 0);
|
||||
CHECK(g_cursor.surfaceExit);
|
||||
CHECK(g_cursor.inWindow);
|
||||
CHECK(g_cursor.inView);
|
||||
CHECK(g_cursor.viewReq);
|
||||
|
||||
core_handleMouseNormal(1, 0);
|
||||
CHECK(count(EV_MOTION) == 2);
|
||||
CHECK(g_cursor.surfaceExit);
|
||||
CHECK(g_cursor.inWindow);
|
||||
CHECK(g_cursor.inView);
|
||||
CHECK(g_cursor.viewReq);
|
||||
|
||||
core_handleGuestMouseUpdate();
|
||||
CHECK(count(EV_GUEST) == 1);
|
||||
|
||||
setLocal(99, 40);
|
||||
core_handleMouseNormal(-1, 0);
|
||||
CHECK(m.conf.req);
|
||||
CHECK(g_cursor.surfaceExit);
|
||||
|
||||
setConf(false);
|
||||
CHECK(g_cursor.inView);
|
||||
CHECK(g_cursor.surfaceExit);
|
||||
|
||||
setConf(true);
|
||||
CHECK(g_cursor.inView);
|
||||
CHECK(!g_cursor.surfaceExit);
|
||||
|
||||
setSurfaceEdge(0, 79);
|
||||
core_handleMouseNormal(-1, 1);
|
||||
CHECK(g_cursor.surfaceExit);
|
||||
CHECK(g_cursor.inWindow);
|
||||
CHECK(g_cursor.inView);
|
||||
CHECK(g_cursor.viewReq);
|
||||
CHECK(count(EV_MOTION) == 1);
|
||||
|
||||
core_handleGuestMouseUpdate();
|
||||
CHECK(count(EV_GUEST) == 1);
|
||||
|
||||
g_cursor.inWindow = false;
|
||||
core_setCursorInView(false);
|
||||
CHECK(!g_cursor.surfaceExit);
|
||||
CHECK(!g_cursor.inView);
|
||||
CHECK(!g_cursor.viewReq);
|
||||
}
|
||||
|
||||
static void startExit(void)
|
||||
{
|
||||
reset();
|
||||
@@ -742,6 +819,7 @@ struct Test
|
||||
|
||||
static const struct Test tests[] = {
|
||||
{ "inset-exit" , testInsetExit },
|
||||
{ "surface-exit" , testSurfaceExit },
|
||||
{ "exit-delay" , testExitWait },
|
||||
{ "exit-guest" , testExitGuest },
|
||||
{ "exit-cancel" , testExitCancel },
|
||||
|
||||
Reference in New Issue
Block a user