commit 1c1c5a8

Michael Forney  ·  2014-07-16 01:40:39 +0000 UTC
parent a77e11d
Add optional support for libinput

Fixes #5.
3 files changed,  +178, -136
+5, -5
 1@@ -14,9 +14,9 @@ CFLAGS          = -pipe
 2 # PKG_CONFIG      = pkg-config
 3 # WAYLAND_SCANNER = wayland-scanner
 4 
 5-ENABLE_DEBUG        = 1
 6-ENABLE_STATIC       = 1
 7-ENABLE_SHARED       = 1
 8-ENABLE_HOTPLUGGING  = 1
 9-ENABLE_XWAYLAND     = 1
10+ENABLE_DEBUG    = 1
11+ENABLE_STATIC   = 1
12+ENABLE_SHARED   = 1
13+ENABLE_LIBINPUT = 1
14+ENABLE_XWAYLAND = 1
15 
+5, -4
 1@@ -35,7 +35,6 @@ SWC_SOURCES =                       \
 2     libswc/data_device.c            \
 3     libswc/data_device_manager.c    \
 4     libswc/drm.c                    \
 5-    libswc/evdev_device.c           \
 6     libswc/framebuffer_plane.c      \
 7     libswc/input.c                  \
 8     libswc/keyboard.c               \
 9@@ -61,9 +60,11 @@ SWC_SOURCES =                       \
10     protocol/swc-protocol.c         \
11     protocol/wayland-drm-protocol.c
12 
13-ifeq ($(ENABLE_HOTPLUGGING),1)
14-$(dir)_CFLAGS += -DENABLE_HOTPLUGGING
15-$(dir)_PACKAGES += libudev
16+ifeq ($(ENABLE_LIBINPUT),1)
17+$(dir)_CFLAGS += -DENABLE_LIBINPUT
18+$(dir)_PACKAGES += libinput libudev
19+else
20+SWC_SOURCES += libswc/evdev_device.c
21 endif
22 
23 ifeq ($(ENABLE_XWAYLAND),1)
+168, -127
  1@@ -32,12 +32,15 @@
  2 #include "pointer.h"
  3 #include "util.h"
  4 
  5+#include <errno.h>
  6 #include <dirent.h>
  7 #include <stdlib.h>
  8 #include <stdio.h>
  9 #include <string.h>
 10-#ifdef ENABLE_HOTPLUGGING
 11+#include <unistd.h>
 12+#ifdef ENABLE_LIBINPUT
 13 # include <libudev.h>
 14+# include <libinput.h>
 15 #endif
 16 
 17 static struct
 18@@ -45,10 +48,12 @@ static struct
 19     char * name;
 20     uint32_t capabilities;
 21 
 22-#ifdef ENABLE_HOTPLUGGING
 23+#ifdef ENABLE_LIBINPUT
 24     struct udev * udev;
 25-    struct udev_monitor * monitor;
 26-    struct wl_event_source * monitor_source;
 27+    struct libinput * libinput;
 28+    struct wl_event_source * libinput_source;
 29+#else
 30+    struct wl_list devices;
 31 #endif
 32 
 33     struct keyboard keyboard;
 34@@ -57,7 +62,6 @@ static struct
 35 
 36     struct wl_global * global;
 37     struct wl_list resources;
 38-    struct wl_list devices;
 39 } seat;
 40 
 41 const struct swc_seat swc_seat = {
 42@@ -86,13 +90,6 @@ static void handle_relative_motion(uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
 43     pointer_handle_relative_motion(&seat.pointer, time, dx, dy);
 44 }
 45 
 46-const static struct swc_evdev_device_handler evdev_handler = {
 47-    .key = &handle_key,
 48-    .button = &handle_button,
 49-    .axis = &handle_axis,
 50-    .relative_motion = &handle_relative_motion
 51-};
 52-
 53 static void handle_keyboard_focus_event(struct wl_listener * listener,
 54                                         void * data)
 55 {
 56@@ -142,11 +139,22 @@ static struct wl_listener data_device_listener = {
 57 static void handle_launch_event(struct wl_listener * listener, void * data)
 58 {
 59     struct swc_event * event = data;
 60-    struct swc_evdev_device * device, * next;
 61 
 62     switch (event->type)
 63     {
 64+        case SWC_LAUNCH_EVENT_DEACTIVATED:
 65+#ifdef ENABLE_LIBINPUT
 66+            libinput_suspend(seat.libinput);
 67+#endif
 68+            break;
 69         case SWC_LAUNCH_EVENT_ACTIVATED:
 70+        {
 71+#ifdef ENABLE_LIBINPUT
 72+            if (libinput_resume(seat.libinput) != 0)
 73+                WARNING("Failed to resume libinput context\n");
 74+#else
 75+            struct swc_evdev_device * device, * next;
 76+
 77             /* Re-open all input devices */
 78             wl_list_for_each_safe(device, next, &seat.devices, link)
 79             {
 80@@ -156,8 +164,9 @@ static void handle_launch_event(struct wl_listener * listener, void * data)
 81                     swc_evdev_device_destroy(device);
 82                 }
 83             }
 84-
 85+#endif
 86             break;
 87+        }
 88     }
 89 }
 90 
 91@@ -209,159 +218,194 @@ static void bind_seat(struct wl_client * client, void * data, uint32_t version,
 92     wl_seat_send_capabilities(resource, seat.capabilities);
 93 }
 94 
 95-static void add_device(const char * path)
 96+#ifdef ENABLE_LIBINPUT
 97+static int open_restricted(const char * path, int flags, void * user_data)
 98 {
 99-    struct swc_evdev_device * device;
100-
101-    if (!(device = swc_evdev_device_new(path, &evdev_handler)))
102-    {
103-        ERROR("Could not create evdev device\n");
104-        return;
105-    }
106-
107-    if (~seat.capabilities & device->capabilities)
108-    {
109-        struct wl_resource * resource;
110-
111-        seat.capabilities |= device->capabilities;
112-        wl_list_for_each(resource, &seat.resources, link)
113-            wl_seat_send_capabilities(resource, seat.capabilities);
114-    }
115-
116-    wl_list_insert(&seat.devices, &device->link);
117+    return swc_launch_open_device(path, flags);
118 }
119 
120-static int select_device(const struct dirent * entry)
121+static void close_restricted(int fd, void * user_data)
122 {
123-    unsigned num;
124-
125-    return sscanf(entry->d_name, "event%u", &num) == 1;
126+    close(fd);
127 }
128 
129-static bool add_devices()
130-{
131-    struct dirent ** devices;
132-    int num_devices;
133-    char path[64];
134-    unsigned index;
135+const struct libinput_interface libinput_interface = {
136+    .open_restricted = &open_restricted,
137+    .close_restricted = &close_restricted,
138+};
139 
140-    num_devices = scandir("/dev/input", &devices, &select_device, &alphasort);
141+static int handle_libinput_data(int fd, uint32_t mask, void * data)
142+{
143+    struct libinput_event * generic_event;
144 
145-    if (num_devices == -1)
146+    if (libinput_dispatch(seat.libinput) != 0)
147     {
148-        ERROR("Failed to scan /dev/input for event devices\n");
149-        return false;
150+        WARNING("libinput_dispatch failed: %s\n", strerror(errno));
151+        return 0;
152     }
153 
154-    for (index = 0; index < num_devices; ++index)
155+    while ((generic_event = libinput_get_event(seat.libinput)))
156     {
157-        snprintf(path, sizeof path, "/dev/input/%s", devices[index]->d_name);
158-        free(devices[index]);
159-        add_device(path);
160-    }
161-
162-    free(devices);
163-
164-    return true;
165-}
166-
167-#ifdef ENABLE_HOTPLUGGING
168-static int handle_monitor_data(int fd, uint32_t mask, void * data)
169-{
170-    struct udev_device * udev_device;
171-    const char * path, * action, * sysname;
172-    unsigned num;
173-
174-    if (!(udev_device = udev_monitor_receive_device(seat.monitor)))
175-        return 0;
176-
177-    if (!(action = udev_device_get_action(udev_device)))
178-        goto done;
179-
180-    sysname = udev_device_get_sysname(udev_device);
181-
182-    if (sscanf(sysname, "event%u", &num) != 1)
183-        goto done;
184-
185-    path = udev_device_get_devnode(udev_device);
186+        switch (libinput_event_get_type(generic_event))
187+        {
188+            case LIBINPUT_EVENT_KEYBOARD_KEY:
189+            {
190+                struct libinput_event_keyboard * event;
191 
192-    if (strcmp(action, "add") == 0)
193-        add_device(path);
194-    else if (strcmp(action, "remove") == 0)
195-    {
196-        struct swc_evdev_device * device, * next;
197+                event = libinput_event_get_keyboard_event(generic_event);
198+                handle_key(libinput_event_keyboard_get_time(event),
199+                           libinput_event_keyboard_get_key(event),
200+                           libinput_event_keyboard_get_key_state(event));
201+                break;
202+            }
203+            case LIBINPUT_EVENT_POINTER_MOTION:
204+            {
205+                struct libinput_event_pointer * event;
206+                wl_fixed_t dx, dy;
207+
208+                event = libinput_event_get_pointer_event(generic_event);
209+                dx = wl_fixed_from_double(libinput_event_pointer_get_dx(event));
210+                dy = wl_fixed_from_double(libinput_event_pointer_get_dy(event));
211+                handle_relative_motion(libinput_event_pointer_get_time(event),
212+                                       dx, dy);
213+                break;
214+            }
215+            case LIBINPUT_EVENT_POINTER_BUTTON:
216+            {
217+                struct libinput_event_pointer * event;
218 
219-        wl_list_for_each_safe(device, next, &seat.devices, link)
220-        {
221-            if (strcmp(device->path, path) == 0)
222+                event = libinput_event_get_pointer_event(generic_event);
223+                handle_button(libinput_event_pointer_get_time(event),
224+                              libinput_event_pointer_get_button(event),
225+                              libinput_event_pointer_get_button_state(event));
226+                break;
227+            }
228+            case LIBINPUT_EVENT_POINTER_AXIS:
229             {
230-                wl_list_remove(&device->link);
231-                swc_evdev_device_destroy(device);
232+                struct libinput_event_pointer * event;
233+                wl_fixed_t amount;
234+
235+                event = libinput_event_get_pointer_event(generic_event);
236+                amount = wl_fixed_from_double
237+                    (libinput_event_pointer_get_axis_value(event));
238+                handle_axis(libinput_event_pointer_get_time(event),
239+                            libinput_event_pointer_get_axis(event), amount);
240                 break;
241             }
242+            default:
243+                break;
244         }
245+
246+        libinput_event_destroy(generic_event);
247     }
248 
249-  done:
250-    udev_device_unref(udev_device);
251     return 0;
252 }
253 
254-bool initialize_monitor()
255+bool initialize_libinput(const char * seat_name)
256 {
257-    int fd;
258-
259     if (!(seat.udev = udev_new()))
260     {
261         ERROR("Could not create udev context\n");
262         goto error0;
263     }
264 
265-    if (!(seat.monitor = udev_monitor_new_from_netlink(seat.udev, "udev")))
266-    {
267-        ERROR("Could not create udev monitor\n");
268-        goto error1;
269-    }
270+    seat.libinput = libinput_udev_create_context(&libinput_interface, NULL,
271+                                                 seat.udev);
272 
273-    if (udev_monitor_filter_add_match_subsystem_devtype(seat.monitor,
274-                                                        "input", NULL) != 0)
275+    if (!seat.libinput)
276     {
277-        ERROR("Could not set up udev monitor filter\n");
278-        goto error2;
279+        ERROR("Could not create libinput context\n");
280+        goto error1;
281     }
282 
283-    if (udev_monitor_enable_receiving(seat.monitor) != 0)
284+    if (libinput_udev_assign_seat(seat.libinput, seat_name) != 0)
285     {
286-        ERROR("Could not enable receiving for udev monitor\n");
287+        ERROR("Failed to assign seat to libinput context\n");
288         goto error2;
289     }
290 
291-    fd = udev_monitor_get_fd(seat.monitor);
292-    seat.monitor_source = wl_event_loop_add_fd
293-        (swc.event_loop, fd, WL_EVENT_READABLE, &handle_monitor_data, NULL);
294+    seat.libinput_source = wl_event_loop_add_fd
295+        (swc.event_loop, libinput_get_fd(seat.libinput), WL_EVENT_READABLE,
296+         &handle_libinput_data, NULL);
297 
298-    if (!seat.monitor_source)
299+    if (!seat.libinput_source)
300     {
301-        ERROR("Could not create event source for udev monitor\n");
302+        ERROR("Could not create event source for libinput\n");
303         goto error2;
304     }
305 
306     return true;
307 
308   error2:
309-    udev_monitor_unref(seat.monitor);
310+    libinput_unref(seat.libinput);
311   error1:
312     udev_unref(seat.udev);
313   error0:
314     return false;
315 }
316 
317-void finalize_monitor()
318+void finalize_libinput()
319 {
320-    wl_event_source_remove(seat.monitor_source);
321-    udev_monitor_unref(seat.monitor);
322+    wl_event_source_remove(seat.libinput_source);
323+    libinput_unref(seat.libinput);
324     udev_unref(seat.udev);
325 }
326+#else
327+const static struct swc_evdev_device_handler evdev_handler = {
328+    .key = &handle_key,
329+    .button = &handle_button,
330+    .axis = &handle_axis,
331+    .relative_motion = &handle_relative_motion,
332+};
333+
334+static void add_device(const char * path)
335+{
336+    struct swc_evdev_device * device;
337+
338+    if (!(device = swc_evdev_device_new(path, &evdev_handler)))
339+    {
340+        ERROR("Could not create evdev device\n");
341+        return;
342+    }
343+
344+    update_capabilities(device->capabilities);
345+    wl_list_insert(&seat.devices, &device->link);
346+}
347+
348+static int select_device(const struct dirent * entry)
349+{
350+    unsigned num;
351+
352+    return sscanf(entry->d_name, "event%u", &num) == 1;
353+}
354+
355+static bool add_devices()
356+{
357+    struct dirent ** devices;
358+    int num_devices;
359+    char path[64];
360+    unsigned index;
361+
362+    num_devices = scandir("/dev/input", &devices, &select_device, &alphasort);
363+
364+    if (num_devices == -1)
365+    {
366+        ERROR("Failed to scan /dev/input for event devices\n");
367+        return false;
368+    }
369+
370+    for (index = 0; index < num_devices; ++index)
371+    {
372+        snprintf(path, sizeof path, "/dev/input/%s", devices[index]->d_name);
373+        free(devices[index]);
374+        add_device(path);
375+    }
376+
377+    free(devices);
378+
379+    return true;
380+}
381 #endif
382 
383 bool swc_seat_initialize(const char * seat_name)
384@@ -380,7 +424,6 @@ bool swc_seat_initialize(const char * seat_name)
385 
386     seat.capabilities = 0;
387     wl_list_init(&seat.resources);
388-    wl_list_init(&seat.devices);
389     wl_signal_add(&swc.launch->event_signal, &launch_listener);
390 
391     if (!swc_data_device_initialize(&seat.data_device))
392@@ -405,21 +448,19 @@ bool swc_seat_initialize(const char * seat_name)
393         goto error4;
394     }
395 
396-#ifdef ENABLE_HOTPLUGGING
397-    if (!initialize_monitor())
398+#ifdef ENABLE_LIBINPUT
399+    if (!initialize_libinput(seat.name))
400         goto error5;
401-#endif
402+#else
403+    wl_list_init(&seat.devices);
404 
405     if (!add_devices())
406-        goto error6;
407+        goto error5;
408+#endif
409 
410     return true;
411 
412-  error6:
413-#ifdef ENABLE_HOTPLUGGING
414-    finalize_monitor();
415   error5:
416-#endif
417     pointer_finalize(&seat.pointer);
418   error4:
419     keyboard_finalize(&seat.keyboard);
420@@ -435,17 +476,17 @@ bool swc_seat_initialize(const char * seat_name)
421 
422 void swc_seat_finalize()
423 {
424+#ifdef ENABLE_LIBINPUT
425+    finalize_libinput();
426+#else
427     struct swc_evdev_device * device, * tmp;
428-
429-#ifdef ENABLE_HOTPLUGGING
430-    finalize_monitor();
431+    wl_list_for_each_safe(device, tmp, &seat.devices, link)
432+        swc_evdev_device_destroy(device);
433 #endif
434+
435     pointer_finalize(&seat.pointer);
436     keyboard_finalize(&seat.keyboard);
437 
438-    wl_list_for_each_safe(device, tmp, &seat.devices, link)
439-        swc_evdev_device_destroy(device);
440-
441     wl_global_destroy(seat.global);
442     free(seat.name);
443 }