XI2 raw events are not delivered when Mouse or Keyboard is grabbed with GrabModeSync
According to the documentation, raw events should be delivered regardless of the grab state as stated in https://www.x.org/releases/current/doc/inputproto/XI2proto.txt
"Clients supporting XI 2.1 or later receive raw events at all times, even when the device is grabbed by another client."
But they are not reported when a grab is done with GrabModeSync.
I have reproduced this on
- Ubuntu 16.04.6 LTS, using Xorg version 1.18.4, which has Xinput extension version 2.3
- and on RHEL 7.7 using Xorg version 1.20.4, which has Xinput extension version 2.3
I have looked at the code and it seems that GrabModeSync causes the device to get frozen in the layer below XI2. See function "GrabDevice" in dix/events.c:
if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
access_mode |= DixFreezeAccess;
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
Note: The XaceHook probably does not freeze the device because Xace is just about access control. My guess is that the device access is frozen someplace else because it asks permission for that from Xace here. My guess may be wrong, though.
If my guess is somewhat right then I think that a fix would require to handle GrabModeSync in DIX and XI2 rather than freezing the device. So, a fix would probably have some complexity and would need to be carefully crafted and reviewed to avoid undesired side-effects.
To reproduce, you can use the following two little programs:
Run XI2RawEventReporter in a shell-window. If you press keys or buttons or move the mouse, the activity will be reported on stdout, i.e., to this shell-window.
Then run GrabKeyboard from another shell-window. This will grab the keyboard for a while (and display a graphic in a window while it does this). You'll see that the XI2RawEventReporter does not show any keyboard and mouse activity
The same happens if you grab the pointer instead of the keyboard.