diff --git a/tests/server/grab.cpp b/tests/server/grab.cpp index 859f573..032c5cf 100644 --- a/tests/server/grab.cpp +++ b/tests/server/grab.cpp @@ -1256,6 +1256,120 @@ TEST_F(TouchGrabTest, GrabMultipleTouchpoints) } +TEST_F(TouchGrabTest, MasterSlaveMixed) +{ + XORG_TESTCASE("Client A has a touch grab on root window\n" + "Client B has no support for touch, and listens on its own window\n" + "Client C uses touch on the slave device in its own window\n" + "Trigger pointer-emulated button grab\n" + "Client A rejects, pointer emulated to B, C listening on slave device\n" + "Ungrab the button\n" + "Trigger another touch event, observe B not getting button events\n" + "https://bugs.freedesktop.org/show_bug.cgi?id=78345\n"); + + ::Display *dpy = Display(); + + ::Display *dpy2 = NewClient(); + ::Display *dpy3 = NewClient(); + Window win3 = /*CreateWindow(dpy3, DefaultRootWindow(dpy3));*/DefaultRootWindow(dpy3); + Window win2 = CreateWindow(dpy2, DefaultRootWindow(dpy2), 0, 0, 300, 300); + + XIEventMask mask; + mask.mask_len = XIMaskLen(XI_LASTEVENT); + mask.deviceid = VIRTUAL_CORE_POINTER_ID; + mask.mask = new unsigned char[mask.mask_len](); + + XISetMask(mask.mask, XI_TouchBegin); + XISetMask(mask.mask, XI_TouchUpdate); + XISetMask(mask.mask, XI_TouchEnd); + XISetMask(mask.mask, XI_TouchOwnership); + + XIGrabModifiers mods = {}; + mods.modifiers = XIAnyModifier; + + XIGrabTouchBegin(dpy, VIRTUAL_CORE_POINTER_ID, DefaultRootWindow(dpy), 0, &mask, 1, &mods); + + /* set up client B on the master device */ + memset(mask.mask, 0, mask.mask_len); + XISetMask(mask.mask, XI_ButtonPress); + XISetMask(mask.mask, XI_ButtonRelease); + XISetMask(mask.mask, XI_Motion); + XISelectEvents(dpy2, win2, &mask, 1); + + /* set up client C for touch on the slave device, without ownership events */ + mask.deviceid = 6; + memset(mask.mask, 0, mask.mask_len); + XISetMask(mask.mask, XI_TouchBegin); + XISetMask(mask.mask, XI_TouchUpdate); + XISetMask(mask.mask, XI_TouchEnd); + XISelectEvents(dpy3, win3, &mask, 1); + + /* run test */ + + XSetInputFocus(dpy2, win2, RevertToPointerRoot, CurrentTime); + ASSERT_TRUE(NoEventPending(dpy)); + ASSERT_TRUE(NoEventPending(dpy2)); + ASSERT_TRUE(NoEventPending(dpy3)); + + TouchBegin((int)(150. * 9.375), 20); + ASSERT_EVENT(XIDeviceEvent, tbegin, dpy, GenericEvent, xi2_opcode, XI_TouchBegin); + ASSERT_EVENT(XIDeviceEvent, towner, dpy, GenericEvent, xi2_opcode, XI_TouchOwnership); + ASSERT_TRUE(NoEventPending(dpy)); + + TouchUpdate((int)(200. * 9.375), 20); + ASSERT_EVENT(XIDeviceEvent, tupdate, dpy, GenericEvent, xi2_opcode, XI_TouchUpdate); + ASSERT_TRUE(NoEventPending(dpy)); + + EXPECT_EVENT(XIDeviceEvent, m0, dpy2, GenericEvent, xi2_opcode, XI_Motion); + ASSERT_TRUE(NoEventPending(dpy2)); + + XIAllowTouchEvents(dpy, tbegin->deviceid, tbegin->detail, + DefaultRootWindow(dpy), XIRejectTouch); + + ASSERT_EVENT(XIDeviceEvent, tend, dpy, GenericEvent, xi2_opcode, XI_TouchEnd); + ASSERT_TRUE(NoEventPending(dpy)); + + EXPECT_EVENT(XIDeviceEvent, m1, dpy2, GenericEvent, xi2_opcode, XI_Motion); + EXPECT_EVENT(XIDeviceEvent, b0, dpy2, GenericEvent, xi2_opcode, XI_ButtonPress); + ASSERT_TRUE(NoEventPending(dpy2)); + + ASSERT_EVENT(XIDeviceEvent, tbegin3, dpy3, GenericEvent, xi2_opcode, XI_TouchBegin); + ASSERT_EVENT(XIDeviceEvent, tupdate3, dpy3, GenericEvent, xi2_opcode, XI_TouchUpdate); + ASSERT_TRUE(NoEventPending(dpy3)); + + TouchEnd(); + ASSERT_EVENT(XIDeviceEvent, tend3, dpy3, GenericEvent, xi2_opcode, XI_TouchEnd); + ASSERT_TRUE(NoEventPending(dpy3)); + + ASSERT_EVENT(XIDeviceEvent, m100, dpy2, GenericEvent, xi2_opcode, XI_Motion); + EXPECT_EVENT(XIDeviceEvent, b1, dpy2, GenericEvent, xi2_opcode, XI_ButtonRelease); + ASSERT_TRUE(NoEventPending(dpy2)); + + TouchBegin((int)(512 * 9.375), (512 * 9.375)); + + ASSERT_EVENT(XIDeviceEvent, tbegin2, dpy, GenericEvent, xi2_opcode, XI_TouchBegin); + ASSERT_EVENT(XIDeviceEvent, towner2, dpy, GenericEvent, xi2_opcode, XI_TouchOwnership); + ASSERT_TRUE(NoEventPending(dpy)); + + ASSERT_TRUE(NoEventPending(dpy)); + ASSERT_TRUE(NoEventPending(dpy2)); + + XIAllowTouchEvents(dpy, tbegin2->deviceid, tbegin2->detail, + DefaultRootWindow(dpy), XIRejectTouch); + + ASSERT_EVENT(XIDeviceEvent, tend2, dpy, GenericEvent, xi2_opcode, XI_TouchEnd); + ASSERT_TRUE(NoEventPending(dpy)); + + EXPECT_EVENT(XIDeviceEvent, p1, dpy2, GenericEvent, xi2_opcode, XI_ButtonPress); + ASSERT_TRUE(NoEventPending(dpy2)); + + TouchEnd(); + EXPECT_EVENT(XIDeviceEvent, m3, dpy2, GenericEvent, xi2_opcode, XI_ButtonRelease); + ASSERT_TRUE(NoEventPending(dpy2)); + + delete[] mask.mask; +} + class TouchGrabTestOnLegacyClient : public TouchGrabTest { virtual void SetUp() { SetDevice("tablets/N-Trig-MultiTouch.desc");