[PATCH xf86-input-libinput] Handle capability events after adding a device
Peter Hutterer
peter.hutterer at who-t.net
Thu Jan 29 21:31:40 PST 2015
Needs a temporary libinput context to get all capability events without
events from other devices interfering.
This doesn't yet handle true capability changes, only the initial burst of
events after the DEVICE_ADDED event.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
That's based on a patchset scheduled for libinput 0.10
src/libinput.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 61 insertions(+), 7 deletions(-)
diff --git a/src/libinput.c b/src/libinput.c
index a24cbff..29a624c 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -51,6 +51,8 @@
#define TOUCH_MAX_SLOTS 15
#define XORG_KEYCODE_OFFSET 8
+#define AS_MASK(v) (1 << v)
+
/*
libinput does not provide axis information for absolute devices, instead
it scales into the screen dimensions provided. So we set up the axes with
@@ -70,6 +72,7 @@ static struct xf86libinput_driver driver_context;
struct xf86libinput {
char *path;
struct libinput_device *device;
+ unsigned int capabilities;
int scroll_vdist;
int scroll_hdist;
@@ -600,15 +603,15 @@ xf86libinput_init(DeviceIntPtr dev)
dev->public.on = FALSE;
- if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD))
+ if (driver_data->capabilities & AS_MASK(LIBINPUT_DEVICE_CAP_KEYBOARD))
xf86libinput_init_keyboard(pInfo);
- if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) {
+ if (driver_data->capabilities & AS_MASK(LIBINPUT_DEVICE_CAP_POINTER)) {
if (libinput_device_config_calibration_has_matrix(device))
xf86libinput_init_pointer_absolute(pInfo);
else
xf86libinput_init_pointer(pInfo);
}
- if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH))
+ if (driver_data->capabilities & AS_MASK(LIBINPUT_DEVICE_CAP_TOUCH))
xf86libinput_init_touch(pInfo);
/* unref the device now, because we'll get a new ref during
@@ -815,6 +818,8 @@ xf86libinput_handle_event(struct libinput_event *event)
case LIBINPUT_EVENT_NONE:
case LIBINPUT_EVENT_DEVICE_ADDED:
case LIBINPUT_EVENT_DEVICE_REMOVED:
+ case LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED:
+ case LIBINPUT_EVENT_DEVICE_CAPABILITY_REMOVED:
break;
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
xf86libinput_handle_absmotion(pInfo,
@@ -1117,6 +1122,49 @@ xf86libinput_parse_options(InputInfoPtr pInfo,
}
+/* libinput sends capabilities as events after opening the device. In X we
+ need the capabilities to be done when we get to DEVICE_INIT.
+ The capability events may be intermixed with real events from other
+ devices, making handling device init a lot more complicated than it needs
+ to be. To avoid this, we create a temporary libinput context, pull the
+ capability events off the context, then ignore them in the main context.
+ */
+static int
+get_capabilities(const char *path)
+{
+ int rc = -1;
+ struct libinput *libinput = NULL;
+ struct libinput_device *device;
+ struct libinput_event *event;
+ struct libinput_event_device_capability *cap;
+
+ libinput = libinput_path_create_context(&interface,
+ &driver_context);
+ if (!libinput)
+ goto out;
+
+
+ device = libinput_path_add_device(libinput, path);
+ if (!device)
+ goto out;
+
+ libinput_dispatch(libinput);
+
+ rc = 0;
+ while ((event = libinput_get_event(libinput))) {
+ if (libinput_event_get_type(event) == LIBINPUT_EVENT_DEVICE_CAPABILITY_ADDED) {
+ cap = libinput_event_get_device_capability_event(event);
+ rc |= AS_MASK(libinput_event_device_capability_get_capability(cap));
+ }
+ libinput_event_destroy(event);
+ }
+
+out:
+ libinput_unref(libinput);
+
+ return rc;
+}
+
static int
xf86libinput_pre_init(InputDriverPtr drv,
InputInfoPtr pInfo,
@@ -1125,6 +1173,7 @@ xf86libinput_pre_init(InputDriverPtr drv,
struct xf86libinput *driver_data = NULL;
struct libinput *libinput = NULL;
struct libinput_device *device;
+ int capabilities;
char *path;
pInfo->type_name = 0;
@@ -1170,6 +1219,12 @@ xf86libinput_pre_init(InputDriverPtr drv,
if (use_server_fd(pInfo))
fd_push(&driver_context, pInfo->fd, path);
+ capabilities = get_capabilities(path);
+ if (capabilities == -1) {
+ xf86IDrvMsg(pInfo, X_ERROR, "Failed to create a device for %s\n", path);
+ goto fail;
+ }
+
device = libinput_path_add_device(libinput, path);
if (!device) {
xf86IDrvMsg(pInfo, X_ERROR, "Failed to create a device for %s\n", path);
@@ -1187,6 +1242,7 @@ xf86libinput_pre_init(InputDriverPtr drv,
pInfo->private = driver_data;
driver_data->path = path;
driver_data->device = device;
+ driver_data->capabilities = (unsigned int)capabilities;
/* Disable acceleration in the server, libinput does it for us */
pInfo->options = xf86ReplaceIntOption(pInfo->options, "AccelerationProfile", -1);
@@ -1197,11 +1253,9 @@ xf86libinput_pre_init(InputDriverPtr drv,
/* now pick an actual type */
if (libinput_device_config_tap_get_finger_count(device) > 0)
pInfo->type_name = XI_TOUCHPAD;
- else if (libinput_device_has_capability(device,
- LIBINPUT_DEVICE_CAP_TOUCH))
+ else if (capabilities & AS_MASK(LIBINPUT_DEVICE_CAP_TOUCH))
pInfo->type_name = XI_TOUCHSCREEN;
- else if (libinput_device_has_capability(device,
- LIBINPUT_DEVICE_CAP_POINTER))
+ else if (capabilities & AS_MASK(LIBINPUT_DEVICE_CAP_POINTER))
pInfo->type_name = XI_MOUSE;
else
pInfo->type_name = XI_KEYBOARD;
--
2.1.0
More information about the xorg-devel
mailing list