Server sends XInput 2 HierarchyEvents that do not correspond to the protocol description (value zero for a field that may not contain zero)
Originally reported at https://github.com/psychon/x11rb/issues/458
What is the problem?
XI's HierarchyEvent
contains a list of HIERARCHYINFO
structs. When a device is removed, the value zero appears in the type
field of that struct. Zero is not a valid value for this field.
To reproduce, run xinput test-xi2
and remove a master in another terminal. The following event is printed (notice the <undefined> (0)
):
EVENT type 11 (HierarchyChanged)
Changes happened: [master removed] [slave removed] [slave detached] [device disabled]
device 2 [master pointer (3)] is enabled
device 3 [master keyboard (2)] is enabled
device 4 [slave pointer (2)] is enabled
device 5 [slave keyboard (3)] is enabled
device 6 [slave keyboard (3)] is enabled
device 7 [slave keyboard (3)] is enabled
device 8 [slave keyboard (3)] is enabled
device 9 [slave keyboard (3)] is enabled
device 10 [slave keyboard (3)] is enabled
device 11 [slave keyboard (3)] is enabled
device 12 [slave keyboard (3)] is enabled
device 13 [slave pointer (2)] is enabled
device 14 [<undefined> (0)] is disabled
changes: [master removed] [device disabled]
device 15 [<undefined> (0)] is disabled
changes: [master removed] [device disabled]
device 16 [<undefined> (0)] is disabled
changes: [slave removed] [slave detached] [device disabled]
device 17 [<undefined> (0)] is disabled
changes: [slave removed] [slave detached] [device disabled]
Where is this generated?
What should be done about this?
I do not have much clue about XI / XI2. Personally, I would prefer option A below: Fix the server. However, no idea what the "right thing to send" is and no idea how much code out there this would break.
Option A: Fix the server not to sent this invalid events. info->use = 0
could be replaced with a more readable equivalent of info->use = [no idea how to check if this was keyboard / pointer] ?(flags[i] & XIMasterRemoved ? XIMasterPointer : XISlavePointer) : (flags[i] & XIMasterRemoved ? XIMasterKeyboard : XISlaveKeyboard)
.
Option B: Just "allow" the value zero here. Patch for https://gitlab.freedesktop.org/xorg/proto/xorgproto/- (no idea what format this file is in and how to word this correctly):
diff --git a/include/X11/extensions/XI2.h b/include/X11/extensions/XI2.h
index 5a1c66a..5a2c11b 100644
--- a/include/X11/extensions/XI2.h
+++ b/include/X11/extensions/XI2.h
@@ -129,6 +129,7 @@
#define XIModeAbsolute 1
/* Device types */
+#define XIRemoved 0
#define XIMasterPointer 1
#define XIMasterKeyboard 2
#define XISlavePointer 3
diff --git a/include/X11/extensions/XI2proto.h b/include/X11/extensions/XI2proto.h
index a1133b5..359f09a 100644
--- a/include/X11/extensions/XI2proto.h
+++ b/include/X11/extensions/XI2proto.h
@@ -125,7 +125,7 @@ typedef struct {
*/
typedef struct {
uint16_t deviceid;
- uint16_t use; /**< ::XIMasterPointer, ::XIMasterKeyboard,
+ uint16_t use; /**< ::XIRemoved, ::XIMasterPointer, ::XIMasterKeyboard,
::XISlavePointer, ::XISlaveKeyboard,
::XIFloatingSlave */
uint16_t attachment; /**< Current attachment or pairing.*/
diff --git a/specs/XI2proto.txt b/specs/XI2proto.txt
index 440b0d0..6d98f01 100644
--- a/specs/XI2proto.txt
+++ b/specs/XI2proto.txt
@@ -666,12 +666,15 @@ Data types
AllDevices ........ 0
AllMasterDevices .. 1
- DEVICEUSE { MasterPointer, MasterKeyboard, SlavePointer,
+ DEVICEUSE { Removed, MasterPointer, MasterKeyboard, SlavePointer,
SlaveKeyboard, FloatingSlave }
A DEVICEUSE field specifies the current use of a device in the MD/SD
device hierarchy. See Section "The Master/Slave device hierarchy"
for more information.
+ The value Removed is only used in HierarchyEvent to signify that
+ some device was removed
+
EVTYPEMASK
An EVTYPEMASK is a binary mask defined as (1 << event type).
A SETofEVTYPEMASK is a binary OR of zero or more EVTYPEMASK.
Patch for https://gitlab.freedesktop.org/xorg/proto/xcbproto:
diff --git a/src/xinput.xml b/src/xinput.xml
index 5f88a98..231aa6c 100644
--- a/src/xinput.xml
+++ b/src/xinput.xml
@@ -1604,6 +1604,7 @@ authorization from the authors.
</enum>
<enum name="DeviceType">
+ <item name="Removed"> <value>0</value> </item>
<item name="MasterPointer"> <value>1</value> </item>
<item name="MasterKeyboard"> <value>2</value> </item>
<item name="SlavePointer"> <value>3</value> </item>
Patch for https://gitlab.freedesktop.org/xorg/app/xinput:
diff --git a/src/test_xi2.c b/src/test_xi2.c
index 10a46c3..c9cf0ae 100644
--- a/src/test_xi2.c
+++ b/src/test_xi2.c
@@ -123,6 +123,7 @@ static void print_hierarchychangedevent(XIHierarchyEvent *event)
char *use = "<undefined>";
switch(event->info[i].use)
{
+ case XIRemoved: use = "removed"; break;
case XIMasterPointer: use = "master pointer"; break;
case XIMasterKeyboard: use = "master keyboard"; break;
case XISlavePointer: use = "slave pointer"; break;
Edit: blame
says the code has always been like this. It was added in 033a2b12