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