1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Copyright (C) 2010  Intel Corp.
7  * Copyright (C) 2014  Jonas Ådahl
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
21  *
22  * Author: Damien Lespiau <damien.lespiau@intel.com>
23  * Author: Jonas Ådahl <jadahl@gmail.com>
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include "clutter-build-config.h"
28 #endif
29 
30 #include <math.h>
31 #include <float.h>
32 #include <linux/input.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <string.h>
38 #include <unistd.h>
39 
40 #include <glib.h>
41 #include <libinput.h>
42 
43 #include "clutter-backend.h"
44 #include "clutter-debug.h"
45 #include "clutter-device-manager.h"
46 #include "clutter-device-manager-private.h"
47 #include "clutter-event-private.h"
48 #include "clutter-input-device-evdev.h"
49 #include "clutter-seat-evdev.h"
50 #include "clutter-virtual-input-device-evdev.h"
51 #include "clutter-main.h"
52 #include "clutter-private.h"
53 #include "clutter-stage-manager.h"
54 #include "clutter-xkb-utils.h"
55 #include "clutter-backend-private.h"
56 #include "clutter-evdev.h"
57 #include "clutter-stage-private.h"
58 #include "clutter-input-device-tool-evdev.h"
59 
60 #include "clutter-device-manager-evdev.h"
61 
62 /*
63  * Clutter makes the assumption that two core devices have ID's 2 and 3 (core
64  * pointer and core keyboard).
65  *
66  * Since the two first devices that will ever be created will be the virtual
67  * pointer and virtual keyboard of the first seat, we fulfill the made
68  * assumptions by having the first device having ID 2 and following 3.
69  */
70 #define INITIAL_DEVICE_ID 2
71 
72 typedef struct _ClutterEventFilter ClutterEventFilter;
73 
74 struct _ClutterEventFilter
75 {
76   ClutterEvdevFilterFunc func;
77   gpointer data;
78   GDestroyNotify destroy_notify;
79 };
80 
81 typedef struct _ClutterEventSource  ClutterEventSource;
82 
83 struct _ClutterDeviceManagerEvdevPrivate
84 {
85   struct libinput *libinput;
86 
87   ClutterStage *stage;
88   gboolean released;
89 
90   ClutterEventSource *event_source;
91 
92   GSList *devices;
93   GSList *seats;
94 
95   ClutterSeatEvdev *main_seat;
96   struct xkb_keymap *keymap;
97 
98   ClutterPointerConstrainCallback constrain_callback;
99   gpointer                        constrain_data;
100   GDestroyNotify                  constrain_data_notify;
101 
102   ClutterRelativeMotionFilter relative_motion_filter;
103   gpointer relative_motion_filter_user_data;
104 
105   ClutterStageManager *stage_manager;
106   guint stage_added_handler;
107   guint stage_removed_handler;
108 
109   GSList *event_filters;
110 
111   gint device_id_next;
112   GList *free_device_ids;
113 };
114 
115 static void clutter_device_manager_evdev_event_extender_init (ClutterEventExtenderInterface *iface);
116 
117 G_DEFINE_TYPE_WITH_CODE (ClutterDeviceManagerEvdev,
118                          clutter_device_manager_evdev,
119                          CLUTTER_TYPE_DEVICE_MANAGER,
120                          G_ADD_PRIVATE (ClutterDeviceManagerEvdev)
121                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_EXTENDER,
122                                                 clutter_device_manager_evdev_event_extender_init))
123 
124 static ClutterOpenDeviceCallback  device_open_callback;
125 static ClutterCloseDeviceCallback device_close_callback;
126 static gpointer                   device_callback_data;
127 static gchar *                    evdev_seat_id;
128 
129 #ifdef CLUTTER_ENABLE_DEBUG
130 static const char *device_type_str[] = {
131   "pointer",            /* CLUTTER_POINTER_DEVICE */
132   "keyboard",           /* CLUTTER_KEYBOARD_DEVICE */
133   "extension",          /* CLUTTER_EXTENSION_DEVICE */
134   "joystick",           /* CLUTTER_JOYSTICK_DEVICE */
135   "tablet",             /* CLUTTER_TABLET_DEVICE */
136   "touchpad",           /* CLUTTER_TOUCHPAD_DEVICE */
137   "touchscreen",        /* CLUTTER_TOUCHSCREEN_DEVICE */
138   "pen",                /* CLUTTER_PEN_DEVICE */
139   "eraser",             /* CLUTTER_ERASER_DEVICE */
140   "cursor",             /* CLUTTER_CURSOR_DEVICE */
141   "pad",                /* CLUTTER_PAD_DEVICE */
142 };
143 #endif /* CLUTTER_ENABLE_DEBUG */
144 
145 /*
146  * ClutterEventSource management
147  *
148  * The device manager is responsible for managing the GSource when devices
149  * appear and disappear from the system.
150  */
151 
152 static const char *option_xkb_layout = "us";
153 static const char *option_xkb_variant = "";
154 static const char *option_xkb_options = "";
155 
156 static void
clutter_device_manager_evdev_copy_event_data(ClutterEventExtender * event_extender,const ClutterEvent * src,ClutterEvent * dest)157 clutter_device_manager_evdev_copy_event_data (ClutterEventExtender *event_extender,
158                                               const ClutterEvent   *src,
159                                               ClutterEvent         *dest)
160 {
161   ClutterEventEvdev *event_evdev;
162 
163   event_evdev = _clutter_event_get_platform_data (src);
164   if (event_evdev != NULL)
165     _clutter_event_set_platform_data (dest, _clutter_event_evdev_copy (event_evdev));
166 }
167 
168 static void
clutter_device_manager_evdev_free_event_data(ClutterEventExtender * event_extender,ClutterEvent * event)169 clutter_device_manager_evdev_free_event_data (ClutterEventExtender *event_extender,
170                                               ClutterEvent         *event)
171 {
172   ClutterEventEvdev *event_evdev;
173 
174   event_evdev = _clutter_event_get_platform_data (event);
175   if (event_evdev != NULL)
176     _clutter_event_evdev_free (event_evdev);
177 }
178 
179 static void
clutter_device_manager_evdev_event_extender_init(ClutterEventExtenderInterface * iface)180 clutter_device_manager_evdev_event_extender_init (ClutterEventExtenderInterface *iface)
181 {
182   iface->copy_event_data = clutter_device_manager_evdev_copy_event_data;
183   iface->free_event_data = clutter_device_manager_evdev_free_event_data;
184 }
185 
186 /*
187  * ClutterEventSource for reading input devices
188  */
189 
190 struct _ClutterEventSource
191 {
192   GSource source;
193 
194   ClutterDeviceManagerEvdev *manager_evdev;
195   GPollFD event_poll_fd;
196 };
197 
198 static void
199 process_events (ClutterDeviceManagerEvdev *manager_evdev);
200 
201 static gboolean
clutter_event_prepare(GSource * source,gint * timeout)202 clutter_event_prepare (GSource *source,
203                        gint    *timeout)
204 {
205   gboolean retval;
206 
207   _clutter_threads_acquire_lock ();
208 
209   *timeout = -1;
210   retval = clutter_events_pending ();
211 
212   _clutter_threads_release_lock ();
213 
214   return retval;
215 }
216 
217 static gboolean
clutter_event_check(GSource * source)218 clutter_event_check (GSource *source)
219 {
220   ClutterEventSource *event_source = (ClutterEventSource *) source;
221   gboolean retval;
222 
223   _clutter_threads_acquire_lock ();
224 
225   retval = ((event_source->event_poll_fd.revents & G_IO_IN) ||
226             clutter_events_pending ());
227 
228   _clutter_threads_release_lock ();
229 
230   return retval;
231 }
232 
233 static void
queue_event(ClutterEvent * event)234 queue_event (ClutterEvent *event)
235 {
236   _clutter_event_push (event, FALSE);
237 }
238 
239 void
_clutter_device_manager_evdev_constrain_pointer(ClutterDeviceManagerEvdev * manager_evdev,ClutterInputDevice * core_pointer,uint64_t time_us,float x,float y,float * new_x,float * new_y)240 _clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev,
241                                                  ClutterInputDevice        *core_pointer,
242                                                  uint64_t                   time_us,
243                                                  float                      x,
244                                                  float                      y,
245                                                  float                     *new_x,
246                                                  float                     *new_y)
247 {
248   if (manager_evdev->priv->constrain_callback)
249     {
250       manager_evdev->priv->constrain_callback (core_pointer,
251                                                us2ms (time_us),
252                                                x, y,
253                                                new_x, new_y,
254 					       manager_evdev->priv->constrain_data);
255     }
256   else
257     {
258       ClutterActor *stage = CLUTTER_ACTOR (manager_evdev->priv->stage);
259       float stage_width = clutter_actor_get_width (stage);
260       float stage_height = clutter_actor_get_height (stage);
261 
262       x = CLAMP (x, 0.f, stage_width - 1);
263       y = CLAMP (y, 0.f, stage_height - 1);
264     }
265 }
266 
267 void
_clutter_device_manager_evdev_filter_relative_motion(ClutterDeviceManagerEvdev * manager_evdev,ClutterInputDevice * device,float x,float y,float * dx,float * dy)268 _clutter_device_manager_evdev_filter_relative_motion (ClutterDeviceManagerEvdev *manager_evdev,
269                                                       ClutterInputDevice        *device,
270                                                       float                      x,
271                                                       float                      y,
272                                                       float                     *dx,
273                                                       float                     *dy)
274 {
275   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
276 
277   if (!priv->relative_motion_filter)
278     return;
279 
280   priv->relative_motion_filter (device, x, y, dx, dy,
281                                 priv->relative_motion_filter_user_data);
282 }
283 
284 static ClutterEvent *
new_absolute_motion_event(ClutterInputDevice * input_device,guint64 time_us,gfloat x,gfloat y,gdouble * axes)285 new_absolute_motion_event (ClutterInputDevice *input_device,
286                            guint64             time_us,
287                            gfloat              x,
288                            gfloat              y,
289                            gdouble            *axes)
290 {
291   gfloat stage_width, stage_height;
292   ClutterDeviceManagerEvdev *manager_evdev;
293   ClutterInputDeviceEvdev *device_evdev;
294   ClutterSeatEvdev *seat;
295   ClutterStage *stage;
296   ClutterEvent *event = NULL;
297 
298   stage = _clutter_input_device_get_stage (input_device);
299   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
300   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (input_device->device_manager);
301   seat = _clutter_input_device_evdev_get_seat (device_evdev);
302 
303   stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
304   stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
305 
306   event = clutter_event_new (CLUTTER_MOTION);
307 
308   if (manager_evdev->priv->constrain_callback &&
309       clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
310     {
311       manager_evdev->priv->constrain_callback (seat->core_pointer,
312                                                us2ms (time_us),
313                                                seat->pointer_x,
314                                                seat->pointer_y,
315                                                &x, &y,
316 					       manager_evdev->priv->constrain_data);
317     }
318   else
319     {
320       x = CLAMP (x, 0.f, stage_width - 1);
321       y = CLAMP (y, 0.f, stage_height - 1);
322     }
323 
324   _clutter_evdev_event_set_time_usec (event, time_us);
325   event->motion.time = us2ms (time_us);
326   event->motion.stage = stage;
327   event->motion.device = seat->core_pointer;
328   _clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
329   event->motion.x = x;
330   event->motion.y = y;
331   clutter_input_device_evdev_translate_coordinates (input_device, stage,
332                                                     &event->motion.x,
333                                                     &event->motion.y);
334   event->motion.axes = axes;
335   clutter_event_set_source_device (event, input_device);
336 
337   if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
338     {
339       clutter_event_set_device_tool (event, device_evdev->last_tool);
340       clutter_event_set_device (event, input_device);
341     }
342   else
343     clutter_event_set_device (event, seat->core_pointer);
344 
345   _clutter_input_device_set_stage (seat->core_pointer, stage);
346 
347   if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
348     {
349       seat->pointer_x = x;
350       seat->pointer_y = y;
351     }
352 
353   return event;
354 }
355 
356 static void
notify_absolute_motion(ClutterInputDevice * input_device,guint64 time_us,gfloat x,gfloat y,gdouble * axes)357 notify_absolute_motion (ClutterInputDevice *input_device,
358                         guint64             time_us,
359                         gfloat              x,
360                         gfloat              y,
361                         gdouble            *axes)
362 {
363   ClutterEvent *event;
364 
365   event = new_absolute_motion_event (input_device, time_us, x, y, axes);
366 
367   queue_event (event);
368 }
369 
370 static void
notify_relative_tool_motion(ClutterInputDevice * input_device,guint64 time_us,gfloat dx,gfloat dy,gdouble * axes)371 notify_relative_tool_motion (ClutterInputDevice *input_device,
372                              guint64             time_us,
373                              gfloat              dx,
374                              gfloat              dy,
375                              gdouble            *axes)
376 {
377   ClutterInputDeviceEvdev *device_evdev;
378   ClutterEvent *event;
379   ClutterSeatEvdev *seat;
380   gfloat x, y;
381 
382   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
383   seat = _clutter_input_device_evdev_get_seat (device_evdev);
384   x = input_device->current_x + dx;
385   y = input_device->current_y + dy;
386 
387   _clutter_device_manager_evdev_filter_relative_motion (seat->manager_evdev,
388                                                         input_device,
389                                                         seat->pointer_x,
390                                                         seat->pointer_y,
391                                                         &dx,
392                                                         &dy);
393 
394   event = new_absolute_motion_event (input_device, time_us, x, y, axes);
395   _clutter_evdev_event_set_relative_motion (event, dx, dy, 0, 0);
396 
397   queue_event (event);
398 }
399 
400 static void
notify_pinch_gesture_event(ClutterInputDevice * input_device,ClutterTouchpadGesturePhase phase,guint64 time_us,gdouble dx,gdouble dy,gdouble angle_delta,gdouble scale,guint n_fingers)401 notify_pinch_gesture_event (ClutterInputDevice          *input_device,
402                             ClutterTouchpadGesturePhase  phase,
403                             guint64                      time_us,
404                             gdouble                      dx,
405                             gdouble                      dy,
406                             gdouble                      angle_delta,
407                             gdouble                      scale,
408                             guint                        n_fingers)
409 {
410   ClutterInputDeviceEvdev *device_evdev;
411   ClutterSeatEvdev *seat;
412   ClutterStage *stage;
413   ClutterEvent *event = NULL;
414   ClutterPoint pos;
415 
416   /* We can drop the event on the floor if no stage has been
417    * associated with the device yet. */
418   stage = _clutter_input_device_get_stage (input_device);
419   if (stage == NULL)
420     return;
421 
422   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
423   seat = _clutter_input_device_evdev_get_seat (device_evdev);
424 
425   event = clutter_event_new (CLUTTER_TOUCHPAD_PINCH);
426 
427   clutter_input_device_get_coords (seat->core_pointer, NULL, &pos);
428 
429   _clutter_evdev_event_set_time_usec (event, time_us);
430   event->touchpad_pinch.phase = phase;
431   event->touchpad_pinch.time = us2ms (time_us);
432   event->touchpad_pinch.stage = CLUTTER_STAGE (stage);
433   event->touchpad_pinch.x = pos.x;
434   event->touchpad_pinch.y = pos.y;
435   event->touchpad_pinch.dx = dx;
436   event->touchpad_pinch.dy = dy;
437   event->touchpad_pinch.angle_delta = angle_delta;
438   event->touchpad_pinch.scale = scale;
439   event->touchpad_pinch.n_fingers = n_fingers;
440 
441   _clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
442 
443   clutter_event_set_device (event, seat->core_pointer);
444   clutter_event_set_source_device (event, input_device);
445 
446   queue_event (event);
447 }
448 
449 static void
notify_swipe_gesture_event(ClutterInputDevice * input_device,ClutterTouchpadGesturePhase phase,guint64 time_us,guint n_fingers,gdouble dx,gdouble dy)450 notify_swipe_gesture_event (ClutterInputDevice          *input_device,
451                             ClutterTouchpadGesturePhase  phase,
452                             guint64                      time_us,
453                             guint                        n_fingers,
454                             gdouble                      dx,
455                             gdouble                      dy)
456 {
457   ClutterInputDeviceEvdev *device_evdev;
458   ClutterSeatEvdev *seat;
459   ClutterStage *stage;
460   ClutterEvent *event = NULL;
461   ClutterPoint pos;
462 
463   /* We can drop the event on the floor if no stage has been
464    * associated with the device yet. */
465   stage = _clutter_input_device_get_stage (input_device);
466   if (stage == NULL)
467     return;
468 
469   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
470   seat = _clutter_input_device_evdev_get_seat (device_evdev);
471 
472   event = clutter_event_new (CLUTTER_TOUCHPAD_SWIPE);
473 
474   _clutter_evdev_event_set_time_usec (event, time_us);
475   event->touchpad_swipe.phase = phase;
476   event->touchpad_swipe.time = us2ms (time_us);
477   event->touchpad_swipe.stage = CLUTTER_STAGE (stage);
478 
479   clutter_input_device_get_coords (seat->core_pointer, NULL, &pos);
480   event->touchpad_swipe.x = pos.x;
481   event->touchpad_swipe.y = pos.y;
482   event->touchpad_swipe.dx = dx;
483   event->touchpad_swipe.dy = dy;
484   event->touchpad_swipe.n_fingers = n_fingers;
485 
486   _clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
487 
488   clutter_event_set_device (event, seat->core_pointer);
489   clutter_event_set_source_device (event, input_device);
490 
491   queue_event (event);
492 }
493 
494 static void
notify_proximity(ClutterInputDevice * input_device,guint64 time_us,gboolean in)495 notify_proximity (ClutterInputDevice *input_device,
496                   guint64             time_us,
497                   gboolean            in)
498 {
499   ClutterInputDeviceEvdev *device_evdev;
500   ClutterSeatEvdev *seat;
501   ClutterStage *stage;
502   ClutterEvent *event = NULL;
503 
504   /* We can drop the event on the floor if no stage has been
505    * associated with the device yet. */
506   stage = _clutter_input_device_get_stage (input_device);
507   if (stage == NULL)
508     return;
509 
510   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
511   seat = _clutter_input_device_evdev_get_seat (device_evdev);
512 
513   if (in)
514     event = clutter_event_new (CLUTTER_PROXIMITY_IN);
515   else
516     event = clutter_event_new (CLUTTER_PROXIMITY_OUT);
517 
518   _clutter_evdev_event_set_time_usec (event, time_us);
519 
520   event->proximity.time = us2ms (time_us);
521   event->proximity.stage = CLUTTER_STAGE (stage);
522   event->proximity.device = seat->core_pointer;
523   clutter_event_set_device_tool (event, device_evdev->last_tool);
524   clutter_event_set_device (event, seat->core_pointer);
525   clutter_event_set_source_device (event, input_device);
526 
527   _clutter_input_device_set_stage (seat->core_pointer, stage);
528 
529   queue_event (event);
530 }
531 
532 static void
notify_pad_button(ClutterInputDevice * input_device,guint64 time_us,guint32 button,guint32 mode_group,guint32 mode,guint32 pressed)533 notify_pad_button (ClutterInputDevice *input_device,
534                    guint64             time_us,
535                    guint32             button,
536                    guint32             mode_group,
537                    guint32             mode,
538                    guint32             pressed)
539 {
540   ClutterInputDeviceEvdev *device_evdev;
541   ClutterSeatEvdev *seat;
542   ClutterStage *stage;
543   ClutterEvent *event;
544 
545   /* We can drop the event on the floor if no stage has been
546    * associated with the device yet. */
547   stage = _clutter_input_device_get_stage (input_device);
548   if (stage == NULL)
549     return;
550 
551   if (pressed)
552     event = clutter_event_new (CLUTTER_PAD_BUTTON_PRESS);
553   else
554     event = clutter_event_new (CLUTTER_PAD_BUTTON_RELEASE);
555 
556   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
557   seat = _clutter_input_device_evdev_get_seat (device_evdev);
558 
559   _clutter_evdev_event_set_time_usec (event, time_us);
560   event->pad_button.stage = stage;
561   event->pad_button.button = button;
562   event->pad_button.group = mode_group;
563   event->pad_button.mode = mode;
564   clutter_event_set_device (event, input_device);
565   clutter_event_set_source_device (event, input_device);
566   clutter_event_set_time (event, us2ms (time_us));
567 
568   _clutter_input_device_set_stage (seat->core_pointer, stage);
569 
570   queue_event (event);
571 }
572 
573 static void
notify_pad_strip(ClutterInputDevice * input_device,guint64 time_us,guint32 strip_number,guint32 strip_source,guint32 mode_group,guint32 mode,gdouble value)574 notify_pad_strip (ClutterInputDevice *input_device,
575                   guint64             time_us,
576                   guint32             strip_number,
577                   guint32             strip_source,
578                   guint32             mode_group,
579                   guint32             mode,
580                   gdouble             value)
581 {
582   ClutterInputDeviceEvdev *device_evdev;
583   ClutterInputDevicePadSource source;
584   ClutterSeatEvdev *seat;
585   ClutterStage *stage;
586   ClutterEvent *event;
587 
588   /* We can drop the event on the floor if no stage has been
589    * associated with the device yet. */
590   stage = _clutter_input_device_get_stage (input_device);
591   if (stage == NULL)
592     return;
593 
594   if (strip_source == LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER)
595     source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER;
596   else
597     source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN;
598 
599   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
600   seat = _clutter_input_device_evdev_get_seat (device_evdev);
601 
602   event = clutter_event_new (CLUTTER_PAD_STRIP);
603   _clutter_evdev_event_set_time_usec (event, time_us);
604   event->pad_strip.strip_source = source;
605   event->pad_strip.stage = stage;
606   event->pad_strip.strip_number = strip_number;
607   event->pad_strip.value = value;
608   event->pad_strip.group = mode_group;
609   event->pad_strip.mode = mode;
610   clutter_event_set_device (event, input_device);
611   clutter_event_set_source_device (event, input_device);
612   clutter_event_set_time (event, us2ms (time_us));
613 
614   _clutter_input_device_set_stage (seat->core_pointer, stage);
615 
616   queue_event (event);
617 }
618 
619 static void
notify_pad_ring(ClutterInputDevice * input_device,guint64 time_us,guint32 ring_number,guint32 ring_source,guint32 mode_group,guint32 mode,gdouble angle)620 notify_pad_ring (ClutterInputDevice *input_device,
621                  guint64             time_us,
622                  guint32             ring_number,
623                  guint32             ring_source,
624                  guint32             mode_group,
625                  guint32             mode,
626                  gdouble             angle)
627 {
628   ClutterInputDeviceEvdev *device_evdev;
629   ClutterInputDevicePadSource source;
630   ClutterSeatEvdev *seat;
631   ClutterStage *stage;
632   ClutterEvent *event;
633 
634   /* We can drop the event on the floor if no stage has been
635    * associated with the device yet. */
636   stage = _clutter_input_device_get_stage (input_device);
637   if (stage == NULL)
638     return;
639 
640   if (ring_source == LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER)
641     source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER;
642   else
643     source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN;
644 
645   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
646   seat = _clutter_input_device_evdev_get_seat (device_evdev);
647 
648   event = clutter_event_new (CLUTTER_PAD_RING);
649   _clutter_evdev_event_set_time_usec (event, time_us);
650   event->pad_ring.ring_source = source;
651   event->pad_ring.stage = stage;
652   event->pad_ring.ring_number = ring_number;
653   event->pad_ring.angle = angle;
654   event->pad_ring.group = mode_group;
655   event->pad_ring.mode = mode;
656   clutter_event_set_device (event, input_device);
657   clutter_event_set_source_device (event, input_device);
658   clutter_event_set_time (event, us2ms (time_us));
659 
660   _clutter_input_device_set_stage (seat->core_pointer, stage);
661 
662   queue_event (event);
663 }
664 
665 static void
dispatch_libinput(ClutterDeviceManagerEvdev * manager_evdev)666 dispatch_libinput (ClutterDeviceManagerEvdev *manager_evdev)
667 {
668   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
669 
670   libinput_dispatch (priv->libinput);
671   process_events (manager_evdev);
672 }
673 
674 static gboolean
clutter_event_dispatch(GSource * g_source,GSourceFunc callback,gpointer user_data)675 clutter_event_dispatch (GSource     *g_source,
676                         GSourceFunc  callback,
677                         gpointer     user_data)
678 {
679   ClutterEventSource *source = (ClutterEventSource *) g_source;
680   ClutterDeviceManagerEvdev *manager_evdev;
681   ClutterEvent *event;
682 
683   _clutter_threads_acquire_lock ();
684 
685   manager_evdev = source->manager_evdev;
686 
687   /* Don't queue more events if we haven't finished handling the previous batch
688    */
689   if (clutter_events_pending ())
690     goto queue_event;
691 
692   dispatch_libinput (manager_evdev);
693 
694  queue_event:
695   event = clutter_event_get ();
696 
697   if (event)
698     {
699       ClutterModifierType event_state;
700       ClutterInputDevice *input_device =
701         clutter_event_get_source_device (event);
702       ClutterInputDeviceEvdev *device_evdev =
703         CLUTTER_INPUT_DEVICE_EVDEV (input_device);
704       ClutterSeatEvdev *seat =
705         _clutter_input_device_evdev_get_seat (device_evdev);
706 
707       /* Drop events if we don't have any stage to forward them to */
708       if (!_clutter_input_device_get_stage (input_device))
709         goto out;
710 
711       /* forward the event into clutter for emission etc. */
712       _clutter_stage_queue_event (event->any.stage, event, FALSE);
713 
714       /* update the device states *after* the event */
715       event_state = seat->button_state |
716         xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_EFFECTIVE);
717       _clutter_input_device_set_state (seat->core_pointer, event_state);
718       _clutter_input_device_set_state (seat->core_keyboard, event_state);
719     }
720 
721 out:
722   _clutter_threads_release_lock ();
723 
724   return TRUE;
725 }
726 static GSourceFuncs event_funcs = {
727   clutter_event_prepare,
728   clutter_event_check,
729   clutter_event_dispatch,
730   NULL
731 };
732 
733 static ClutterEventSource *
clutter_event_source_new(ClutterDeviceManagerEvdev * manager_evdev)734 clutter_event_source_new (ClutterDeviceManagerEvdev *manager_evdev)
735 {
736   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
737   GSource *source;
738   ClutterEventSource *event_source;
739   gint fd;
740 
741   source = g_source_new (&event_funcs, sizeof (ClutterEventSource));
742   event_source = (ClutterEventSource *) source;
743 
744   /* setup the source */
745   event_source->manager_evdev = manager_evdev;
746 
747   fd = libinput_get_fd (priv->libinput);
748   event_source->event_poll_fd.fd = fd;
749   event_source->event_poll_fd.events = G_IO_IN;
750 
751   /* and finally configure and attach the GSource */
752   g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
753   g_source_add_poll (source, &event_source->event_poll_fd);
754   g_source_set_can_recurse (source, TRUE);
755   g_source_attach (source, NULL);
756 
757   return event_source;
758 }
759 
760 static void
clutter_event_source_free(ClutterEventSource * source)761 clutter_event_source_free (ClutterEventSource *source)
762 {
763   GSource *g_source = (GSource *) source;
764 
765   CLUTTER_NOTE (EVENT, "Removing GSource for evdev device manager");
766 
767   /* ignore the return value of close, it's not like we can do something
768    * about it */
769   close (source->event_poll_fd.fd);
770 
771   g_source_destroy (g_source);
772   g_source_unref (g_source);
773 }
774 
775 static void
evdev_add_device(ClutterDeviceManagerEvdev * manager_evdev,struct libinput_device * libinput_device)776 evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev,
777                   struct libinput_device    *libinput_device)
778 {
779   ClutterDeviceManager *manager = (ClutterDeviceManager *) manager_evdev;
780   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
781   ClutterInputDeviceType type;
782   struct libinput_seat *libinput_seat;
783   ClutterSeatEvdev *seat;
784   ClutterInputDevice *device;
785 
786   libinput_seat = libinput_device_get_seat (libinput_device);
787   seat = libinput_seat_get_user_data (libinput_seat);
788   if (seat == NULL)
789     {
790       /* Clutter has the notion of global "core" pointers and keyboard devices,
791        * which are located on the main seat. Make whatever seat comes first the
792        * main seat. */
793       if (priv->main_seat->libinput_seat == NULL)
794         seat = priv->main_seat;
795       else
796         {
797           seat = clutter_seat_evdev_new (manager_evdev);
798           priv->seats = g_slist_append (priv->seats, seat);
799         }
800 
801       clutter_seat_evdev_set_libinput_seat (seat, libinput_seat);
802     }
803 
804   device = _clutter_input_device_evdev_new (manager, seat, libinput_device);
805   _clutter_input_device_set_stage (device, manager_evdev->priv->stage);
806 
807   _clutter_device_manager_add_device (manager, device);
808 
809   /* Clutter assumes that device types are exclusive in the
810    * ClutterInputDevice API */
811   type = _clutter_input_device_evdev_determine_type (libinput_device);
812 
813   if (type == CLUTTER_KEYBOARD_DEVICE)
814     {
815       _clutter_input_device_set_associated_device (device, seat->core_keyboard);
816       _clutter_input_device_add_slave (seat->core_keyboard, device);
817     }
818   else if (type == CLUTTER_POINTER_DEVICE)
819     {
820       _clutter_input_device_set_associated_device (device, seat->core_pointer);
821       _clutter_input_device_add_slave (seat->core_pointer, device);
822     }
823 
824   CLUTTER_NOTE (EVENT, "Added physical device '%s', type %s",
825                 clutter_input_device_get_device_name (device),
826                 device_type_str[type]);
827 }
828 
829 static void
evdev_remove_device(ClutterDeviceManagerEvdev * manager_evdev,ClutterInputDeviceEvdev * device_evdev)830 evdev_remove_device (ClutterDeviceManagerEvdev *manager_evdev,
831                      ClutterInputDeviceEvdev   *device_evdev)
832 {
833   ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (manager_evdev);
834   ClutterInputDevice *input_device = CLUTTER_INPUT_DEVICE (device_evdev);
835 
836   _clutter_device_manager_remove_device (manager, input_device);
837 }
838 
839 /*
840  * ClutterDeviceManager implementation
841  */
842 
843 static void
clutter_device_manager_evdev_add_device(ClutterDeviceManager * manager,ClutterInputDevice * device)844 clutter_device_manager_evdev_add_device (ClutterDeviceManager *manager,
845                                          ClutterInputDevice   *device)
846 {
847   ClutterDeviceManagerEvdev *manager_evdev;
848   ClutterDeviceManagerEvdevPrivate *priv;
849   ClutterInputDeviceEvdev *device_evdev;
850   ClutterSeatEvdev *seat;
851 
852   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
853   priv = manager_evdev->priv;
854   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
855   seat = _clutter_input_device_evdev_get_seat (device_evdev);
856 
857   seat->devices = g_slist_prepend (seat->devices, device);
858   priv->devices = g_slist_prepend (priv->devices, device);
859 }
860 
861 static void
clutter_device_manager_evdev_remove_device(ClutterDeviceManager * manager,ClutterInputDevice * device)862 clutter_device_manager_evdev_remove_device (ClutterDeviceManager *manager,
863                                             ClutterInputDevice   *device)
864 {
865   ClutterDeviceManagerEvdev *manager_evdev;
866   ClutterDeviceManagerEvdevPrivate *priv;
867   ClutterInputDeviceEvdev *device_evdev;
868   ClutterSeatEvdev *seat;
869 
870   device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
871   seat = _clutter_input_device_evdev_get_seat (device_evdev);
872   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
873   priv = manager_evdev->priv;
874 
875   /* Remove the device */
876   seat->devices = g_slist_remove (seat->devices, device);
877   priv->devices = g_slist_remove (priv->devices, device);
878 
879   if (seat->repeat_timer && seat->repeat_device == device)
880     clutter_seat_evdev_clear_repeat_timer (seat);
881 
882   g_object_unref (device);
883 }
884 
885 static const GSList *
clutter_device_manager_evdev_get_devices(ClutterDeviceManager * manager)886 clutter_device_manager_evdev_get_devices (ClutterDeviceManager *manager)
887 {
888   return CLUTTER_DEVICE_MANAGER_EVDEV (manager)->priv->devices;
889 }
890 
891 static ClutterInputDevice *
clutter_device_manager_evdev_get_core_device(ClutterDeviceManager * manager,ClutterInputDeviceType type)892 clutter_device_manager_evdev_get_core_device (ClutterDeviceManager   *manager,
893                                               ClutterInputDeviceType  type)
894 {
895   ClutterDeviceManagerEvdev *manager_evdev;
896   ClutterDeviceManagerEvdevPrivate *priv;
897 
898   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
899   priv = manager_evdev->priv;
900 
901   switch (type)
902     {
903     case CLUTTER_POINTER_DEVICE:
904       return priv->main_seat->core_pointer;
905 
906     case CLUTTER_KEYBOARD_DEVICE:
907       return priv->main_seat->core_keyboard;
908 
909     case CLUTTER_EXTENSION_DEVICE:
910     default:
911       return NULL;
912     }
913 
914   return NULL;
915 }
916 
917 static ClutterInputDevice *
clutter_device_manager_evdev_get_device(ClutterDeviceManager * manager,gint id)918 clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
919                                          gint                  id)
920 {
921   ClutterDeviceManagerEvdev *manager_evdev;
922   ClutterDeviceManagerEvdevPrivate *priv;
923   GSList *l;
924 
925   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
926   priv = manager_evdev->priv;
927 
928   for (l = priv->seats; l; l = l->next)
929     {
930       ClutterSeatEvdev *seat = l->data;
931       ClutterInputDevice *device = clutter_seat_evdev_get_device (seat, id);
932 
933       if (device)
934         return device;
935     }
936 
937   return NULL;
938 }
939 
940 static void
flush_event_queue(void)941 flush_event_queue (void)
942 {
943   ClutterEvent *event;
944 
945   while ((event = clutter_event_get ()) != NULL)
946     {
947       _clutter_process_event (event);
948       clutter_event_free (event);
949     }
950 }
951 
952 static gboolean
process_base_event(ClutterDeviceManagerEvdev * manager_evdev,struct libinput_event * event)953 process_base_event (ClutterDeviceManagerEvdev *manager_evdev,
954                     struct libinput_event *event)
955 {
956   ClutterInputDevice *device;
957   struct libinput_device *libinput_device;
958   gboolean handled = TRUE;
959 
960   switch (libinput_event_get_type (event))
961     {
962     case LIBINPUT_EVENT_DEVICE_ADDED:
963       libinput_device = libinput_event_get_device (event);
964 
965       evdev_add_device (manager_evdev, libinput_device);
966       break;
967 
968     case LIBINPUT_EVENT_DEVICE_REMOVED:
969       /* Flush all queued events, there
970        * might be some from this device.
971        */
972       flush_event_queue ();
973 
974       libinput_device = libinput_event_get_device (event);
975 
976       device = libinput_device_get_user_data (libinput_device);
977       evdev_remove_device (manager_evdev,
978                            CLUTTER_INPUT_DEVICE_EVDEV (device));
979       break;
980 
981     default:
982       handled = FALSE;
983     }
984 
985   return handled;
986 }
987 
988 static ClutterScrollSource
translate_scroll_source(enum libinput_pointer_axis_source source)989 translate_scroll_source (enum libinput_pointer_axis_source source)
990 {
991   switch (source)
992     {
993     case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
994       return CLUTTER_SCROLL_SOURCE_WHEEL;
995     case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
996       return CLUTTER_SCROLL_SOURCE_FINGER;
997     case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
998       return CLUTTER_SCROLL_SOURCE_CONTINUOUS;
999     default:
1000       return CLUTTER_SCROLL_SOURCE_UNKNOWN;
1001     }
1002 }
1003 
1004 static ClutterInputDeviceToolType
translate_tool_type(struct libinput_tablet_tool * libinput_tool)1005 translate_tool_type (struct libinput_tablet_tool *libinput_tool)
1006 {
1007   enum libinput_tablet_tool_type tool;
1008 
1009   tool = libinput_tablet_tool_get_type (libinput_tool);
1010 
1011   switch (tool)
1012     {
1013     case LIBINPUT_TABLET_TOOL_TYPE_PEN:
1014       return CLUTTER_INPUT_DEVICE_TOOL_PEN;
1015     case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
1016       return CLUTTER_INPUT_DEVICE_TOOL_ERASER;
1017     case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
1018       return CLUTTER_INPUT_DEVICE_TOOL_BRUSH;
1019     case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
1020       return CLUTTER_INPUT_DEVICE_TOOL_PENCIL;
1021     case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
1022       return CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH;
1023     case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
1024       return CLUTTER_INPUT_DEVICE_TOOL_MOUSE;
1025     case LIBINPUT_TABLET_TOOL_TYPE_LENS:
1026       return CLUTTER_INPUT_DEVICE_TOOL_LENS;
1027     default:
1028       return CLUTTER_INPUT_DEVICE_TOOL_NONE;
1029     }
1030 }
1031 
1032 static void
input_device_update_tool(ClutterInputDevice * input_device,struct libinput_tablet_tool * libinput_tool)1033 input_device_update_tool (ClutterInputDevice          *input_device,
1034                           struct libinput_tablet_tool *libinput_tool)
1035 {
1036   ClutterInputDeviceEvdev *evdev_device = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
1037   ClutterInputDeviceTool *tool = NULL;
1038   ClutterInputDeviceToolType tool_type;
1039   guint64 tool_serial;
1040 
1041   if (libinput_tool)
1042     {
1043       tool_serial = libinput_tablet_tool_get_serial (libinput_tool);
1044       tool_type = translate_tool_type (libinput_tool);
1045       tool = clutter_input_device_lookup_tool (input_device,
1046                                                tool_serial, tool_type);
1047 
1048       if (!tool)
1049         {
1050           tool = clutter_input_device_tool_evdev_new (libinput_tool,
1051                                                       tool_serial, tool_type);
1052           clutter_input_device_add_tool (input_device, tool);
1053         }
1054     }
1055 
1056   if (evdev_device->last_tool != tool)
1057     {
1058       evdev_device->last_tool = tool;
1059       g_signal_emit_by_name (clutter_device_manager_get_default (),
1060                              "tool-changed", input_device, tool);
1061     }
1062 }
1063 
1064 static gdouble *
translate_tablet_axes(struct libinput_event_tablet_tool * tablet_event,ClutterInputDeviceTool * tool)1065 translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event,
1066                        ClutterInputDeviceTool            *tool)
1067 {
1068   GArray *axes = g_array_new (FALSE, FALSE, sizeof (gdouble));
1069   struct libinput_tablet_tool *libinput_tool;
1070   gdouble value;
1071 
1072   libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event);
1073 
1074   value = libinput_event_tablet_tool_get_x (tablet_event);
1075   g_array_append_val (axes, value);
1076   value = libinput_event_tablet_tool_get_y (tablet_event);
1077   g_array_append_val (axes, value);
1078 
1079   if (libinput_tablet_tool_has_distance (libinput_tool))
1080     {
1081       value = libinput_event_tablet_tool_get_distance (tablet_event);
1082       g_array_append_val (axes, value);
1083     }
1084 
1085   if (libinput_tablet_tool_has_pressure (libinput_tool))
1086     {
1087       value = libinput_event_tablet_tool_get_pressure (tablet_event);
1088       value = clutter_input_device_tool_evdev_translate_pressure (tool, value);
1089       g_array_append_val (axes, value);
1090     }
1091 
1092   if (libinput_tablet_tool_has_tilt (libinput_tool))
1093     {
1094       value = libinput_event_tablet_tool_get_tilt_x (tablet_event);
1095       g_array_append_val (axes, value);
1096       value = libinput_event_tablet_tool_get_tilt_y (tablet_event);
1097       g_array_append_val (axes, value);
1098     }
1099 
1100   if (libinput_tablet_tool_has_rotation (libinput_tool))
1101     {
1102       value = libinput_event_tablet_tool_get_rotation (tablet_event);
1103       g_array_append_val (axes, value);
1104     }
1105 
1106   if (libinput_tablet_tool_has_slider (libinput_tool))
1107     {
1108       value = libinput_event_tablet_tool_get_slider_position (tablet_event);
1109       g_array_append_val (axes, value);
1110     }
1111 
1112   if (libinput_tablet_tool_has_wheel (libinput_tool))
1113     {
1114       value = libinput_event_tablet_tool_get_wheel_delta (tablet_event);
1115       g_array_append_val (axes, value);
1116     }
1117 
1118   if (axes->len == 0)
1119     {
1120       g_array_free (axes, TRUE);
1121       return NULL;
1122     }
1123   else
1124     return (gdouble *) g_array_free (axes, FALSE);
1125 }
1126 
1127 static ClutterSeatEvdev *
seat_from_device(ClutterInputDevice * device)1128 seat_from_device (ClutterInputDevice *device)
1129 {
1130   ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
1131 
1132   return _clutter_input_device_evdev_get_seat (device_evdev);
1133 }
1134 
1135 static void
notify_continuous_axis(ClutterSeatEvdev * seat,ClutterInputDevice * device,uint64_t time_us,ClutterScrollSource scroll_source,struct libinput_event_pointer * axis_event)1136 notify_continuous_axis (ClutterSeatEvdev              *seat,
1137                         ClutterInputDevice            *device,
1138                         uint64_t                       time_us,
1139                         ClutterScrollSource            scroll_source,
1140                         struct libinput_event_pointer *axis_event)
1141 {
1142   gdouble dx = 0.0, dy = 0.0;
1143   ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE;
1144 
1145   if (libinput_event_pointer_has_axis (axis_event,
1146                                        LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
1147     {
1148       dx = libinput_event_pointer_get_axis_value (
1149           axis_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
1150 
1151       if (fabs (dx) < DBL_EPSILON)
1152         finish_flags |= CLUTTER_SCROLL_FINISHED_HORIZONTAL;
1153     }
1154   if (libinput_event_pointer_has_axis (axis_event,
1155                                        LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
1156     {
1157       dy = libinput_event_pointer_get_axis_value (
1158           axis_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
1159 
1160       if (fabs (dy) < DBL_EPSILON)
1161         finish_flags |= CLUTTER_SCROLL_FINISHED_VERTICAL;
1162     }
1163 
1164   clutter_seat_evdev_notify_scroll_continuous (seat, device, time_us,
1165                                                dx, dy,
1166                                                scroll_source, finish_flags);
1167 }
1168 
1169 static void
notify_discrete_axis(ClutterSeatEvdev * seat,ClutterInputDevice * device,uint64_t time_us,ClutterScrollSource scroll_source,struct libinput_event_pointer * axis_event)1170 notify_discrete_axis (ClutterSeatEvdev              *seat,
1171                       ClutterInputDevice            *device,
1172                       uint64_t                       time_us,
1173                       ClutterScrollSource            scroll_source,
1174                       struct libinput_event_pointer *axis_event)
1175 {
1176   gdouble discrete_dx = 0.0, discrete_dy = 0.0;
1177 
1178   if (libinput_event_pointer_has_axis (axis_event,
1179                                        LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
1180     {
1181       discrete_dx = libinput_event_pointer_get_axis_value_discrete (
1182           axis_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
1183     }
1184   if (libinput_event_pointer_has_axis (axis_event,
1185                                        LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
1186     {
1187       discrete_dy = libinput_event_pointer_get_axis_value_discrete (
1188           axis_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
1189     }
1190 
1191   clutter_seat_evdev_notify_discrete_scroll (seat, device,
1192                                              time_us,
1193                                              discrete_dx, discrete_dy,
1194                                              scroll_source);
1195 }
1196 
1197 static gboolean
process_device_event(ClutterDeviceManagerEvdev * manager_evdev,struct libinput_event * event)1198 process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
1199                       struct libinput_event *event)
1200 {
1201   gboolean handled = TRUE;
1202   struct libinput_device *libinput_device = libinput_event_get_device(event);
1203   ClutterInputDevice *device;
1204   ClutterInputDeviceEvdev *device_evdev;
1205 
1206   switch (libinput_event_get_type (event))
1207     {
1208     case LIBINPUT_EVENT_KEYBOARD_KEY:
1209       {
1210         guint32 key, key_state, seat_key_count;
1211         guint64 time_us;
1212         struct libinput_event_keyboard *key_event =
1213           libinput_event_get_keyboard_event (event);
1214 
1215         device = libinput_device_get_user_data (libinput_device);
1216         time_us = libinput_event_keyboard_get_time_usec (key_event);
1217         key = libinput_event_keyboard_get_key (key_event);
1218         key_state = libinput_event_keyboard_get_key_state (key_event) ==
1219                     LIBINPUT_KEY_STATE_PRESSED;
1220         seat_key_count =
1221           libinput_event_keyboard_get_seat_key_count (key_event);
1222 
1223 	/* Ignore key events that are not seat wide state changes. */
1224 	if ((key_state == LIBINPUT_KEY_STATE_PRESSED &&
1225 	     seat_key_count != 1) ||
1226 	    (key_state == LIBINPUT_KEY_STATE_RELEASED &&
1227 	     seat_key_count != 0))
1228           break;
1229 
1230         clutter_seat_evdev_notify_key (seat_from_device (device),
1231                                        device,
1232                                        time_us, key, key_state, TRUE);
1233 
1234         break;
1235       }
1236 
1237     case LIBINPUT_EVENT_POINTER_MOTION:
1238       {
1239         struct libinput_event_pointer *pointer_event =
1240           libinput_event_get_pointer_event (event);
1241         uint64_t time_us;
1242         double dx;
1243         double dy;
1244         double dx_unaccel;
1245         double dy_unaccel;
1246 
1247         device = libinput_device_get_user_data (libinput_device);
1248         time_us = libinput_event_pointer_get_time_usec (pointer_event);
1249         dx = libinput_event_pointer_get_dx (pointer_event);
1250         dy = libinput_event_pointer_get_dy (pointer_event);
1251         dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event);
1252         dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event);
1253 
1254         clutter_seat_evdev_notify_relative_motion (seat_from_device (device),
1255                                                    device,
1256                                                    time_us,
1257                                                    dx, dy,
1258                                                    dx_unaccel, dy_unaccel);
1259 
1260         break;
1261       }
1262 
1263     case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
1264       {
1265         guint64 time_us;
1266         double x, y;
1267         gfloat stage_width, stage_height;
1268         ClutterStage *stage;
1269         struct libinput_event_pointer *motion_event =
1270           libinput_event_get_pointer_event (event);
1271         device = libinput_device_get_user_data (libinput_device);
1272 
1273         stage = _clutter_input_device_get_stage (device);
1274         if (stage == NULL)
1275           break;
1276 
1277         stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
1278         stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
1279 
1280         time_us = libinput_event_pointer_get_time_usec (motion_event);
1281         x = libinput_event_pointer_get_absolute_x_transformed (motion_event,
1282                                                                stage_width);
1283         y = libinput_event_pointer_get_absolute_y_transformed (motion_event,
1284                                                                stage_height);
1285 
1286         clutter_seat_evdev_notify_absolute_motion (seat_from_device (device),
1287                                                    device,
1288                                                    time_us,
1289                                                    x, y,
1290                                                    NULL);
1291 
1292         break;
1293       }
1294 
1295     case LIBINPUT_EVENT_POINTER_BUTTON:
1296       {
1297         guint32 button, button_state, seat_button_count;
1298         guint64 time_us;
1299         struct libinput_event_pointer *button_event =
1300           libinput_event_get_pointer_event (event);
1301         device = libinput_device_get_user_data (libinput_device);
1302 
1303         time_us = libinput_event_pointer_get_time_usec (button_event);
1304         button = libinput_event_pointer_get_button (button_event);
1305         button_state = libinput_event_pointer_get_button_state (button_event) ==
1306                        LIBINPUT_BUTTON_STATE_PRESSED;
1307         seat_button_count =
1308           libinput_event_pointer_get_seat_button_count (button_event);
1309 
1310         /* Ignore button events that are not seat wide state changes. */
1311         if ((button_state == LIBINPUT_BUTTON_STATE_PRESSED &&
1312              seat_button_count != 1) ||
1313             (button_state == LIBINPUT_BUTTON_STATE_RELEASED &&
1314              seat_button_count != 0))
1315           break;
1316 
1317         clutter_seat_evdev_notify_button (seat_from_device (device), device,
1318                                           time_us, button, button_state);
1319         break;
1320       }
1321 
1322     case LIBINPUT_EVENT_POINTER_AXIS:
1323       {
1324         guint64 time_us;
1325         enum libinput_pointer_axis_source source;
1326         struct libinput_event_pointer *axis_event =
1327           libinput_event_get_pointer_event (event);
1328         ClutterSeatEvdev *seat;
1329         ClutterScrollSource scroll_source;
1330 
1331         device = libinput_device_get_user_data (libinput_device);
1332         seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device));
1333 
1334         time_us = libinput_event_pointer_get_time_usec (axis_event);
1335         source = libinput_event_pointer_get_axis_source (axis_event);
1336         scroll_source = translate_scroll_source (source);
1337 
1338         /* libinput < 0.8 sent wheel click events with value 10. Since 0.8
1339            the value is the angle of the click in degrees. To keep
1340            backwards-compat with existing clients, we just send multiples of
1341            the click count. */
1342 
1343         switch (scroll_source)
1344           {
1345           case CLUTTER_SCROLL_SOURCE_WHEEL:
1346             notify_discrete_axis (seat, device, time_us, scroll_source,
1347                                   axis_event);
1348             break;
1349           case CLUTTER_SCROLL_SOURCE_FINGER:
1350           case CLUTTER_SCROLL_SOURCE_CONTINUOUS:
1351           case CLUTTER_SCROLL_SOURCE_UNKNOWN:
1352             notify_continuous_axis (seat, device, time_us, scroll_source,
1353                                     axis_event);
1354             break;
1355           }
1356         break;
1357       }
1358 
1359     case LIBINPUT_EVENT_TOUCH_DOWN:
1360       {
1361         int device_slot;
1362         guint64 time_us;
1363         double x, y;
1364         gfloat stage_width, stage_height;
1365         ClutterSeatEvdev *seat;
1366         ClutterStage *stage;
1367         ClutterTouchState *touch_state;
1368         struct libinput_event_touch *touch_event =
1369           libinput_event_get_touch_event (event);
1370 
1371         device = libinput_device_get_user_data (libinput_device);
1372         device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
1373         seat = _clutter_input_device_evdev_get_seat (device_evdev);
1374 
1375         stage = _clutter_input_device_get_stage (device);
1376         if (stage == NULL)
1377           break;
1378 
1379         stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
1380         stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
1381 
1382         device_slot = libinput_event_touch_get_slot (touch_event);
1383         time_us = libinput_event_touch_get_time_usec (touch_event);
1384         x = libinput_event_touch_get_x_transformed (touch_event,
1385                                                     stage_width);
1386         y = libinput_event_touch_get_y_transformed (touch_event,
1387                                                     stage_height);
1388 
1389         touch_state =
1390           clutter_input_device_evdev_acquire_touch_state (device_evdev,
1391                                                           device_slot);
1392         touch_state->coords.x = x;
1393         touch_state->coords.y = y;
1394 
1395         clutter_seat_evdev_notify_touch_event (seat, device,
1396                                                CLUTTER_TOUCH_BEGIN,
1397                                                time_us,
1398                                                touch_state->seat_slot,
1399                                                touch_state->coords.x,
1400                                                touch_state->coords.y);
1401         break;
1402       }
1403 
1404     case LIBINPUT_EVENT_TOUCH_UP:
1405       {
1406         int device_slot;
1407         guint64 time_us;
1408         ClutterSeatEvdev *seat;
1409         ClutterTouchState *touch_state;
1410         struct libinput_event_touch *touch_event =
1411           libinput_event_get_touch_event (event);
1412 
1413         device = libinput_device_get_user_data (libinput_device);
1414         device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
1415         seat = _clutter_input_device_evdev_get_seat (device_evdev);
1416 
1417         device_slot = libinput_event_touch_get_slot (touch_event);
1418         time_us = libinput_event_touch_get_time_usec (touch_event);
1419         touch_state =
1420           clutter_input_device_evdev_lookup_touch_state (device_evdev,
1421                                                          device_slot);
1422         if (!touch_state)
1423           break;
1424 
1425         clutter_seat_evdev_notify_touch_event (seat, device,
1426                                                CLUTTER_TOUCH_END, time_us,
1427                                                touch_state->seat_slot,
1428                                                touch_state->coords.x,
1429                                                touch_state->coords.y);
1430         clutter_input_device_evdev_release_touch_state (device_evdev,
1431                                                         touch_state);
1432         break;
1433       }
1434 
1435     case LIBINPUT_EVENT_TOUCH_MOTION:
1436       {
1437         int device_slot;
1438         guint64 time_us;
1439         double x, y;
1440         gfloat stage_width, stage_height;
1441         ClutterSeatEvdev *seat;
1442         ClutterStage *stage;
1443         ClutterTouchState *touch_state;
1444         struct libinput_event_touch *touch_event =
1445           libinput_event_get_touch_event (event);
1446 
1447         device = libinput_device_get_user_data (libinput_device);
1448         device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
1449         seat = _clutter_input_device_evdev_get_seat (device_evdev);
1450 
1451         stage = _clutter_input_device_get_stage (device);
1452         if (stage == NULL)
1453           break;
1454 
1455         stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
1456         stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
1457 
1458         device_slot = libinput_event_touch_get_slot (touch_event);
1459         time_us = libinput_event_touch_get_time_usec (touch_event);
1460         x = libinput_event_touch_get_x_transformed (touch_event,
1461                                                     stage_width);
1462         y = libinput_event_touch_get_y_transformed (touch_event,
1463                                                     stage_height);
1464 
1465         touch_state =
1466           clutter_input_device_evdev_lookup_touch_state (device_evdev,
1467                                                          device_slot);
1468         if (!touch_state)
1469           break;
1470 
1471         touch_state->coords.x = x;
1472         touch_state->coords.y = y;
1473 
1474         clutter_seat_evdev_notify_touch_event (seat, device,
1475                                                CLUTTER_TOUCH_UPDATE,
1476                                                time_us,
1477                                                touch_state->seat_slot,
1478                                                touch_state->coords.x,
1479                                                touch_state->coords.y);
1480         break;
1481       }
1482     case LIBINPUT_EVENT_TOUCH_CANCEL:
1483       {
1484         guint64 time_us;
1485         struct libinput_event_touch *touch_event =
1486           libinput_event_get_touch_event (event);
1487 
1488         device = libinput_device_get_user_data (libinput_device);
1489         device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
1490         time_us = libinput_event_touch_get_time_usec (touch_event);
1491 
1492         clutter_input_device_evdev_release_touch_slots (device_evdev, time_us);
1493 
1494         break;
1495       }
1496     case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
1497     case LIBINPUT_EVENT_GESTURE_PINCH_END:
1498       {
1499         struct libinput_event_gesture *gesture_event =
1500           libinput_event_get_gesture_event (event);
1501         ClutterTouchpadGesturePhase phase;
1502         guint n_fingers;
1503         guint64 time_us;
1504 
1505         if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_PINCH_BEGIN)
1506           phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN;
1507         else
1508           phase = libinput_event_gesture_get_cancelled (gesture_event) ?
1509             CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END;
1510 
1511         n_fingers = libinput_event_gesture_get_finger_count (gesture_event);
1512         device = libinput_device_get_user_data (libinput_device);
1513         time_us = libinput_event_gesture_get_time_usec (gesture_event);
1514         notify_pinch_gesture_event (device, phase, time_us, 0, 0, 0, 0, n_fingers);
1515         break;
1516       }
1517     case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
1518       {
1519         struct libinput_event_gesture *gesture_event =
1520           libinput_event_get_gesture_event (event);
1521         gdouble angle_delta, scale, dx, dy;
1522         guint n_fingers;
1523         guint64 time_us;
1524 
1525         n_fingers = libinput_event_gesture_get_finger_count (gesture_event);
1526         device = libinput_device_get_user_data (libinput_device);
1527         time_us = libinput_event_gesture_get_time_usec (gesture_event);
1528         angle_delta = libinput_event_gesture_get_angle_delta (gesture_event);
1529         scale = libinput_event_gesture_get_scale (gesture_event);
1530         dx = libinput_event_gesture_get_dx (gesture_event);
1531         dy = libinput_event_gesture_get_dx (gesture_event);
1532 
1533         notify_pinch_gesture_event (device,
1534                                     CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE,
1535                                     time_us, dx, dy, angle_delta, scale, n_fingers);
1536         break;
1537       }
1538     case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
1539     case LIBINPUT_EVENT_GESTURE_SWIPE_END:
1540       {
1541         struct libinput_event_gesture *gesture_event =
1542           libinput_event_get_gesture_event (event);
1543         ClutterTouchpadGesturePhase phase;
1544         guint32 n_fingers;
1545         guint64 time_us;
1546 
1547         device = libinput_device_get_user_data (libinput_device);
1548         time_us = libinput_event_gesture_get_time_usec (gesture_event);
1549         n_fingers = libinput_event_gesture_get_finger_count (gesture_event);
1550 
1551         if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN)
1552           phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN;
1553         else
1554           phase = libinput_event_gesture_get_cancelled (gesture_event) ?
1555             CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END;
1556 
1557         notify_swipe_gesture_event (device, phase, time_us, n_fingers, 0, 0);
1558         break;
1559       }
1560     case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
1561       {
1562         struct libinput_event_gesture *gesture_event =
1563           libinput_event_get_gesture_event (event);
1564         guint32 n_fingers;
1565         guint64 time_us;
1566         gdouble dx, dy;
1567 
1568         device = libinput_device_get_user_data (libinput_device);
1569         time_us = libinput_event_gesture_get_time_usec (gesture_event);
1570         n_fingers = libinput_event_gesture_get_finger_count (gesture_event);
1571         dx = libinput_event_gesture_get_dx (gesture_event);
1572         dy = libinput_event_gesture_get_dy (gesture_event);
1573 
1574         notify_swipe_gesture_event (device,
1575                                     CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE,
1576                                     time_us, n_fingers, dx, dy);
1577         break;
1578       }
1579     case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
1580       {
1581         guint64 time;
1582         double x, y, dx, dy, *axes;
1583         gfloat stage_width, stage_height;
1584         ClutterStage *stage;
1585         struct libinput_event_tablet_tool *tablet_event =
1586           libinput_event_get_tablet_tool_event (event);
1587         ClutterInputDeviceEvdev *evdev_device;
1588 
1589         device = libinput_device_get_user_data (libinput_device);
1590         evdev_device = CLUTTER_INPUT_DEVICE_EVDEV (device);
1591 
1592         stage = _clutter_input_device_get_stage (device);
1593         if (!stage)
1594           break;
1595 
1596         axes = translate_tablet_axes (tablet_event,
1597                                       evdev_device->last_tool);
1598         if (!axes)
1599           break;
1600 
1601         stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
1602         stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
1603 
1604         time = libinput_event_tablet_tool_get_time_usec (tablet_event);
1605 
1606         if (clutter_input_device_get_mapping_mode (device) == CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE ||
1607             clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_MOUSE ||
1608             clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_LENS)
1609           {
1610             dx = libinput_event_tablet_tool_get_dx (tablet_event);
1611             dy = libinput_event_tablet_tool_get_dy (tablet_event);
1612             notify_relative_tool_motion (device, time, dx, dy, axes);
1613           }
1614         else
1615           {
1616             x = libinput_event_tablet_tool_get_x_transformed (tablet_event, stage_width);
1617             y = libinput_event_tablet_tool_get_y_transformed (tablet_event, stage_height);
1618             notify_absolute_motion (device, time, x, y, axes);
1619           }
1620 
1621         break;
1622       }
1623     case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
1624       {
1625         guint64 time;
1626         struct libinput_event_tablet_tool *tablet_event =
1627           libinput_event_get_tablet_tool_event (event);
1628         struct libinput_tablet_tool *libinput_tool = NULL;
1629         enum libinput_tablet_tool_proximity_state state;
1630 
1631         state = libinput_event_tablet_tool_get_proximity_state (tablet_event);
1632         time = libinput_event_tablet_tool_get_time_usec (tablet_event);
1633         device = libinput_device_get_user_data (libinput_device);
1634 
1635         libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event);
1636 
1637         if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN)
1638           input_device_update_tool (device, libinput_tool);
1639         notify_proximity (device, time, state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
1640         if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT)
1641           input_device_update_tool (device, NULL);
1642         break;
1643       }
1644     case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
1645       {
1646         guint64 time_us;
1647         guint32 button_state;
1648         struct libinput_event_tablet_tool *tablet_event =
1649           libinput_event_get_tablet_tool_event (event);
1650         guint tablet_button;
1651 
1652         device = libinput_device_get_user_data (libinput_device);
1653         time_us = libinput_event_tablet_tool_get_time_usec (tablet_event);
1654         tablet_button = libinput_event_tablet_tool_get_button (tablet_event);
1655 
1656         button_state = libinput_event_tablet_tool_get_button_state (tablet_event) ==
1657                        LIBINPUT_BUTTON_STATE_PRESSED;
1658 
1659         clutter_seat_evdev_notify_button (seat_from_device (device), device,
1660                                           time_us, tablet_button, button_state);
1661         break;
1662       }
1663     case LIBINPUT_EVENT_TABLET_TOOL_TIP:
1664       {
1665         guint64 time_us;
1666         guint32 button_state;
1667         struct libinput_event_tablet_tool *tablet_event =
1668           libinput_event_get_tablet_tool_event (event);
1669 
1670         device = libinput_device_get_user_data (libinput_device);
1671         time_us = libinput_event_tablet_tool_get_time_usec (tablet_event);
1672 
1673         button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) ==
1674                        LIBINPUT_TABLET_TOOL_TIP_DOWN;
1675 
1676         clutter_seat_evdev_notify_button (seat_from_device (device), device,
1677                                           time_us, BTN_TOUCH, button_state);
1678         break;
1679       }
1680     case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
1681       {
1682         guint64 time;
1683         guint32 button_state, button, group, mode;
1684         struct libinput_tablet_pad_mode_group *mode_group;
1685         struct libinput_event_tablet_pad *pad_event =
1686           libinput_event_get_tablet_pad_event (event);
1687 
1688         device = libinput_device_get_user_data (libinput_device);
1689         time = libinput_event_tablet_pad_get_time_usec (pad_event);
1690 
1691         mode_group = libinput_event_tablet_pad_get_mode_group (pad_event);
1692         group = libinput_tablet_pad_mode_group_get_index (mode_group);
1693         mode = libinput_event_tablet_pad_get_mode (pad_event);
1694 
1695         button = libinput_event_tablet_pad_get_button_number (pad_event);
1696         button_state = libinput_event_tablet_pad_get_button_state (pad_event) ==
1697                        LIBINPUT_BUTTON_STATE_PRESSED;
1698         notify_pad_button (device, time, button, group, mode, button_state);
1699         break;
1700       }
1701     case LIBINPUT_EVENT_TABLET_PAD_STRIP:
1702       {
1703         guint64 time;
1704         guint32 number, source, group, mode;
1705         struct libinput_tablet_pad_mode_group *mode_group;
1706         struct libinput_event_tablet_pad *pad_event =
1707           libinput_event_get_tablet_pad_event (event);
1708         gdouble value;
1709 
1710         device = libinput_device_get_user_data (libinput_device);
1711         time = libinput_event_tablet_pad_get_time_usec (pad_event);
1712         number = libinput_event_tablet_pad_get_strip_number (pad_event);
1713         value = libinput_event_tablet_pad_get_strip_position (pad_event);
1714         source = libinput_event_tablet_pad_get_strip_source (pad_event);
1715 
1716         mode_group = libinput_event_tablet_pad_get_mode_group (pad_event);
1717         group = libinput_tablet_pad_mode_group_get_index (mode_group);
1718         mode = libinput_event_tablet_pad_get_mode (pad_event);
1719 
1720         notify_pad_strip (device, time, number, source, group, mode, value);
1721         break;
1722       }
1723     case LIBINPUT_EVENT_TABLET_PAD_RING:
1724       {
1725         guint64 time;
1726         guint32 number, source, group, mode;
1727         struct libinput_tablet_pad_mode_group *mode_group;
1728         struct libinput_event_tablet_pad *pad_event =
1729           libinput_event_get_tablet_pad_event (event);
1730         gdouble angle;
1731 
1732         device = libinput_device_get_user_data (libinput_device);
1733         time = libinput_event_tablet_pad_get_time_usec (pad_event);
1734         number = libinput_event_tablet_pad_get_ring_number (pad_event);
1735         angle = libinput_event_tablet_pad_get_ring_position (pad_event);
1736         source = libinput_event_tablet_pad_get_ring_source (pad_event);
1737 
1738         mode_group = libinput_event_tablet_pad_get_mode_group (pad_event);
1739         group = libinput_tablet_pad_mode_group_get_index (mode_group);
1740         mode = libinput_event_tablet_pad_get_mode (pad_event);
1741 
1742         notify_pad_ring (device, time, number, source, group, mode, angle);
1743         break;
1744       }
1745     default:
1746       handled = FALSE;
1747     }
1748 
1749   return handled;
1750 }
1751 
1752 static gboolean
filter_event(ClutterDeviceManagerEvdev * manager_evdev,struct libinput_event * event)1753 filter_event (ClutterDeviceManagerEvdev *manager_evdev,
1754               struct libinput_event     *event)
1755 {
1756   gboolean retval = CLUTTER_EVENT_PROPAGATE;
1757   ClutterEventFilter *filter;
1758   GSList *tmp_list;
1759 
1760   tmp_list = manager_evdev->priv->event_filters;
1761 
1762   while (tmp_list)
1763     {
1764       filter = tmp_list->data;
1765       retval = filter->func (event, filter->data);
1766       tmp_list = tmp_list->next;
1767 
1768       if (retval != CLUTTER_EVENT_PROPAGATE)
1769         break;
1770     }
1771 
1772   return retval;
1773 }
1774 
1775 static void
process_event(ClutterDeviceManagerEvdev * manager_evdev,struct libinput_event * event)1776 process_event (ClutterDeviceManagerEvdev *manager_evdev,
1777                struct libinput_event *event)
1778 {
1779   gboolean retval;
1780 
1781   retval = filter_event (manager_evdev, event);
1782 
1783   if (retval != CLUTTER_EVENT_PROPAGATE)
1784     return;
1785 
1786   if (process_base_event (manager_evdev, event))
1787     return;
1788   if (process_device_event (manager_evdev, event))
1789     return;
1790 }
1791 
1792 static void
process_events(ClutterDeviceManagerEvdev * manager_evdev)1793 process_events (ClutterDeviceManagerEvdev *manager_evdev)
1794 {
1795   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
1796   struct libinput_event *event;
1797 
1798   while ((event = libinput_get_event (priv->libinput)))
1799     {
1800       process_event(manager_evdev, event);
1801       libinput_event_destroy(event);
1802     }
1803 }
1804 
1805 static int
open_restricted(const char * path,int flags,void * user_data)1806 open_restricted (const char *path,
1807                  int flags,
1808                  void *user_data)
1809 {
1810   gint fd;
1811 
1812   if (device_open_callback)
1813     {
1814       GError *error = NULL;
1815 
1816       fd = device_open_callback (path, flags, device_callback_data, &error);
1817 
1818       if (fd < 0)
1819         {
1820           g_warning ("Could not open device %s: %s", path, error->message);
1821           g_error_free (error);
1822         }
1823     }
1824   else
1825     {
1826       fd = open (path, O_RDWR | O_NONBLOCK);
1827       if (fd < 0)
1828         {
1829           g_warning ("Could not open device %s: %s", path, strerror (errno));
1830         }
1831     }
1832 
1833   return fd;
1834 }
1835 
1836 static void
close_restricted(int fd,void * user_data)1837 close_restricted (int fd,
1838                   void *user_data)
1839 {
1840   if (device_close_callback)
1841     device_close_callback (fd, device_callback_data);
1842   else
1843     close (fd);
1844 }
1845 
1846 static const struct libinput_interface libinput_interface = {
1847   open_restricted,
1848   close_restricted
1849 };
1850 
1851 static ClutterVirtualInputDevice *
clutter_device_manager_evdev_create_virtual_device(ClutterDeviceManager * manager,ClutterInputDeviceType device_type)1852 clutter_device_manager_evdev_create_virtual_device (ClutterDeviceManager  *manager,
1853                                                     ClutterInputDeviceType device_type)
1854 {
1855   ClutterDeviceManagerEvdev *manager_evdev =
1856     CLUTTER_DEVICE_MANAGER_EVDEV (manager);
1857   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
1858 
1859   return g_object_new (CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_EVDEV,
1860                        "device-manager", manager,
1861                        "seat", priv->main_seat,
1862                        "device-type", device_type,
1863                        NULL);
1864 }
1865 
1866 static ClutterVirtualDeviceType
clutter_device_manager_evdev_get_supported_virtual_device_types(ClutterDeviceManager * device_manager)1867 clutter_device_manager_evdev_get_supported_virtual_device_types (ClutterDeviceManager *device_manager)
1868 {
1869   return (CLUTTER_VIRTUAL_DEVICE_TYPE_KEYBOARD |
1870           CLUTTER_VIRTUAL_DEVICE_TYPE_POINTER |
1871           CLUTTER_VIRTUAL_DEVICE_TYPE_TOUCHSCREEN);
1872 }
1873 
1874 static void
clutter_device_manager_evdev_compress_motion(ClutterDeviceManager * device_manger,ClutterEvent * event,const ClutterEvent * to_discard)1875 clutter_device_manager_evdev_compress_motion (ClutterDeviceManager *device_manger,
1876                                               ClutterEvent         *event,
1877                                               const ClutterEvent   *to_discard)
1878 {
1879   double dx, dy;
1880   double dx_unaccel, dy_unaccel;
1881   double dst_dx = 0.0, dst_dy = 0.0;
1882   double dst_dx_unaccel = 0.0, dst_dy_unaccel = 0.0;
1883 
1884   if (!clutter_evdev_event_get_relative_motion (to_discard,
1885                                                 &dx, &dy,
1886                                                 &dx_unaccel, &dy_unaccel))
1887     return;
1888 
1889   clutter_evdev_event_get_relative_motion (event,
1890                                            &dst_dx, &dst_dy,
1891                                            &dst_dx_unaccel, &dst_dy_unaccel);
1892   _clutter_evdev_event_set_relative_motion (event,
1893                                             dx + dst_dx,
1894                                             dy + dst_dy,
1895                                             dx_unaccel + dst_dx_unaccel,
1896                                             dy_unaccel + dst_dy_unaccel);
1897 }
1898 
1899 static void
clutter_device_manager_evdev_apply_kbd_a11y_settings(ClutterDeviceManager * device_manager,ClutterKbdA11ySettings * settings)1900 clutter_device_manager_evdev_apply_kbd_a11y_settings (ClutterDeviceManager   *device_manager,
1901                                                       ClutterKbdA11ySettings *settings)
1902 {
1903   ClutterInputDevice *device;
1904 
1905   device = clutter_device_manager_evdev_get_core_device (device_manager, CLUTTER_KEYBOARD_DEVICE);
1906   if (device)
1907     clutter_input_device_evdev_apply_kbd_a11y_settings (CLUTTER_INPUT_DEVICE_EVDEV (device),
1908                                                         settings);
1909 }
1910 
1911 /*
1912  * GObject implementation
1913  */
1914 
1915 static void
clutter_device_manager_evdev_constructed(GObject * gobject)1916 clutter_device_manager_evdev_constructed (GObject *gobject)
1917 {
1918   ClutterDeviceManagerEvdev *manager_evdev;
1919   ClutterDeviceManagerEvdevPrivate *priv;
1920   ClutterEventSource *source;
1921   struct udev *udev;
1922   struct xkb_context *ctx;
1923   struct xkb_rule_names names;
1924 
1925   udev = udev_new ();
1926   if (G_UNLIKELY (udev == NULL))
1927     {
1928       g_warning ("Failed to create udev object");
1929       return;
1930     }
1931 
1932   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (gobject);
1933   priv = manager_evdev->priv;
1934 
1935   priv->libinput = libinput_udev_create_context (&libinput_interface,
1936                                                  manager_evdev,
1937                                                  udev);
1938   if (priv->libinput == NULL)
1939     {
1940       g_critical ("Failed to create the libinput object.");
1941       return;
1942     }
1943 
1944   if (libinput_udev_assign_seat (priv->libinput,
1945                                  evdev_seat_id ? evdev_seat_id : "seat0") == -1)
1946     {
1947       g_critical ("Failed to assign a seat to the libinput object.");
1948       libinput_unref (priv->libinput);
1949       priv->libinput = NULL;
1950       return;
1951     }
1952 
1953   udev_unref (udev);
1954 
1955   names.rules = "evdev";
1956   names.model = "pc105";
1957   names.layout = option_xkb_layout;
1958   names.variant = option_xkb_variant;
1959   names.options = option_xkb_options;
1960 
1961   ctx = xkb_context_new (0);
1962   g_assert (ctx);
1963   priv->keymap = xkb_keymap_new_from_names (ctx, &names, 0);
1964   xkb_context_unref (ctx);
1965 
1966   priv->main_seat = clutter_seat_evdev_new (manager_evdev);
1967   priv->seats = g_slist_append (priv->seats, priv->main_seat);
1968 
1969   dispatch_libinput (manager_evdev);
1970 
1971   source = clutter_event_source_new (manager_evdev);
1972   priv->event_source = source;
1973 }
1974 
1975 static void
clutter_device_manager_evdev_dispose(GObject * object)1976 clutter_device_manager_evdev_dispose (GObject *object)
1977 {
1978   ClutterDeviceManagerEvdev *manager_evdev;
1979   ClutterDeviceManagerEvdevPrivate *priv;
1980 
1981   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object);
1982   priv = manager_evdev->priv;
1983 
1984   if (priv->stage_added_handler)
1985     {
1986       g_signal_handler_disconnect (priv->stage_manager,
1987                                    priv->stage_added_handler);
1988       priv->stage_added_handler = 0;
1989     }
1990 
1991   if (priv->stage_removed_handler)
1992     {
1993       g_signal_handler_disconnect (priv->stage_manager,
1994                                    priv->stage_removed_handler);
1995       priv->stage_removed_handler = 0;
1996     }
1997 
1998   if (priv->stage_manager)
1999     {
2000       g_object_unref (priv->stage_manager);
2001       priv->stage_manager = NULL;
2002     }
2003 
2004   G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->dispose (object);
2005 }
2006 
2007 static void
clutter_device_manager_evdev_finalize(GObject * object)2008 clutter_device_manager_evdev_finalize (GObject *object)
2009 {
2010   ClutterDeviceManagerEvdev *manager_evdev;
2011   ClutterDeviceManagerEvdevPrivate *priv;
2012 
2013   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object);
2014   priv = manager_evdev->priv;
2015 
2016   g_slist_free_full (priv->seats, (GDestroyNotify) clutter_seat_evdev_free);
2017   g_slist_free (priv->devices);
2018 
2019   if (priv->keymap)
2020     xkb_keymap_unref (priv->keymap);
2021 
2022   if (priv->event_source != NULL)
2023     clutter_event_source_free (priv->event_source);
2024 
2025   if (priv->constrain_data_notify != NULL)
2026     priv->constrain_data_notify (priv->constrain_data);
2027 
2028   if (priv->libinput != NULL)
2029     libinput_unref (priv->libinput);
2030 
2031   g_list_free (priv->free_device_ids);
2032 
2033   G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->finalize (object);
2034 }
2035 
2036 static void
clutter_device_manager_evdev_class_init(ClutterDeviceManagerEvdevClass * klass)2037 clutter_device_manager_evdev_class_init (ClutterDeviceManagerEvdevClass *klass)
2038 {
2039   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
2040   ClutterDeviceManagerClass *manager_class;
2041 
2042   gobject_class->constructed = clutter_device_manager_evdev_constructed;
2043   gobject_class->finalize = clutter_device_manager_evdev_finalize;
2044   gobject_class->dispose = clutter_device_manager_evdev_dispose;
2045 
2046   manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
2047   manager_class->add_device = clutter_device_manager_evdev_add_device;
2048   manager_class->remove_device = clutter_device_manager_evdev_remove_device;
2049   manager_class->get_devices = clutter_device_manager_evdev_get_devices;
2050   manager_class->get_core_device = clutter_device_manager_evdev_get_core_device;
2051   manager_class->get_device = clutter_device_manager_evdev_get_device;
2052   manager_class->create_virtual_device = clutter_device_manager_evdev_create_virtual_device;
2053   manager_class->get_supported_virtual_device_types = clutter_device_manager_evdev_get_supported_virtual_device_types;
2054   manager_class->compress_motion = clutter_device_manager_evdev_compress_motion;
2055   manager_class->apply_kbd_a11y_settings = clutter_device_manager_evdev_apply_kbd_a11y_settings;
2056 }
2057 
2058 static void
clutter_device_manager_evdev_stage_added_cb(ClutterStageManager * manager,ClutterStage * stage,ClutterDeviceManagerEvdev * self)2059 clutter_device_manager_evdev_stage_added_cb (ClutterStageManager *manager,
2060                                              ClutterStage *stage,
2061                                              ClutterDeviceManagerEvdev *self)
2062 {
2063   ClutterDeviceManagerEvdevPrivate *priv = self->priv;
2064   GSList *l;
2065 
2066   /* NB: Currently we can only associate a single stage with all evdev
2067    * devices.
2068    *
2069    * We save a pointer to the stage so if we release/reclaim input
2070    * devices due to switching virtual terminals then we know what
2071    * stage to re associate the devices with.
2072    */
2073   priv->stage = stage;
2074 
2075   /* Set the stage of any devices that don't already have a stage */
2076   for (l = priv->seats; l; l = l->next)
2077     {
2078       ClutterSeatEvdev *seat = l->data;
2079 
2080       clutter_seat_evdev_set_stage (seat, stage);
2081     }
2082 
2083   /* We only want to do this once so we can catch the default
2084      stage. If the application has multiple stages then it will need
2085      to manage the stage of the input devices itself */
2086   g_signal_handler_disconnect (priv->stage_manager,
2087                                priv->stage_added_handler);
2088   priv->stage_added_handler = 0;
2089 }
2090 
2091 static void
clutter_device_manager_evdev_stage_removed_cb(ClutterStageManager * manager,ClutterStage * stage,ClutterDeviceManagerEvdev * self)2092 clutter_device_manager_evdev_stage_removed_cb (ClutterStageManager *manager,
2093                                                ClutterStage *stage,
2094                                                ClutterDeviceManagerEvdev *self)
2095 {
2096   ClutterDeviceManagerEvdevPrivate *priv = self->priv;
2097   GSList *l;
2098 
2099   /* Remove the stage of any input devices that were pointing to this
2100      stage so we don't send events to invalid stages */
2101   for (l = priv->seats; l; l = l->next)
2102     {
2103       ClutterSeatEvdev *seat = l->data;
2104 
2105       clutter_seat_evdev_set_stage (seat, NULL);
2106     }
2107 }
2108 
2109 static void
clutter_device_manager_evdev_init(ClutterDeviceManagerEvdev * self)2110 clutter_device_manager_evdev_init (ClutterDeviceManagerEvdev *self)
2111 {
2112   ClutterDeviceManagerEvdevPrivate *priv;
2113 
2114   priv = self->priv = clutter_device_manager_evdev_get_instance_private (self);
2115 
2116   priv->stage_manager = clutter_stage_manager_get_default ();
2117   g_object_ref (priv->stage_manager);
2118 
2119   /* evdev doesn't have any way to link an event to a particular stage
2120      so we'll have to leave it up to applications to set the
2121      corresponding stage for an input device. However to make it
2122      easier for applications that are only using one fullscreen stage
2123      (which is probably the most frequent use-case for the evdev
2124      backend) we'll associate any input devices that don't have a
2125      stage with the first stage created. */
2126   priv->stage_added_handler =
2127     g_signal_connect (priv->stage_manager,
2128                       "stage-added",
2129                       G_CALLBACK (clutter_device_manager_evdev_stage_added_cb),
2130                       self);
2131   priv->stage_removed_handler =
2132     g_signal_connect (priv->stage_manager,
2133                       "stage-removed",
2134                       G_CALLBACK (clutter_device_manager_evdev_stage_removed_cb),
2135                       self);
2136 
2137   priv->device_id_next = INITIAL_DEVICE_ID;
2138 }
2139 
2140 void
_clutter_events_evdev_init(ClutterBackend * backend)2141 _clutter_events_evdev_init (ClutterBackend *backend)
2142 {
2143   CLUTTER_NOTE (EVENT, "Initializing evdev backend");
2144 
2145   backend->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV,
2146                                           "backend", backend,
2147                                           NULL);
2148 }
2149 
2150 void
_clutter_events_evdev_uninit(ClutterBackend * backend)2151 _clutter_events_evdev_uninit (ClutterBackend *backend)
2152 {
2153   CLUTTER_NOTE (EVENT, "Uninitializing evdev backend");
2154 }
2155 
2156 gint
_clutter_device_manager_evdev_acquire_device_id(ClutterDeviceManagerEvdev * manager_evdev)2157 _clutter_device_manager_evdev_acquire_device_id (ClutterDeviceManagerEvdev *manager_evdev)
2158 {
2159   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
2160   GList *first;
2161   gint next_id;
2162 
2163   if (priv->free_device_ids == NULL)
2164     {
2165       gint i;
2166 
2167       /* We ran out of free ID's, so append 10 new ones. */
2168       for (i = 0; i < 10; i++)
2169         priv->free_device_ids =
2170           g_list_append (priv->free_device_ids,
2171                          GINT_TO_POINTER (priv->device_id_next++));
2172     }
2173 
2174   first = g_list_first (priv->free_device_ids);
2175   next_id = GPOINTER_TO_INT (first->data);
2176   priv->free_device_ids = g_list_delete_link (priv->free_device_ids, first);
2177 
2178   return next_id;
2179 }
2180 
2181 void
_clutter_device_manager_evdev_dispatch(ClutterDeviceManagerEvdev * manager_evdev)2182 _clutter_device_manager_evdev_dispatch (ClutterDeviceManagerEvdev *manager_evdev)
2183 {
2184   dispatch_libinput (manager_evdev);
2185 }
2186 
2187 static int
compare_ids(gconstpointer a,gconstpointer b)2188 compare_ids (gconstpointer a,
2189              gconstpointer b)
2190 {
2191   return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b);
2192 }
2193 
2194 void
_clutter_device_manager_evdev_release_device_id(ClutterDeviceManagerEvdev * manager_evdev,ClutterInputDevice * device)2195 _clutter_device_manager_evdev_release_device_id (ClutterDeviceManagerEvdev *manager_evdev,
2196                                                  ClutterInputDevice        *device)
2197 {
2198   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
2199   gint device_id;
2200 
2201   device_id = clutter_input_device_get_device_id (device);
2202   priv->free_device_ids = g_list_insert_sorted (priv->free_device_ids,
2203                                                 GINT_TO_POINTER (device_id),
2204                                                 compare_ids);
2205 }
2206 
2207 struct xkb_keymap *
_clutter_device_manager_evdev_get_keymap(ClutterDeviceManagerEvdev * manager_evdev)2208 _clutter_device_manager_evdev_get_keymap (ClutterDeviceManagerEvdev *manager_evdev)
2209 {
2210   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
2211 
2212   return priv->keymap;
2213 }
2214 
2215 ClutterStage *
_clutter_device_manager_evdev_get_stage(ClutterDeviceManagerEvdev * manager_evdev)2216 _clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev)
2217 {
2218   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
2219 
2220   return priv->stage;
2221 }
2222 
2223 /**
2224  * clutter_evdev_release_devices:
2225  *
2226  * Releases all the evdev devices that Clutter is currently managing. This api
2227  * is typically used when switching away from the Clutter application when
2228  * switching tty. The devices can be reclaimed later with a call to
2229  * clutter_evdev_reclaim_devices().
2230  *
2231  * This function should only be called after clutter has been initialized.
2232  *
2233  * Since: 1.10
2234  * Stability: unstable
2235  */
2236 void
clutter_evdev_release_devices(void)2237 clutter_evdev_release_devices (void)
2238 {
2239   ClutterDeviceManager *manager = clutter_device_manager_get_default ();
2240   ClutterDeviceManagerEvdev *manager_evdev;
2241   ClutterDeviceManagerEvdevPrivate *priv;
2242 
2243   if (!manager)
2244     {
2245       g_warning ("clutter_evdev_release_devices shouldn't be called "
2246                  "before clutter_init()");
2247       return;
2248     }
2249 
2250   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager));
2251 
2252   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
2253   priv = manager_evdev->priv;
2254 
2255   if (priv->released)
2256     {
2257       g_warning ("clutter_evdev_release_devices() shouldn't be called "
2258                  "multiple times without a corresponding call to "
2259                  "clutter_evdev_reclaim_devices() first");
2260       return;
2261     }
2262 
2263   libinput_suspend (priv->libinput);
2264   process_events (manager_evdev);
2265 
2266   priv->released = TRUE;
2267 }
2268 
2269 static void
clutter_evdev_update_xkb_state(ClutterDeviceManagerEvdev * manager_evdev)2270 clutter_evdev_update_xkb_state (ClutterDeviceManagerEvdev *manager_evdev)
2271 {
2272   ClutterDeviceManagerEvdevPrivate *priv;
2273   GSList *iter;
2274   ClutterSeatEvdev *seat;
2275   xkb_mod_mask_t latched_mods;
2276   xkb_mod_mask_t locked_mods;
2277 
2278   priv = manager_evdev->priv;
2279 
2280   for (iter = priv->seats; iter; iter = iter->next)
2281     {
2282       seat = iter->data;
2283 
2284       latched_mods = xkb_state_serialize_mods (seat->xkb,
2285                                                XKB_STATE_MODS_LATCHED);
2286       locked_mods = xkb_state_serialize_mods (seat->xkb,
2287                                               XKB_STATE_MODS_LOCKED);
2288       xkb_state_unref (seat->xkb);
2289       seat->xkb = xkb_state_new (priv->keymap);
2290 
2291       xkb_state_update_mask (seat->xkb,
2292                              0, /* depressed */
2293                              latched_mods,
2294                              locked_mods,
2295                              0, 0, seat->layout_idx);
2296 
2297       seat->caps_lock_led = xkb_keymap_led_get_index (priv->keymap, XKB_LED_NAME_CAPS);
2298       seat->num_lock_led = xkb_keymap_led_get_index (priv->keymap, XKB_LED_NAME_NUM);
2299       seat->scroll_lock_led = xkb_keymap_led_get_index (priv->keymap, XKB_LED_NAME_SCROLL);
2300 
2301       clutter_seat_evdev_sync_leds (seat);
2302     }
2303 }
2304 
2305 /**
2306  * clutter_evdev_reclaim_devices:
2307  *
2308  * This causes Clutter to re-probe for evdev devices. This is must only be
2309  * called after a corresponding call to clutter_evdev_release_devices()
2310  * was previously used to release all evdev devices. This API is typically
2311  * used when a clutter application using evdev has regained focus due to
2312  * switching ttys.
2313  *
2314  * This function should only be called after clutter has been initialized.
2315  *
2316  * Since: 1.10
2317  * Stability: unstable
2318  */
2319 void
clutter_evdev_reclaim_devices(void)2320 clutter_evdev_reclaim_devices (void)
2321 {
2322   ClutterDeviceManager *manager = clutter_device_manager_get_default ();
2323   ClutterDeviceManagerEvdev *manager_evdev =
2324     CLUTTER_DEVICE_MANAGER_EVDEV (manager);
2325   ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
2326 
2327   if (!priv->released)
2328     {
2329       g_warning ("Spurious call to clutter_evdev_reclaim_devices() without "
2330                  "previous call to clutter_evdev_release_devices");
2331       return;
2332     }
2333 
2334   libinput_resume (priv->libinput);
2335   clutter_evdev_update_xkb_state (manager_evdev);
2336   process_events (manager_evdev);
2337 
2338   priv->released = FALSE;
2339 }
2340 
2341 /**
2342  * clutter_evdev_set_device_callbacks: (skip)
2343  * @open_callback: the user replacement for open()
2344  * @close_callback: the user replacement for close()
2345  * @user_data: user data for @callback
2346  *
2347  * Through this function, the application can set a custom callback
2348  * to invoked when Clutter is about to open an evdev device. It can do
2349  * so if special handling is needed, for example to circumvent permission
2350  * problems.
2351  *
2352  * Setting @callback to %NULL will reset the default behavior.
2353  *
2354  * For reliable effects, this function must be called before clutter_init().
2355  *
2356  * Since: 1.16
2357  * Stability: unstable
2358  */
2359 void
clutter_evdev_set_device_callbacks(ClutterOpenDeviceCallback open_callback,ClutterCloseDeviceCallback close_callback,gpointer user_data)2360 clutter_evdev_set_device_callbacks (ClutterOpenDeviceCallback  open_callback,
2361                                     ClutterCloseDeviceCallback close_callback,
2362                                     gpointer                   user_data)
2363 {
2364   device_open_callback = open_callback;
2365   device_close_callback = close_callback;
2366   device_callback_data = user_data;
2367 }
2368 
2369 /**
2370  * clutter_evdev_set_keyboard_map: (skip)
2371  * @evdev: the #ClutterDeviceManager created by the evdev backend
2372  * @keymap: the new keymap
2373  *
2374  * Instructs @evdev to use the speficied keyboard map. This will cause
2375  * the backend to drop the state and create a new one with the new
2376  * map. To avoid state being lost, callers should ensure that no key
2377  * is pressed when calling this function.
2378  *
2379  * Since: 1.16
2380  * Stability: unstable
2381  */
2382 void
clutter_evdev_set_keyboard_map(ClutterDeviceManager * evdev,struct xkb_keymap * keymap)2383 clutter_evdev_set_keyboard_map (ClutterDeviceManager *evdev,
2384 				struct xkb_keymap    *keymap)
2385 {
2386   ClutterDeviceManagerEvdev *manager_evdev;
2387   ClutterDeviceManagerEvdevPrivate *priv;
2388 
2389   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev));
2390 
2391   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
2392   priv = manager_evdev->priv;
2393 
2394   if (priv->keymap)
2395     xkb_keymap_unref (priv->keymap);
2396 
2397   priv->keymap = xkb_keymap_ref (keymap);
2398   clutter_evdev_update_xkb_state (manager_evdev);
2399 }
2400 
2401 /**
2402  * clutter_evdev_get_keyboard_map: (skip)
2403  * @evdev: the #ClutterDeviceManager created by the evdev backend
2404  *
2405  * Retrieves the #xkb_keymap in use by the evdev backend.
2406  *
2407  * Return value: the #xkb_keymap.
2408  *
2409  * Since: 1.18
2410  * Stability: unstable
2411  */
2412 struct xkb_keymap *
clutter_evdev_get_keyboard_map(ClutterDeviceManager * evdev)2413 clutter_evdev_get_keyboard_map (ClutterDeviceManager *evdev)
2414 {
2415   ClutterDeviceManagerEvdev *manager_evdev;
2416 
2417   g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev), NULL);
2418 
2419   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
2420 
2421   return xkb_state_get_keymap (manager_evdev->priv->main_seat->xkb);
2422 }
2423 
2424 /**
2425  * clutter_evdev_set_keyboard_layout_index: (skip)
2426  * @evdev: the #ClutterDeviceManager created by the evdev backend
2427  * @idx: the xkb layout index to set
2428  *
2429  * Sets the xkb layout index on the backend's #xkb_state .
2430  *
2431  * Since: 1.20
2432  * Stability: unstable
2433  */
2434 void
clutter_evdev_set_keyboard_layout_index(ClutterDeviceManager * evdev,xkb_layout_index_t idx)2435 clutter_evdev_set_keyboard_layout_index (ClutterDeviceManager *evdev,
2436                                          xkb_layout_index_t    idx)
2437 {
2438   ClutterDeviceManagerEvdev *manager_evdev;
2439   xkb_mod_mask_t depressed_mods;
2440   xkb_mod_mask_t latched_mods;
2441   xkb_mod_mask_t locked_mods;
2442   struct xkb_state *state;
2443   GSList *l;
2444 
2445   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev));
2446 
2447   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
2448   state = manager_evdev->priv->main_seat->xkb;
2449 
2450   depressed_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED);
2451   latched_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED);
2452   locked_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED);
2453 
2454   xkb_state_update_mask (state, depressed_mods, latched_mods, locked_mods, 0, 0, idx);
2455   for (l = manager_evdev->priv->seats; l; l = l->next)
2456     {
2457       ClutterSeatEvdev *seat = l->data;
2458 
2459       seat->layout_idx = idx;
2460     }
2461 }
2462 
2463 /**
2464  * clutter_evdev_get_keyboard_layout_index: (skip)
2465  */
2466 xkb_layout_index_t
clutter_evdev_get_keyboard_layout_index(ClutterDeviceManager * evdev)2467 clutter_evdev_get_keyboard_layout_index (ClutterDeviceManager *evdev)
2468 {
2469   ClutterDeviceManagerEvdev *manager_evdev;
2470 
2471   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
2472   return manager_evdev->priv->main_seat->layout_idx;
2473 }
2474 
2475 /**
2476  * clutter_evdev_set_keyboard_numlock: (skip)
2477  * @evdev: the #ClutterDeviceManager created by the evdev backend
2478  * @numlock_set: TRUE to set NumLock ON, FALSE otherwise.
2479  *
2480  * Sets the NumLock state on the backend's #xkb_state .
2481  *
2482  * Stability: unstable
2483  */
2484 void
clutter_evdev_set_keyboard_numlock(ClutterDeviceManager * evdev,gboolean numlock_state)2485 clutter_evdev_set_keyboard_numlock (ClutterDeviceManager *evdev,
2486                                     gboolean              numlock_state)
2487 {
2488   ClutterDeviceManagerEvdev *manager_evdev;
2489   ClutterDeviceManagerEvdevPrivate *priv;
2490   GSList *iter;
2491   xkb_mod_mask_t numlock;
2492 
2493   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev));
2494 
2495   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
2496   priv = manager_evdev->priv;
2497   numlock = (1 << xkb_keymap_mod_get_index(priv->keymap, "Mod2"));
2498 
2499   for (iter = priv->seats; iter; iter = iter->next)
2500     {
2501       ClutterSeatEvdev *seat = iter->data;
2502       xkb_mod_mask_t depressed_mods;
2503       xkb_mod_mask_t latched_mods;
2504       xkb_mod_mask_t locked_mods;
2505       xkb_mod_mask_t group_mods;
2506 
2507       depressed_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_DEPRESSED);
2508       latched_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LATCHED);
2509       locked_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LOCKED);
2510       group_mods = xkb_state_serialize_layout (seat->xkb, XKB_STATE_LAYOUT_EFFECTIVE);
2511 
2512       if (numlock_state)
2513         locked_mods |= numlock;
2514       else
2515         locked_mods &= ~numlock;
2516 
2517       xkb_state_update_mask (seat->xkb,
2518                              depressed_mods,
2519                              latched_mods,
2520                              locked_mods,
2521                              0, 0,
2522                              group_mods);
2523 
2524       clutter_seat_evdev_sync_leds (seat);
2525     }
2526 }
2527 
2528 
2529 /**
2530  * clutter_evdev_set_pointer_constrain_callback:
2531  * @evdev: the #ClutterDeviceManager created by the evdev backend
2532  * @callback: the callback
2533  * @user_data: data to pass to the callback
2534  * @user_data_notify: function to be called when removing the callback
2535  *
2536  * Sets a callback to be invoked for every pointer motion. The callback
2537  * can then modify the new pointer coordinates to constrain movement within
2538  * a specific region.
2539  *
2540  * Since: 1.16
2541  * Stability: unstable
2542  */
2543 void
clutter_evdev_set_pointer_constrain_callback(ClutterDeviceManager * evdev,ClutterPointerConstrainCallback callback,gpointer user_data,GDestroyNotify user_data_notify)2544 clutter_evdev_set_pointer_constrain_callback (ClutterDeviceManager            *evdev,
2545 					      ClutterPointerConstrainCallback  callback,
2546 					      gpointer                         user_data,
2547 					      GDestroyNotify                   user_data_notify)
2548 {
2549   ClutterDeviceManagerEvdev *manager_evdev;
2550   ClutterDeviceManagerEvdevPrivate *priv;
2551 
2552   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev));
2553 
2554   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
2555   priv = manager_evdev->priv;
2556 
2557   if (priv->constrain_data_notify)
2558     priv->constrain_data_notify (priv->constrain_data);
2559 
2560   priv->constrain_callback = callback;
2561   priv->constrain_data = user_data;
2562   priv->constrain_data_notify = user_data_notify;
2563 }
2564 
2565 void
clutter_evdev_set_relative_motion_filter(ClutterDeviceManager * evdev,ClutterRelativeMotionFilter filter,gpointer user_data)2566 clutter_evdev_set_relative_motion_filter (ClutterDeviceManager       *evdev,
2567                                           ClutterRelativeMotionFilter filter,
2568                                           gpointer                    user_data)
2569 {
2570   ClutterDeviceManagerEvdev *manager_evdev;
2571   ClutterDeviceManagerEvdevPrivate *priv;
2572 
2573   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev));
2574 
2575   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
2576   priv = manager_evdev->priv;
2577 
2578   priv->relative_motion_filter = filter;
2579   priv->relative_motion_filter_user_data = user_data;
2580 }
2581 
2582 /**
2583  * clutter_evdev_set_keyboard_repeat:
2584  * @evdev: the #ClutterDeviceManager created by the evdev backend
2585  * @repeat: whether to enable or disable keyboard repeat events
2586  * @delay: the delay in ms between the hardware key press event and
2587  * the first synthetic event
2588  * @interval: the period in ms between consecutive synthetic key
2589  * press events
2590  *
2591  * Enables or disables sythetic key press events, allowing for initial
2592  * delay and interval period to be specified.
2593  *
2594  * Since: 1.18
2595  * Stability: unstable
2596  */
2597 void
clutter_evdev_set_keyboard_repeat(ClutterDeviceManager * evdev,gboolean repeat,guint32 delay,guint32 interval)2598 clutter_evdev_set_keyboard_repeat (ClutterDeviceManager *evdev,
2599                                    gboolean              repeat,
2600                                    guint32               delay,
2601                                    guint32               interval)
2602 {
2603   ClutterDeviceManagerEvdev *manager_evdev;
2604   ClutterSeatEvdev *seat;
2605 
2606   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev));
2607 
2608   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
2609   seat = manager_evdev->priv->main_seat;
2610 
2611   seat->repeat = repeat;
2612   seat->repeat_delay = delay;
2613   seat->repeat_interval = interval;
2614 }
2615 
2616 /**
2617  * clutter_evdev_add_filter: (skip)
2618  * @func: (closure data): a filter function
2619  * @data: (allow-none): user data to be passed to the filter function, or %NULL
2620  * @destroy_notify: (allow-none): function to call on @data when the filter is removed, or %NULL
2621  *
2622  * Adds an event filter function.
2623  *
2624  * Since: 1.20
2625  * Stability: unstable
2626  */
2627 void
clutter_evdev_add_filter(ClutterEvdevFilterFunc func,gpointer data,GDestroyNotify destroy_notify)2628 clutter_evdev_add_filter (ClutterEvdevFilterFunc func,
2629                           gpointer               data,
2630                           GDestroyNotify         destroy_notify)
2631 {
2632   ClutterDeviceManagerEvdev *manager_evdev;
2633   ClutterDeviceManager *manager;
2634   ClutterEventFilter *filter;
2635 
2636   g_return_if_fail (func != NULL);
2637 
2638   manager = clutter_device_manager_get_default ();
2639 
2640   if (!CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager))
2641     {
2642       g_critical ("The Clutter input backend is not a evdev backend");
2643       return;
2644     }
2645 
2646   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
2647 
2648   filter = g_new0 (ClutterEventFilter, 1);
2649   filter->func = func;
2650   filter->data = data;
2651   filter->destroy_notify = destroy_notify;
2652 
2653   manager_evdev->priv->event_filters =
2654     g_slist_append (manager_evdev->priv->event_filters, filter);
2655 }
2656 
2657 /**
2658  * clutter_evdev_remove_filter: (skip)
2659  * @func: a filter function
2660  * @data: (allow-none): user data to be passed to the filter function, or %NULL
2661  *
2662  * Removes the given filter function.
2663  *
2664  * Since: 1.20
2665  * Stability: unstable
2666  */
2667 void
clutter_evdev_remove_filter(ClutterEvdevFilterFunc func,gpointer data)2668 clutter_evdev_remove_filter (ClutterEvdevFilterFunc func,
2669                              gpointer               data)
2670 {
2671   ClutterDeviceManagerEvdev *manager_evdev;
2672   ClutterDeviceManager *manager;
2673   ClutterEventFilter *filter;
2674   GSList *tmp_list;
2675 
2676   g_return_if_fail (func != NULL);
2677 
2678   manager = clutter_device_manager_get_default ();
2679 
2680   if (!CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager))
2681     {
2682       g_critical ("The Clutter input backend is not a evdev backend");
2683       return;
2684     }
2685 
2686   manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
2687   tmp_list = manager_evdev->priv->event_filters;
2688 
2689   while (tmp_list)
2690     {
2691       filter = tmp_list->data;
2692 
2693       if (filter->func == func && filter->data == data)
2694         {
2695           if (filter->destroy_notify)
2696             filter->destroy_notify (filter->data);
2697           free (filter);
2698           manager_evdev->priv->event_filters =
2699             g_slist_delete_link (manager_evdev->priv->event_filters, tmp_list);
2700           return;
2701         }
2702 
2703       tmp_list = tmp_list->next;
2704     }
2705 }
2706 
2707 /**
2708  * clutter_evdev_warp_pointer:
2709  * @pointer_device: the pointer device to warp
2710  * @time: the timestamp for the warp event
2711  * @x: the new X position of the pointer
2712  * @y: the new Y position of the pointer
2713  *
2714  * Warps the pointer to a new location. Technically, this is
2715  * processed the same way as an absolute motion event from
2716  * libinput: it simply generates an absolute motion event that
2717  * will be processed on the next iteration of the mainloop.
2718  *
2719  * The intended use for this is for display servers that need
2720  * to warp cursor the cursor to a new location.
2721  *
2722  * Since: 1.20
2723  * Stability: unstable
2724  */
2725 void
clutter_evdev_warp_pointer(ClutterInputDevice * pointer_device,guint32 time_,int x,int y)2726 clutter_evdev_warp_pointer (ClutterInputDevice   *pointer_device,
2727                             guint32               time_,
2728                             int                   x,
2729                             int                   y)
2730 {
2731   notify_absolute_motion (pointer_device, ms2us(time_), x, y, NULL);
2732 }
2733 
2734 /**
2735  * clutter_evdev_set_seat_id:
2736  * @seat_id: The seat ID
2737  *
2738  * Sets the seat to assign to the libinput context.
2739  *
2740  * For reliable effects, this function must be called before clutter_init().
2741  */
2742 void
clutter_evdev_set_seat_id(const gchar * seat_id)2743 clutter_evdev_set_seat_id (const gchar *seat_id)
2744 {
2745   free (evdev_seat_id);
2746   evdev_seat_id = g_strdup (seat_id);
2747 }
2748