-
Peter Hutterer authored
The server struggles with devices that are both, the protocol (especially XI2) requires a fairly strict separation of pointer vs keyboard devices. Though the server has a couple of hacks to route events correctly, mixed devices still experience bugs like [1]. Instead of advertising the device as a single mixed device, split the device into two X devices, one with only a pointer/touch component, one with only a keyboard component. This ensures that the device is effectively attached to both the VCP and the VCK, something the XI2 protocol doesn't really allow. This patch drops the keyboard capability on a mixed device, duplicates the input options and attributes and queues a NewInputDeviceRequest call. The new device only has the keyboard capability but is otherwise unchanged. The wacom driver has used this approach for years. The WorkProc is necessary to avoid inconsistent state, the server doesn't handle a NewInputDeviceRequest during PreInit well. The approach: During pre-init we create a struct xf86libinput_device with the libinput_device and a unique ID. The child device has that ID added to the options and will look for the other device during its pre-init. The two devices then share the xf86libinput_device struct. We only have a single epollfd for all devices and the server calls read_input on the first device in the list with the epollfd as pInfo->fd. That shared struct is used as the userdata on the libinput_device we get back from the event, and each device is in the xorg_list device_list of that shared struct. We loop through those to find the ones with the right capabilities and post the event through that device. Since devices can be enabled and disabled independently, the rest of the code makes sure that we only ever add the device to libinput when the first shared device is enabled, and remove it accordingly. The server uses pInfo->major/minor to detect if another device is using the same path for a logind-controlled fd. If so, it reuses that device's pInfo->fd and sets the "fd" option to that value. That pInfo->fd is the libinput epollfd though, not the actual device fd. This doesn't matter for us, since we manage the fds largely ourselves and the pInfo->fd we use is the epollfd anyway. On unplug however, the udev code triggers a device removal for all devices, including the duplicated ones. When we disable device, we restore the pInfo->fd from the "fd" option so that the server can request logind to close the fd. That only works if the "fd" option is correct, otherwise the server asks logind to close the epollfd and everyone is unhappy. [1] https://bugs.freedesktop.org/show_bug.cgi?id=49950 https://bugs.freedesktop.org/show_bug.cgi?id=92896 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
1f43f392