1 /*
2  * Copyright (C) 2019 Red Hat Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Author: Carlos Garnacho <carlosg@gnome.org>
18  */
19 #include "config.h"
20 #ifdef __linux__
21 #include <linux/input-event-codes.h>
22 #endif
23 #include <X11/extensions/XInput2.h>
24 #include <X11/extensions/XKB.h>
25 
26 #include "backends/meta-input-settings-private.h"
27 #include "backends/x11/meta-backend-x11.h"
28 #include "backends/x11/meta-clutter-backend-x11.h"
29 #include "backends/x11/meta-event-x11.h"
30 #include "backends/x11/meta-input-device-tool-x11.h"
31 #include "backends/x11/meta-input-device-x11.h"
32 #include "backends/x11/meta-keymap-x11.h"
33 #include "backends/x11/meta-stage-x11.h"
34 #include "backends/x11/meta-virtual-input-device-x11.h"
35 #include "backends/x11/meta-xkb-a11y-x11.h"
36 #include "clutter/clutter-mutter.h"
37 #include "core/bell.h"
38 #include "meta-seat-x11.h"
39 
40 enum
41 {
42   PROP_0,
43   PROP_OPCODE,
44   PROP_POINTER_ID,
45   PROP_KEYBOARD_ID,
46   N_PROPS,
47 
48   /* This property is overridden */
49   PROP_TOUCH_MODE,
50 };
51 
52 typedef struct _MetaTouchInfo MetaTouchInfo;
53 
54 struct _MetaTouchInfo
55 {
56   ClutterEventSequence *sequence;
57   double x;
58   double y;
59 };
60 
61 struct _MetaSeatX11
62 {
63   ClutterSeat parent_instance;
64   ClutterInputDevice *core_pointer;
65   ClutterInputDevice *core_keyboard;
66   GList *devices;
67   GHashTable *devices_by_id;
68   GHashTable *tools_by_serial;
69   GHashTable *touch_coords;
70   MetaKeymapX11 *keymap;
71 
72   int pointer_id;
73   int keyboard_id;
74   int opcode;
75   guint has_touchscreens : 1;
76   guint touch_mode : 1;
77   guint has_pointer_focus : 1;
78 };
79 
80 static GParamSpec *props[N_PROPS] = { 0 };
81 
82 G_DEFINE_TYPE (MetaSeatX11, meta_seat_x11, CLUTTER_TYPE_SEAT)
83 
84 static const char *clutter_input_axis_atom_names[] = {
85   "Abs X",              /* CLUTTER_INPUT_AXIS_X */
86   "Abs Y",              /* CLUTTER_INPUT_AXIS_Y */
87   "Abs Pressure",       /* CLUTTER_INPUT_AXIS_PRESSURE */
88   "Abs Tilt X",         /* CLUTTER_INPUT_AXIS_XTILT */
89   "Abs Tilt Y",         /* CLUTTER_INPUT_AXIS_YTILT */
90   "Abs Wheel",          /* CLUTTER_INPUT_AXIS_WHEEL */
91   "Abs Distance",       /* CLUTTER_INPUT_AXIS_DISTANCE */
92 };
93 
94 static const char *wacom_type_atoms[] = {
95     "STYLUS",
96     "CURSOR",
97     "ERASER",
98     "PAD",
99     "TOUCH"
100 };
101 #define N_WACOM_TYPE_ATOMS G_N_ELEMENTS (wacom_type_atoms)
102 
103 enum
104 {
105     WACOM_TYPE_STYLUS,
106     WACOM_TYPE_CURSOR,
107     WACOM_TYPE_ERASER,
108     WACOM_TYPE_PAD,
109     WACOM_TYPE_TOUCH,
110 };
111 
112 enum
113 {
114   PAD_AXIS_FIRST  = 3, /* First axes are always x/y/pressure, ignored in pads */
115   PAD_AXIS_STRIP1 = PAD_AXIS_FIRST,
116   PAD_AXIS_STRIP2,
117   PAD_AXIS_RING1,
118   PAD_AXIS_RING2,
119 };
120 
121 #define N_AXIS_ATOMS    G_N_ELEMENTS (clutter_input_axis_atom_names)
122 
123 static Atom clutter_input_axis_atoms[N_AXIS_ATOMS] = { 0, };
124 
125 static void
translate_valuator_class(Display * xdisplay,ClutterInputDevice * device,XIValuatorClassInfo * class)126 translate_valuator_class (Display             *xdisplay,
127                           ClutterInputDevice  *device,
128                           XIValuatorClassInfo *class)
129 {
130   static gboolean atoms_initialized = FALSE;
131   ClutterInputAxis i, axis = CLUTTER_INPUT_AXIS_IGNORE;
132 
133   if (G_UNLIKELY (!atoms_initialized))
134     {
135       XInternAtoms (xdisplay,
136                     (char **) clutter_input_axis_atom_names, N_AXIS_ATOMS,
137                     False,
138                     clutter_input_axis_atoms);
139 
140       atoms_initialized = TRUE;
141     }
142 
143   for (i = 0;
144        i < N_AXIS_ATOMS;
145        i += 1)
146     {
147       if (clutter_input_axis_atoms[i] == class->label)
148         {
149           axis = i + 1;
150           break;
151         }
152     }
153 
154   meta_input_device_x11_add_axis (device, axis,
155                                   class->min,
156                                   class->max,
157                                   class->resolution);
158 
159   g_debug ("Added axis '%s' (min:%.2f, max:%.2fd, res:%d) of device %d",
160            clutter_input_axis_atom_names[axis],
161            class->min,
162            class->max,
163            class->resolution,
164            meta_input_device_x11_get_device_id (device));
165 }
166 
167 static void
translate_device_classes(Display * xdisplay,ClutterInputDevice * device,XIAnyClassInfo ** classes,int n_classes)168 translate_device_classes (Display             *xdisplay,
169                           ClutterInputDevice  *device,
170                           XIAnyClassInfo     **classes,
171                           int                  n_classes)
172 {
173   int i;
174 
175   for (i = 0; i < n_classes; i++)
176     {
177       XIAnyClassInfo *class_info = classes[i];
178 
179       switch (class_info->type)
180         {
181         case XIValuatorClass:
182           translate_valuator_class (xdisplay, device,
183                                     (XIValuatorClassInfo *) class_info);
184           break;
185 
186         case XIScrollClass:
187           {
188             XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info;
189             ClutterScrollDirection direction;
190 
191             if (scroll_info->scroll_type == XIScrollTypeVertical)
192               direction = CLUTTER_SCROLL_DOWN;
193             else
194               direction = CLUTTER_SCROLL_RIGHT;
195 
196             g_debug ("Scroll valuator %d: %s, increment: %f",
197                      scroll_info->number,
198                      scroll_info->scroll_type == XIScrollTypeVertical
199                      ? "vertical"
200                      : "horizontal",
201                      scroll_info->increment);
202 
203             meta_input_device_x11_add_scroll_info (device,
204                                                    scroll_info->number,
205                                                    direction,
206                                                    scroll_info->increment);
207           }
208           break;
209 
210         default:
211           break;
212         }
213     }
214 }
215 
216 static gboolean
is_touch_device(XIAnyClassInfo ** classes,int n_classes,ClutterInputDeviceType * device_type,uint32_t * n_touch_points)217 is_touch_device (XIAnyClassInfo         **classes,
218                  int                      n_classes,
219                  ClutterInputDeviceType  *device_type,
220                  uint32_t                *n_touch_points)
221 {
222   int i;
223 
224   for (i = 0; i < n_classes; i++)
225     {
226       XITouchClassInfo *class = (XITouchClassInfo *) classes[i];
227 
228       if (class->type != XITouchClass)
229         continue;
230 
231       if (class->num_touches > 0)
232         {
233           if (class->mode == XIDirectTouch)
234             *device_type = CLUTTER_TOUCHSCREEN_DEVICE;
235           else if (class->mode == XIDependentTouch)
236             *device_type = CLUTTER_TOUCHPAD_DEVICE;
237           else
238             continue;
239 
240           *n_touch_points = class->num_touches;
241 
242           return TRUE;
243         }
244     }
245 
246   return FALSE;
247 }
248 
249 static gboolean
is_touchpad_device(XIDeviceInfo * info)250 is_touchpad_device (XIDeviceInfo *info)
251 {
252   gulong nitems, bytes_after;
253   uint32_t *data = NULL;
254   int rc, format;
255   Atom type;
256   Atom prop;
257 
258   prop = XInternAtom (meta_clutter_x11_get_default_display (),
259                       "libinput Tapping Enabled", True);
260   if (prop == None)
261     return FALSE;
262 
263   meta_clutter_x11_trap_x_errors ();
264   rc = XIGetProperty (meta_clutter_x11_get_default_display (),
265                       info->deviceid,
266                       prop,
267                       0, 1, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
268                       (guchar **) &data);
269   meta_clutter_x11_untrap_x_errors ();
270 
271   /* We don't care about the data */
272   XFree (data);
273 
274   if (rc != Success || type != XA_INTEGER || format != 8 || nitems != 1)
275     return FALSE;
276 
277   return TRUE;
278 }
279 
280 static gboolean
get_device_ids(XIDeviceInfo * info,char ** vendor_id,char ** product_id)281 get_device_ids (XIDeviceInfo  *info,
282                 char         **vendor_id,
283                 char         **product_id)
284 {
285   gulong nitems, bytes_after;
286   uint32_t *data = NULL;
287   int rc, format;
288   Atom type;
289 
290   meta_clutter_x11_trap_x_errors ();
291   rc = XIGetProperty (meta_clutter_x11_get_default_display (),
292                       info->deviceid,
293                       XInternAtom (meta_clutter_x11_get_default_display (), "Device Product ID", False),
294                       0, 2, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
295                       (guchar **) &data);
296   meta_clutter_x11_untrap_x_errors ();
297 
298   if (rc != Success || type != XA_INTEGER || format != 32 || nitems != 2)
299     {
300       XFree (data);
301       return FALSE;
302     }
303 
304   if (vendor_id)
305     *vendor_id = g_strdup_printf ("%.4x", data[0]);
306   if (product_id)
307     *product_id = g_strdup_printf ("%.4x", data[1]);
308 
309   XFree (data);
310 
311   return TRUE;
312 }
313 
314 static char *
get_device_node_path(XIDeviceInfo * info)315 get_device_node_path (XIDeviceInfo *info)
316 {
317   gulong nitems, bytes_after;
318   guchar *data;
319   int rc, format;
320   Atom prop, type;
321   char *node_path;
322 
323   prop = XInternAtom (meta_clutter_x11_get_default_display (), "Device Node", False);
324   if (prop == None)
325     return NULL;
326 
327   meta_clutter_x11_trap_x_errors ();
328 
329   rc = XIGetProperty (meta_clutter_x11_get_default_display (),
330                       info->deviceid, prop, 0, 1024, False,
331                       XA_STRING, &type, &format, &nitems, &bytes_after,
332                       (guchar **) &data);
333 
334   if (meta_clutter_x11_untrap_x_errors ())
335     return NULL;
336 
337   if (rc != Success || type != XA_STRING || format != 8)
338     {
339       XFree (data);
340       return FALSE;
341     }
342 
343   node_path = g_strdup ((char *) data);
344   XFree (data);
345 
346   return node_path;
347 }
348 
349 static void
get_pad_features(XIDeviceInfo * info,uint32_t * n_rings,uint32_t * n_strips)350 get_pad_features (XIDeviceInfo *info,
351                   uint32_t     *n_rings,
352                   uint32_t     *n_strips)
353 {
354   int i, rings = 0, strips = 0;
355 
356   for (i = PAD_AXIS_FIRST; i < info->num_classes; i++)
357     {
358       XIValuatorClassInfo *valuator = (XIValuatorClassInfo*) info->classes[i];
359       int axis = valuator->number;
360 
361       if (valuator->type != XIValuatorClass)
362         continue;
363       if (valuator->max <= 1)
364         continue;
365 
366       /* Ring/strip axes are fixed in pad devices as handled by the
367        * wacom driver. Match those to detect pad features.
368        */
369       if (axis == PAD_AXIS_STRIP1 || axis == PAD_AXIS_STRIP2)
370         strips++;
371       else if (axis == PAD_AXIS_RING1 || axis == PAD_AXIS_RING2)
372         rings++;
373     }
374 
375   *n_rings = rings;
376   *n_strips = strips;
377 }
378 
379 /* The Wacom driver exports the tool type as property. Use that over
380    guessing based on the device name */
381 static gboolean
guess_source_from_wacom_type(XIDeviceInfo * info,ClutterInputDeviceType * source_out)382 guess_source_from_wacom_type (XIDeviceInfo            *info,
383                               ClutterInputDeviceType  *source_out)
384 {
385   gulong nitems, bytes_after;
386   uint32_t *data = NULL;
387   int rc, format;
388   Atom type;
389   Atom prop;
390   Atom device_type;
391   Atom types[N_WACOM_TYPE_ATOMS];
392 
393   prop = XInternAtom (meta_clutter_x11_get_default_display (), "Wacom Tool Type", True);
394   if (prop == None)
395     return FALSE;
396 
397   meta_clutter_x11_trap_x_errors ();
398   rc = XIGetProperty (meta_clutter_x11_get_default_display (),
399                       info->deviceid,
400                       prop,
401                       0, 1, False, XA_ATOM, &type, &format, &nitems, &bytes_after,
402                       (guchar **) &data);
403   meta_clutter_x11_untrap_x_errors ();
404 
405   if (rc != Success || type != XA_ATOM || format != 32 || nitems != 1)
406     {
407       XFree (data);
408       return FALSE;
409     }
410 
411   device_type = *data;
412   XFree (data);
413 
414   if (device_type == 0)
415       return FALSE;
416 
417   rc = XInternAtoms (meta_clutter_x11_get_default_display (),
418                      (char **)wacom_type_atoms,
419                      N_WACOM_TYPE_ATOMS,
420                      False,
421                      types);
422   if (rc == 0)
423       return FALSE;
424 
425   if (device_type == types[WACOM_TYPE_STYLUS])
426     {
427       *source_out = CLUTTER_PEN_DEVICE;
428     }
429   else if (device_type == types[WACOM_TYPE_CURSOR])
430     {
431       *source_out = CLUTTER_CURSOR_DEVICE;
432     }
433   else if (device_type == types[WACOM_TYPE_ERASER])
434     {
435       *source_out = CLUTTER_ERASER_DEVICE;
436     }
437   else if (device_type == types[WACOM_TYPE_PAD])
438     {
439       *source_out = CLUTTER_PAD_DEVICE;
440     }
441   else if (device_type == types[WACOM_TYPE_TOUCH])
442     {
443         uint32_t num_touches = 0;
444 
445         if (!is_touch_device (info->classes, info->num_classes,
446                               source_out, &num_touches))
447             *source_out = CLUTTER_TOUCHSCREEN_DEVICE;
448     }
449   else
450     {
451       return FALSE;
452     }
453 
454   return TRUE;
455 }
456 
457 static ClutterInputDevice *
create_device(MetaSeatX11 * seat_x11,ClutterBackend * backend,XIDeviceInfo * info)458 create_device (MetaSeatX11    *seat_x11,
459                ClutterBackend *backend,
460                XIDeviceInfo   *info)
461 {
462   ClutterInputDeviceType source, touch_source;
463   ClutterInputDevice *retval;
464   ClutterInputMode mode;
465   uint32_t num_touches = 0, num_rings = 0, num_strips = 0;
466   char *vendor_id = NULL, *product_id = NULL, *node_path = NULL;
467 
468   if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
469     {
470       source = CLUTTER_KEYBOARD_DEVICE;
471     }
472   else if (is_touchpad_device (info))
473     {
474       source = CLUTTER_TOUCHPAD_DEVICE;
475     }
476   else if (info->use == XISlavePointer &&
477            is_touch_device (info->classes, info->num_classes,
478                             &touch_source,
479                             &num_touches))
480     {
481       source = touch_source;
482     }
483   else if (!guess_source_from_wacom_type (info, &source))
484     {
485       char *name;
486 
487       name = g_ascii_strdown (info->name, -1);
488 
489       if (strstr (name, "eraser") != NULL)
490         source = CLUTTER_ERASER_DEVICE;
491       else if (strstr (name, "cursor") != NULL)
492         source = CLUTTER_CURSOR_DEVICE;
493       else if (strstr (name, " pad") != NULL)
494         source = CLUTTER_PAD_DEVICE;
495       else if (strstr (name, "wacom") != NULL || strstr (name, "pen") != NULL)
496         source = CLUTTER_PEN_DEVICE;
497       else if (strstr (name, "touchpad") != NULL)
498         source = CLUTTER_TOUCHPAD_DEVICE;
499       else
500         source = CLUTTER_POINTER_DEVICE;
501 
502       g_free (name);
503     }
504 
505   switch (info->use)
506     {
507     case XIMasterKeyboard:
508     case XIMasterPointer:
509       mode = CLUTTER_INPUT_MODE_LOGICAL;
510       break;
511 
512     case XISlaveKeyboard:
513     case XISlavePointer:
514       mode = CLUTTER_INPUT_MODE_PHYSICAL;
515       break;
516 
517     case XIFloatingSlave:
518     default:
519       mode = CLUTTER_INPUT_MODE_FLOATING;
520       break;
521     }
522 
523   if (info->use != XIMasterKeyboard &&
524       info->use != XIMasterPointer)
525     {
526       get_device_ids (info, &vendor_id, &product_id);
527       node_path = get_device_node_path (info);
528     }
529 
530   if (source == CLUTTER_PAD_DEVICE)
531     get_pad_features (info, &num_rings, &num_strips);
532 
533   retval = g_object_new (META_TYPE_INPUT_DEVICE_X11,
534                          "name", info->name,
535                          "id", info->deviceid,
536                          "has-cursor", (info->use == XIMasterPointer),
537                          "device-type", source,
538                          "device-mode", mode,
539                          "backend", backend,
540                          "vendor-id", vendor_id,
541                          "product-id", product_id,
542                          "device-node", node_path,
543                          "n-rings", num_rings,
544                          "n-strips", num_strips,
545                          "n-mode-groups", MAX (num_rings, num_strips),
546                          "seat", seat_x11,
547                          NULL);
548 
549   translate_device_classes (meta_clutter_x11_get_default_display (), retval,
550                             info->classes,
551                             info->num_classes);
552 
553   g_free (vendor_id);
554   g_free (product_id);
555   g_free (node_path);
556 
557   g_debug ("Created device '%s' (id: %d, has-cursor: %s)",
558            info->name,
559            info->deviceid,
560            info->use == XIMasterPointer ? "yes" : "no");
561 
562   return retval;
563 }
564 
565 static void
pad_passive_button_grab(ClutterInputDevice * device)566 pad_passive_button_grab (ClutterInputDevice *device)
567 {
568   XIGrabModifiers xi_grab_mods = { XIAnyModifier, };
569   XIEventMask xi_event_mask;
570   int device_id, rc;
571 
572   device_id = meta_input_device_x11_get_device_id (device);
573 
574   xi_event_mask.deviceid = device_id;
575   xi_event_mask.mask_len = XIMaskLen (XI_LASTEVENT);
576   xi_event_mask.mask = g_new0 (unsigned char, xi_event_mask.mask_len);
577 
578   XISetMask (xi_event_mask.mask, XI_Motion);
579   XISetMask (xi_event_mask.mask, XI_ButtonPress);
580   XISetMask (xi_event_mask.mask, XI_ButtonRelease);
581 
582   meta_clutter_x11_trap_x_errors ();
583   rc = XIGrabButton (meta_clutter_x11_get_default_display (),
584                      device_id, XIAnyButton,
585                      meta_clutter_x11_get_root_window (), None,
586                      XIGrabModeSync, XIGrabModeSync,
587                      True, &xi_event_mask, 1, &xi_grab_mods);
588   if (rc != 0)
589     {
590       g_warning ("Could not passively grab pad device: %s",
591                  clutter_input_device_get_device_name (device));
592     }
593   else
594     {
595       XIAllowEvents (meta_clutter_x11_get_default_display (),
596                      device_id, XIAsyncDevice,
597                      CLUTTER_CURRENT_TIME);
598     }
599 
600   meta_clutter_x11_untrap_x_errors ();
601 
602   g_free (xi_event_mask.mask);
603 }
604 
605 static void
update_touch_mode(MetaSeatX11 * seat_x11)606 update_touch_mode (MetaSeatX11 *seat_x11)
607 {
608   gboolean touch_mode;
609 
610   touch_mode = seat_x11->has_touchscreens;
611 
612   if (seat_x11->touch_mode == touch_mode)
613     return;
614 
615   seat_x11->touch_mode = touch_mode;
616   g_object_notify (G_OBJECT (seat_x11), "touch-mode");
617 }
618 
619 static ClutterInputDevice *
add_device(MetaSeatX11 * seat_x11,ClutterBackend * backend,XIDeviceInfo * info)620 add_device (MetaSeatX11    *seat_x11,
621             ClutterBackend *backend,
622             XIDeviceInfo   *info)
623 {
624   ClutterInputDevice *device;
625 
626   device = create_device (seat_x11, backend, info);
627 
628   g_hash_table_replace (seat_x11->devices_by_id,
629                         GINT_TO_POINTER (info->deviceid),
630                         device);
631 
632   if (info->use == XIMasterPointer &&
633       info->deviceid == seat_x11->pointer_id)
634     {
635       seat_x11->core_pointer = device;
636     }
637   else if (info->use == XIMasterKeyboard &&
638            info->deviceid == seat_x11->keyboard_id)
639     {
640       seat_x11->core_keyboard = device;
641     }
642   else if ((info->use == XISlavePointer &&
643             info->attachment == seat_x11->pointer_id) ||
644            (info->use == XISlaveKeyboard &&
645             info->attachment == seat_x11->keyboard_id))
646     {
647       seat_x11->devices = g_list_prepend (seat_x11->devices, device);
648     }
649   else
650     {
651       g_warning ("Unhandled device: %s",
652                  clutter_input_device_get_device_name (device));
653     }
654 
655   if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE)
656     pad_passive_button_grab (device);
657 
658   return device;
659 }
660 
661 static gboolean
has_touchscreens(MetaSeatX11 * seat_x11)662 has_touchscreens (MetaSeatX11 *seat_x11)
663 {
664   GList *l;
665 
666   for (l = seat_x11->devices; l; l = l->next)
667     {
668       if (clutter_input_device_get_device_type (l->data) == CLUTTER_TOUCHSCREEN_DEVICE)
669         return TRUE;
670     }
671 
672   return FALSE;
673 }
674 
675 static void
remove_device(MetaSeatX11 * seat_x11,ClutterInputDevice * device)676 remove_device (MetaSeatX11        *seat_x11,
677                ClutterInputDevice *device)
678 {
679   if (seat_x11->core_pointer == device)
680     {
681       seat_x11->core_pointer = NULL;
682     }
683   else if (seat_x11->core_keyboard == device)
684     {
685       seat_x11->core_keyboard = NULL;
686     }
687   else
688     {
689       seat_x11->devices = g_list_remove (seat_x11->devices, device);
690     }
691 }
692 
693 static gboolean
meta_seat_x11_handle_event_post(ClutterSeat * seat,const ClutterEvent * event)694 meta_seat_x11_handle_event_post (ClutterSeat        *seat,
695                                  const ClutterEvent *event)
696 {
697   MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
698   ClutterInputDevice *device;
699   MetaInputSettings *input_settings;
700   gboolean is_touch;
701 
702   if (event->type != CLUTTER_DEVICE_ADDED &&
703       event->type != CLUTTER_DEVICE_REMOVED)
704     return TRUE;
705 
706   device = clutter_event_get_device (event);
707   is_touch =
708     clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE;
709   input_settings = meta_backend_get_input_settings (meta_get_backend ());
710 
711   switch (event->type)
712     {
713       case CLUTTER_DEVICE_ADDED:
714         meta_input_settings_add_device (input_settings, device);
715         seat_x11->has_touchscreens |= is_touch;
716         break;
717       case CLUTTER_DEVICE_REMOVED:
718         if (is_touch)
719           seat_x11->has_touchscreens = has_touchscreens (seat_x11);
720         meta_input_settings_remove_device (input_settings, device);
721         break;
722       default:
723         break;
724     }
725 
726   if (is_touch)
727     update_touch_mode (seat_x11);
728 
729   return TRUE;
730 }
731 
732 static uint
device_get_tool_serial(ClutterInputDevice * device)733 device_get_tool_serial (ClutterInputDevice *device)
734 {
735   gulong nitems, bytes_after;
736   uint32_t *data = NULL;
737   int serial_id = 0;
738   int rc, format;
739   Atom type;
740   Atom prop;
741 
742   prop = XInternAtom (meta_clutter_x11_get_default_display (),
743                       "Wacom Serial IDs", True);
744   if (prop == None)
745     return 0;
746 
747   meta_clutter_x11_trap_x_errors ();
748   rc = XIGetProperty (meta_clutter_x11_get_default_display (),
749                       meta_input_device_x11_get_device_id (device),
750                       prop, 0, 4, FALSE, XA_INTEGER, &type, &format, &nitems, &bytes_after,
751                       (guchar **) &data);
752   meta_clutter_x11_untrap_x_errors ();
753 
754   if (rc == Success && type == XA_INTEGER && format == 32 && nitems >= 4)
755     serial_id = data[3];
756 
757   XFree (data);
758 
759   return serial_id;
760 }
761 
762 static gboolean
translate_hierarchy_event(ClutterBackend * backend,MetaSeatX11 * seat_x11,XIHierarchyEvent * ev,ClutterEvent * event)763 translate_hierarchy_event (ClutterBackend   *backend,
764                            MetaSeatX11      *seat_x11,
765                            XIHierarchyEvent *ev,
766                            ClutterEvent     *event)
767 {
768   int i;
769   gboolean retval = FALSE;
770 
771   for (i = 0; i < ev->num_info; i++)
772     {
773       if (ev->info[i].flags & XIDeviceEnabled &&
774           !g_hash_table_lookup (seat_x11->devices_by_id,
775                                 GINT_TO_POINTER (ev->info[i].deviceid)))
776         {
777           XIDeviceInfo *info;
778           int n_devices;
779 
780           g_debug ("Hierarchy event: device enabled");
781 
782           meta_clutter_x11_trap_x_errors ();
783           info = XIQueryDevice (meta_clutter_x11_get_default_display (),
784                                 ev->info[i].deviceid,
785                                 &n_devices);
786           meta_clutter_x11_untrap_x_errors ();
787           if (info != NULL)
788             {
789               ClutterInputDevice *device;
790 
791               device = add_device (seat_x11, backend, &info[0]);
792 
793               event->any.type = CLUTTER_DEVICE_ADDED;
794               event->any.time = ev->time;
795               clutter_event_set_device (event, device);
796 
797               retval = TRUE;
798               XIFreeDeviceInfo (info);
799             }
800         }
801       else if (ev->info[i].flags & XIDeviceDisabled)
802         {
803           g_autoptr (ClutterInputDevice) device = NULL;
804           g_debug ("Hierarchy event: device disabled");
805 
806           g_hash_table_steal_extended (seat_x11->devices_by_id,
807                                        GINT_TO_POINTER (ev->info[i].deviceid),
808                                        NULL,
809                                        (gpointer) &device);
810 
811           if (device != NULL)
812             {
813               remove_device (seat_x11, device);
814 
815               event->any.type = CLUTTER_DEVICE_REMOVED;
816               event->any.time = ev->time;
817               clutter_event_set_device (event, device);
818 
819               retval = TRUE;
820             }
821         }
822       else if ((ev->info[i].flags & XISlaveAttached) ||
823                (ev->info[i].flags & XISlaveDetached))
824         {
825           g_debug ("Hierarchy event: physical device %s",
826                    (ev->info[i].flags & XISlaveAttached)
827                    ? "attached"
828                    : "detached");
829         }
830     }
831 
832   return retval;
833 }
834 
835 static void
translate_property_event(MetaSeatX11 * seat_x11,XIEvent * event)836 translate_property_event (MetaSeatX11 *seat_x11,
837                           XIEvent     *event)
838 {
839   XIPropertyEvent *xev = (XIPropertyEvent *) event;
840   Atom serial_ids_prop;
841   ClutterInputDevice *device;
842 
843   serial_ids_prop = XInternAtom (meta_clutter_x11_get_default_display (),
844                                  "Wacom Serial IDs", True);
845   if (serial_ids_prop == None)
846     return;
847 
848   device = g_hash_table_lookup (seat_x11->devices_by_id,
849                                 GINT_TO_POINTER (xev->deviceid));
850   if (!device)
851     return;
852 
853   if (xev->property == serial_ids_prop)
854     {
855       ClutterInputDeviceTool *tool = NULL;
856       ClutterInputDeviceToolType type;
857       MetaInputSettings *input_settings;
858       int serial_id;
859 
860       serial_id = device_get_tool_serial (device);
861 
862       if (serial_id != 0)
863         {
864           tool = g_hash_table_lookup (seat_x11->tools_by_serial,
865                                       GUINT_TO_POINTER (serial_id));
866           if (!tool)
867             {
868               type = clutter_input_device_get_device_type (device) == CLUTTER_ERASER_DEVICE ?
869                 CLUTTER_INPUT_DEVICE_TOOL_ERASER : CLUTTER_INPUT_DEVICE_TOOL_PEN;
870               tool = meta_input_device_tool_x11_new (serial_id, type);
871               g_hash_table_insert (seat_x11->tools_by_serial,
872                                    GUINT_TO_POINTER (serial_id),
873                                    tool);
874             }
875         }
876 
877       meta_input_device_x11_update_tool (device, tool);
878       input_settings = meta_backend_get_input_settings (meta_get_backend ());
879       meta_input_settings_notify_tool_change (input_settings, device, tool);
880     }
881 }
882 
883 static void
emulate_motion(MetaSeatX11 * seat_x11,double x,double y)884 emulate_motion (MetaSeatX11 *seat_x11,
885                 double       x,
886                 double       y)
887 {
888   ClutterInputDevice *pointer;
889   ClutterEvent *event;
890   ClutterStage *stage;
891 
892   pointer = clutter_seat_get_pointer (CLUTTER_SEAT (seat_x11));
893   stage = CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ()));
894 
895   event = clutter_event_new (CLUTTER_MOTION);
896   clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC);
897   clutter_event_set_coords (event, x, y);
898   clutter_event_set_device (event, pointer);
899   clutter_event_set_source_device (event, NULL);
900   clutter_event_set_stage (event, stage);
901 
902   clutter_event_put (event);
903   clutter_event_free (event);
904 }
905 
906 static void
translate_raw_event(MetaSeatX11 * seat_x11,XEvent * xevent)907 translate_raw_event (MetaSeatX11 *seat_x11,
908                      XEvent      *xevent)
909 {
910   ClutterInputDevice *device;
911   XGenericEventCookie *cookie;
912   XIEvent *xi_event;
913   XIRawEvent *xev;
914   float x,y;
915 
916   cookie = &xevent->xcookie;
917   xi_event = (XIEvent *) cookie->data;
918   xev = (XIRawEvent *) xi_event;
919 
920   device = g_hash_table_lookup (seat_x11->devices_by_id,
921                                 GINT_TO_POINTER (xev->deviceid));
922   if (device == NULL)
923     return;
924 
925   switch (cookie->evtype)
926     {
927     case XI_RawMotion:
928       g_debug ("raw motion: device:%d '%s'",
929                meta_input_device_x11_get_device_id (device),
930                clutter_input_device_get_device_name (device));
931 
932       /* We don't get actual pointer location with raw events, and we cannot
933        * rely on `clutter_input_device_get_coords()` either because of
934        * unreparented toplevels (like all client-side decoration windows),
935        * so we need to explicitly query the pointer here...
936        */
937       if (meta_input_device_x11_get_pointer_location (device, &x, &y))
938         {
939           if (_clutter_is_input_pointer_a11y_enabled (device))
940             _clutter_input_pointer_a11y_on_motion_event (device, x, y);
941           if (!seat_x11->has_pointer_focus)
942             emulate_motion (seat_x11, x, y);
943         }
944       break;
945     case XI_RawButtonPress:
946     case XI_RawButtonRelease:
947       g_debug ("raw button %s: device:%d '%s' button %i",
948                cookie->evtype == XI_RawButtonPress
949                ? "press  "
950                : "release",
951                meta_input_device_x11_get_device_id (device),
952                clutter_input_device_get_device_name (device),
953                xev->detail);
954       if (_clutter_is_input_pointer_a11y_enabled (device))
955         {
956           _clutter_input_pointer_a11y_on_button_event (device,
957                                                        xev->detail,
958                                                        (cookie->evtype == XI_RawButtonPress));
959         }
960       break;
961     }
962 }
963 
964 static gboolean
translate_pad_axis(ClutterInputDevice * device,XIValuatorState * valuators,ClutterEventType * evtype,uint32_t * number,double * value)965 translate_pad_axis (ClutterInputDevice *device,
966                     XIValuatorState    *valuators,
967                     ClutterEventType   *evtype,
968                     uint32_t           *number,
969                     double             *value)
970 {
971   double *values;
972   int i;
973 
974   values = valuators->values;
975 
976   for (i = PAD_AXIS_FIRST; i < valuators->mask_len * 8; i++)
977     {
978       double val;
979       uint32_t axis_number = 0;
980 
981       if (!XIMaskIsSet (valuators->mask, i))
982         continue;
983 
984       val = *values++;
985       if (val <= 0)
986         continue;
987 
988       meta_input_device_x11_translate_axis (device, i, val, value);
989 
990       if (i == PAD_AXIS_RING1 || i == PAD_AXIS_RING2)
991         {
992           *evtype = CLUTTER_PAD_RING;
993           (*value) *= 360.0;
994         }
995       else if (i == PAD_AXIS_STRIP1 || i == PAD_AXIS_STRIP2)
996         {
997           *evtype = CLUTTER_PAD_STRIP;
998         }
999       else
1000         continue;
1001 
1002       if (i == PAD_AXIS_STRIP2 || i == PAD_AXIS_RING2)
1003         axis_number++;
1004 
1005       *number = axis_number;
1006       return TRUE;
1007     }
1008 
1009   return FALSE;
1010 }
1011 
1012 static gboolean
translate_pad_event(ClutterEvent * event,XIDeviceEvent * xev,ClutterInputDevice * device)1013 translate_pad_event (ClutterEvent       *event,
1014                      XIDeviceEvent      *xev,
1015                      ClutterInputDevice *device)
1016 {
1017   double value;
1018   uint32_t number, mode = 0;
1019 
1020   if (!translate_pad_axis (device, &xev->valuators,
1021                            &event->any.type,
1022                            &number, &value))
1023     return FALSE;
1024 
1025   /* When touching a ring/strip a first XI_Motion event
1026    * is generated. Use it to reset the pad state, so
1027    * later events actually have a directionality.
1028    */
1029   if (xev->evtype == XI_Motion)
1030     value = -1;
1031 
1032 #ifdef HAVE_LIBWACOM
1033   mode = meta_input_device_x11_get_pad_group_mode (device, number);
1034 #endif
1035 
1036   if (event->any.type == CLUTTER_PAD_RING)
1037     {
1038       event->pad_ring.ring_number = number;
1039       event->pad_ring.angle = value;
1040       event->pad_ring.mode = mode;
1041     }
1042   else
1043     {
1044       event->pad_strip.strip_number = number;
1045       event->pad_strip.value = value;
1046       event->pad_strip.mode = mode;
1047     }
1048 
1049   event->any.time = xev->time;
1050   clutter_event_set_device (event, device);
1051   clutter_event_set_source_device (event, device);
1052 
1053   g_debug ("%s: win:0x%x, device:%d '%s', time:%d "
1054            "(value:%f)",
1055            event->any.type == CLUTTER_PAD_RING
1056            ? "pad ring  "
1057            : "pad strip",
1058            (unsigned int) xev->event,
1059            meta_input_device_x11_get_device_id (device),
1060            clutter_input_device_get_device_name (device),
1061            event->any.time, value);
1062 
1063   return TRUE;
1064 }
1065 
1066 static ClutterStage *
get_event_stage(MetaSeatX11 * seat_x11,XIEvent * xi_event)1067 get_event_stage (MetaSeatX11 *seat_x11,
1068                  XIEvent     *xi_event)
1069 {
1070   Window xwindow = None;
1071 
1072   switch (xi_event->evtype)
1073     {
1074     case XI_KeyPress:
1075     case XI_KeyRelease:
1076     case XI_ButtonPress:
1077     case XI_ButtonRelease:
1078     case XI_Motion:
1079     case XI_TouchBegin:
1080     case XI_TouchUpdate:
1081     case XI_TouchEnd:
1082       {
1083         XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
1084 
1085         xwindow = xev->event;
1086       }
1087       break;
1088 
1089     case XI_Enter:
1090     case XI_Leave:
1091     case XI_FocusIn:
1092     case XI_FocusOut:
1093       {
1094         XIEnterEvent *xev = (XIEnterEvent *) xi_event;
1095 
1096         xwindow = xev->event;
1097       }
1098       break;
1099 
1100     case XI_HierarchyChanged:
1101       return CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ()));
1102 
1103     default:
1104       break;
1105     }
1106 
1107   if (xwindow == None)
1108     return NULL;
1109 
1110   return meta_x11_get_stage_from_window (xwindow);
1111 }
1112 
1113 /*
1114  * print_key_sym: Translate a symbol to its printable form if any
1115  * @symbol: the symbol to translate
1116  * @buffer: the buffer where to put the translated string
1117  * @len: size of the buffer
1118  *
1119  * Translates @symbol into a printable representation in @buffer, if possible.
1120  *
1121  * Return value: The number of bytes of the translated string, 0 if the
1122  *               symbol can't be printed
1123  *
1124  * Note: The code is derived from libX11's src/KeyBind.c
1125  *       Copyright 1985, 1987, 1998  The Open Group
1126  *
1127  * Note: This code works for Latin-1 symbols. clutter_keysym_to_unicode()
1128  *       does the work for the other keysyms.
1129  */
1130 static int
print_keysym(uint32_t symbol,char * buffer,int len)1131 print_keysym (uint32_t symbol,
1132               char    *buffer,
1133               int      len)
1134 {
1135   unsigned long high_bytes;
1136   unsigned char c;
1137 
1138   high_bytes = symbol >> 8;
1139   if (!(len &&
1140         ((high_bytes == 0) ||
1141          ((high_bytes == 0xFF) &&
1142           (((symbol >= CLUTTER_KEY_BackSpace) &&
1143             (symbol <= CLUTTER_KEY_Clear)) ||
1144            (symbol == CLUTTER_KEY_Return) ||
1145            (symbol == CLUTTER_KEY_Escape) ||
1146            (symbol == CLUTTER_KEY_KP_Space) ||
1147            (symbol == CLUTTER_KEY_KP_Tab) ||
1148            (symbol == CLUTTER_KEY_KP_Enter) ||
1149            ((symbol >= CLUTTER_KEY_KP_Multiply) &&
1150             (symbol <= CLUTTER_KEY_KP_9)) ||
1151            (symbol == CLUTTER_KEY_KP_Equal) ||
1152            (symbol == CLUTTER_KEY_Delete))))))
1153     return 0;
1154 
1155   /* if X keysym, convert to ascii by grabbing low 7 bits */
1156   if (symbol == CLUTTER_KEY_KP_Space)
1157     c = CLUTTER_KEY_space & 0x7F; /* patch encoding botch */
1158   else if (high_bytes == 0xFF)
1159     c = symbol & 0x7F;
1160   else
1161     c = symbol & 0xFF;
1162 
1163   buffer[0] = c;
1164   return 1;
1165 }
1166 
1167 static double *
translate_axes(ClutterInputDevice * device,double x,double y,XIValuatorState * valuators)1168 translate_axes (ClutterInputDevice *device,
1169                 double              x,
1170                 double              y,
1171                 XIValuatorState    *valuators)
1172 {
1173   uint32_t i;
1174   double *retval;
1175   double *values;
1176 
1177   retval = g_new0 (double, CLUTTER_INPUT_AXIS_LAST);
1178   values = valuators->values;
1179 
1180   for (i = 0; i < valuators->mask_len * 8; i++)
1181     {
1182       ClutterInputAxis axis;
1183       double val;
1184 
1185       if (!XIMaskIsSet (valuators->mask, i))
1186         continue;
1187       if (!meta_input_device_x11_get_axis (device, i, &axis))
1188         continue;
1189 
1190       val = *values++;
1191 
1192       switch (axis)
1193         {
1194         case CLUTTER_INPUT_AXIS_X:
1195           retval[axis] = x;
1196           break;
1197 
1198         case CLUTTER_INPUT_AXIS_Y:
1199           retval[axis] = y;
1200           break;
1201 
1202         default:
1203           meta_input_device_x11_translate_axis (device, i, val, &retval[axis]);
1204           break;
1205         }
1206     }
1207 
1208   return retval;
1209 }
1210 
1211 static double
scroll_valuators_changed(ClutterInputDevice * device,XIValuatorState * valuators,double * dx_p,double * dy_p)1212 scroll_valuators_changed (ClutterInputDevice *device,
1213                           XIValuatorState    *valuators,
1214                           double             *dx_p,
1215                           double             *dy_p)
1216 {
1217   gboolean retval = FALSE;
1218   uint32_t n_axes, n_val, i;
1219   double *values;
1220 
1221   n_axes = meta_input_device_x11_get_n_axes (device);
1222   values = valuators->values;
1223 
1224   *dx_p = *dy_p = 0.0;
1225 
1226   n_val = 0;
1227 
1228   for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
1229     {
1230       ClutterScrollDirection direction;
1231       double delta;
1232 
1233       if (!XIMaskIsSet (valuators->mask, i))
1234         continue;
1235 
1236       if (meta_input_device_x11_get_scroll_delta (device, i,
1237                                                   values[n_val],
1238                                                   &direction,
1239                                                   &delta))
1240         {
1241           retval = TRUE;
1242 
1243           if (direction == CLUTTER_SCROLL_UP ||
1244               direction == CLUTTER_SCROLL_DOWN)
1245             *dy_p = delta;
1246           else
1247             *dx_p = delta;
1248         }
1249 
1250       n_val += 1;
1251     }
1252 
1253   return retval;
1254 }
1255 
1256 static void
translate_coords(MetaStageX11 * stage_x11,double event_x,double event_y,float * x_out,float * y_out)1257 translate_coords (MetaStageX11 *stage_x11,
1258                   double        event_x,
1259                   double        event_y,
1260                   float        *x_out,
1261                   float        *y_out)
1262 {
1263   MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_x11);
1264   ClutterActor *stage = CLUTTER_ACTOR (stage_impl->wrapper);
1265   float stage_width;
1266   float stage_height;
1267 
1268   clutter_actor_get_size (stage, &stage_width, &stage_height);
1269 
1270   *x_out = CLAMP (event_x, 0, stage_width);
1271   *y_out = CLAMP (event_y, 0, stage_height);
1272 }
1273 
1274 static void
on_keymap_state_change(MetaKeymapX11 * keymap_x11,gpointer data)1275 on_keymap_state_change (MetaKeymapX11 *keymap_x11,
1276                         gpointer       data)
1277 {
1278   ClutterSeat *seat = data;
1279   MetaInputSettings *input_settings;
1280   MetaKbdA11ySettings kbd_a11y_settings;
1281 
1282   /* On keymaps state change, just reapply the current settings, it'll
1283    * take care of enabling/disabling mousekeys based on NumLock state.
1284    */
1285   input_settings = meta_backend_get_input_settings (meta_get_backend ());
1286   meta_input_settings_get_kbd_a11y_settings (input_settings, &kbd_a11y_settings);
1287   meta_seat_x11_apply_kbd_a11y_settings (seat, &kbd_a11y_settings);
1288 }
1289 
1290 static void
meta_seat_x11_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1291 meta_seat_x11_set_property (GObject      *object,
1292                             guint         prop_id,
1293                             const GValue *value,
1294                             GParamSpec   *pspec)
1295 {
1296   MetaSeatX11 *seat_x11 = META_SEAT_X11 (object);
1297 
1298   switch (prop_id)
1299     {
1300     case PROP_OPCODE:
1301       seat_x11->opcode = g_value_get_int (value);
1302       break;
1303     case PROP_POINTER_ID:
1304       seat_x11->pointer_id = g_value_get_int (value);
1305       break;
1306     case PROP_KEYBOARD_ID:
1307       seat_x11->keyboard_id = g_value_get_int (value);
1308       break;
1309     case PROP_TOUCH_MODE:
1310     default:
1311       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1312     }
1313 }
1314 
1315 static void
meta_seat_x11_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1316 meta_seat_x11_get_property (GObject    *object,
1317                             guint       prop_id,
1318                             GValue     *value,
1319                             GParamSpec *pspec)
1320 {
1321   MetaSeatX11 *seat_x11 = META_SEAT_X11 (object);
1322 
1323   switch (prop_id)
1324     {
1325     case PROP_OPCODE:
1326       g_value_set_int (value, seat_x11->opcode);
1327       break;
1328     case PROP_POINTER_ID:
1329       g_value_set_int (value, seat_x11->pointer_id);
1330       break;
1331     case PROP_KEYBOARD_ID:
1332       g_value_set_int (value, seat_x11->keyboard_id);
1333       break;
1334     case PROP_TOUCH_MODE:
1335       g_value_set_boolean (value, seat_x11->touch_mode);
1336       break;
1337     default:
1338       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1339     }
1340 }
1341 
1342 void
meta_seat_x11_notify_devices(MetaSeatX11 * seat_x11,ClutterStage * stage)1343 meta_seat_x11_notify_devices (MetaSeatX11  *seat_x11,
1344 			      ClutterStage *stage)
1345 {
1346   GHashTableIter iter;
1347   ClutterInputDevice *device;
1348 
1349   g_hash_table_iter_init (&iter, seat_x11->devices_by_id);
1350   while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device))
1351     {
1352       ClutterEvent *event;
1353 
1354       event = clutter_event_new (CLUTTER_DEVICE_ADDED);
1355       clutter_event_set_device (event, device);
1356       clutter_event_set_stage (event, stage);
1357       clutter_event_put (event);
1358       clutter_event_free (event);
1359     }
1360 }
1361 
1362 static void
meta_seat_x11_constructed(GObject * object)1363 meta_seat_x11_constructed (GObject *object)
1364 {
1365   MetaSeatX11 *seat_x11 = META_SEAT_X11 (object);
1366   ClutterBackend *backend = clutter_get_default_backend ();
1367   XIDeviceInfo *info;
1368   XIEventMask event_mask;
1369   unsigned char mask[XIMaskLen(XI_LASTEVENT)] = { 0, };
1370   int n_devices, i;
1371   Display *xdisplay;
1372 
1373   xdisplay = meta_clutter_x11_get_default_display ();
1374 
1375   info = XIQueryDevice (xdisplay, XIAllDevices, &n_devices);
1376 
1377   for (i = 0; i < n_devices; i++)
1378     {
1379       XIDeviceInfo *xi_device = &info[i];
1380 
1381       if (!xi_device->enabled)
1382         continue;
1383 
1384       add_device (seat_x11, backend, xi_device);
1385     }
1386 
1387   XIFreeDeviceInfo (info);
1388 
1389   XISetMask (mask, XI_HierarchyChanged);
1390   XISetMask (mask, XI_DeviceChanged);
1391   XISetMask (mask, XI_PropertyEvent);
1392 
1393   event_mask.deviceid = XIAllDevices;
1394   event_mask.mask_len = sizeof (mask);
1395   event_mask.mask = mask;
1396 
1397   XISelectEvents (xdisplay, meta_clutter_x11_get_root_window (),
1398                   &event_mask, 1);
1399 
1400   memset(mask, 0, sizeof (mask));
1401   XISetMask (mask, XI_RawMotion);
1402   XISetMask (mask, XI_RawButtonPress);
1403   XISetMask (mask, XI_RawButtonRelease);
1404 
1405   event_mask.deviceid = XIAllMasterDevices;
1406   event_mask.mask_len = sizeof (mask);
1407   event_mask.mask = mask;
1408 
1409   XISelectEvents (xdisplay, meta_clutter_x11_get_root_window (),
1410                   &event_mask, 1);
1411 
1412   XSync (xdisplay, False);
1413 
1414   seat_x11->keymap = g_object_new (META_TYPE_KEYMAP_X11,
1415                                    "backend", backend,
1416                                    NULL);
1417   g_signal_connect (seat_x11->keymap,
1418                     "state-changed",
1419                     G_CALLBACK (on_keymap_state_change),
1420                     seat_x11);
1421 
1422   meta_seat_x11_a11y_init (CLUTTER_SEAT (seat_x11));
1423 
1424   if (G_OBJECT_CLASS (meta_seat_x11_parent_class)->constructed)
1425     G_OBJECT_CLASS (meta_seat_x11_parent_class)->constructed (object);
1426 }
1427 
1428 static void
meta_seat_x11_finalize(GObject * object)1429 meta_seat_x11_finalize (GObject *object)
1430 {
1431   MetaSeatX11 *seat_x11 = META_SEAT_X11 (object);
1432 
1433   g_hash_table_unref (seat_x11->devices_by_id);
1434   g_hash_table_unref (seat_x11->tools_by_serial);
1435   g_hash_table_unref (seat_x11->touch_coords);
1436   g_list_free (seat_x11->devices);
1437 
1438   G_OBJECT_CLASS (meta_seat_x11_parent_class)->finalize (object);
1439 }
1440 
1441 static ClutterInputDevice *
meta_seat_x11_get_pointer(ClutterSeat * seat)1442 meta_seat_x11_get_pointer (ClutterSeat *seat)
1443 {
1444   MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
1445 
1446   return seat_x11->core_pointer;
1447 }
1448 
1449 static ClutterInputDevice *
meta_seat_x11_get_keyboard(ClutterSeat * seat)1450 meta_seat_x11_get_keyboard (ClutterSeat *seat)
1451 {
1452   MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
1453 
1454   return seat_x11->core_keyboard;
1455 }
1456 
1457 static const GList *
meta_seat_x11_peek_devices(ClutterSeat * seat)1458 meta_seat_x11_peek_devices (ClutterSeat *seat)
1459 {
1460   MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
1461 
1462   return (const GList *) seat_x11->devices;
1463 }
1464 
1465 static void
meta_seat_x11_bell_notify(ClutterSeat * seat)1466 meta_seat_x11_bell_notify (ClutterSeat *seat)
1467 {
1468   MetaDisplay *display = meta_get_display ();
1469 
1470   meta_bell_notify (display, NULL);
1471 }
1472 
1473 static ClutterKeymap *
meta_seat_x11_get_keymap(ClutterSeat * seat)1474 meta_seat_x11_get_keymap (ClutterSeat *seat)
1475 {
1476   return CLUTTER_KEYMAP (META_SEAT_X11 (seat)->keymap);
1477 }
1478 
1479 static ClutterVirtualInputDevice *
meta_seat_x11_create_virtual_device(ClutterSeat * seat,ClutterInputDeviceType device_type)1480 meta_seat_x11_create_virtual_device (ClutterSeat            *seat,
1481                                      ClutterInputDeviceType  device_type)
1482 {
1483   return g_object_new (META_TYPE_VIRTUAL_INPUT_DEVICE_X11,
1484                        "seat", seat,
1485                        "device-type", device_type,
1486                        NULL);
1487 }
1488 
1489 static ClutterVirtualDeviceType
meta_seat_x11_get_supported_virtual_device_types(ClutterSeat * seat)1490 meta_seat_x11_get_supported_virtual_device_types (ClutterSeat *seat)
1491 {
1492   return (CLUTTER_VIRTUAL_DEVICE_TYPE_KEYBOARD |
1493           CLUTTER_VIRTUAL_DEVICE_TYPE_POINTER);
1494 }
1495 
1496 static void
meta_seat_x11_warp_pointer(ClutterSeat * seat,int x,int y)1497 meta_seat_x11_warp_pointer (ClutterSeat *seat,
1498                             int          x,
1499                             int          y)
1500 {
1501   MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
1502 
1503   meta_clutter_x11_trap_x_errors ();
1504   XIWarpPointer (meta_clutter_x11_get_default_display (),
1505                  seat_x11->pointer_id,
1506                  None,
1507                  meta_clutter_x11_get_root_window (),
1508                  0, 0, 0, 0,
1509                  x, y);
1510   meta_clutter_x11_untrap_x_errors ();
1511 }
1512 
1513 static uint32_t
translate_state(XIButtonState * button_state,XIModifierState * modifier_state,XIGroupState * group_state)1514 translate_state (XIButtonState   *button_state,
1515                  XIModifierState *modifier_state,
1516                  XIGroupState    *group_state)
1517 {
1518   uint32_t state = 0;
1519   int i;
1520 
1521   if (modifier_state)
1522     state |= modifier_state->effective;
1523 
1524   if (button_state)
1525     {
1526       for (i = 1; i < button_state->mask_len * 8; i++)
1527         {
1528           if (!XIMaskIsSet (button_state->mask, i))
1529             continue;
1530 
1531           switch (i)
1532             {
1533             case 1:
1534               state |= CLUTTER_BUTTON1_MASK;
1535               break;
1536             case 2:
1537               state |= CLUTTER_BUTTON2_MASK;
1538               break;
1539             case 3:
1540               state |= CLUTTER_BUTTON3_MASK;
1541               break;
1542             case 8:
1543               state |= CLUTTER_BUTTON4_MASK;
1544               break;
1545             case 9:
1546               state |= CLUTTER_BUTTON5_MASK;
1547               break;
1548             default:
1549               break;
1550             }
1551         }
1552     }
1553 
1554   if (group_state)
1555     state |= XkbBuildCoreState (0, group_state->effective);
1556 
1557   return state;
1558 }
1559 
1560 static gboolean
meta_seat_x11_query_state(ClutterSeat * seat,ClutterInputDevice * device,ClutterEventSequence * sequence,graphene_point_t * coords,ClutterModifierType * modifiers)1561 meta_seat_x11_query_state (ClutterSeat          *seat,
1562                            ClutterInputDevice   *device,
1563                            ClutterEventSequence *sequence,
1564                            graphene_point_t     *coords,
1565                            ClutterModifierType  *modifiers)
1566 {
1567   MetaBackendX11 *backend_x11 = META_BACKEND_X11 (meta_get_backend ());
1568   MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
1569   Window root_ret, child_ret;
1570   double root_x, root_y, win_x, win_y;
1571   XIButtonState button_state = { 0 };
1572   XIModifierState modifier_state;
1573   XIGroupState group_state;
1574 
1575   meta_clutter_x11_trap_x_errors ();
1576   XIQueryPointer (meta_clutter_x11_get_default_display (),
1577                   seat_x11->pointer_id,
1578                   meta_backend_x11_get_xwindow (backend_x11),
1579                   &root_ret, &child_ret,
1580                   &root_x, &root_y, &win_x, &win_y,
1581                   &button_state, &modifier_state, &group_state);
1582   if (meta_clutter_x11_untrap_x_errors ())
1583     {
1584       g_free (button_state.mask);
1585       return FALSE;
1586     }
1587 
1588   if (sequence)
1589     {
1590       MetaTouchInfo *touch_info;
1591 
1592       touch_info = g_hash_table_lookup (seat_x11->touch_coords, sequence);
1593       if (!touch_info)
1594         {
1595           g_free (button_state.mask);
1596           return FALSE;
1597         }
1598 
1599       if (coords)
1600         {
1601           coords->x = touch_info->x;
1602           coords->y = touch_info->y;
1603         }
1604     }
1605   else
1606     {
1607       if (coords)
1608         {
1609           coords->x = win_x;
1610           coords->y = win_y;
1611         }
1612     }
1613 
1614   if (modifiers)
1615     *modifiers = translate_state (&button_state, &modifier_state, &group_state);
1616 
1617   g_free (button_state.mask);
1618   return TRUE;
1619 }
1620 
1621 static void
meta_seat_x11_update_touchpoint(MetaSeatX11 * seat,ClutterEventSequence * sequence,double x,double y)1622 meta_seat_x11_update_touchpoint (MetaSeatX11          *seat,
1623                                  ClutterEventSequence *sequence,
1624                                  double                x,
1625                                  double                y)
1626 {
1627   MetaTouchInfo *touch_info;
1628 
1629   touch_info = g_hash_table_lookup (seat->touch_coords, sequence);
1630   if (!touch_info)
1631     {
1632       touch_info = g_new0 (MetaTouchInfo, 1);
1633       touch_info->sequence = sequence;
1634       g_hash_table_insert (seat->touch_coords, sequence, touch_info);
1635     }
1636 
1637   touch_info->x = x;
1638   touch_info->y = y;
1639 }
1640 
1641 static void
meta_seat_x11_remove_touchpoint(MetaSeatX11 * seat,ClutterEventSequence * sequence)1642 meta_seat_x11_remove_touchpoint (MetaSeatX11          *seat,
1643                                  ClutterEventSequence *sequence)
1644 {
1645   g_hash_table_remove (seat->touch_coords, sequence);
1646 }
1647 
1648 static void
meta_touch_info_free(MetaTouchInfo * touch_info)1649 meta_touch_info_free (MetaTouchInfo *touch_info)
1650 {
1651   g_free (touch_info);
1652 }
1653 
1654 static void
meta_seat_x11_class_init(MetaSeatX11Class * klass)1655 meta_seat_x11_class_init (MetaSeatX11Class *klass)
1656 {
1657   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1658   ClutterSeatClass *seat_class = CLUTTER_SEAT_CLASS (klass);
1659 
1660   object_class->set_property = meta_seat_x11_set_property;
1661   object_class->get_property = meta_seat_x11_get_property;
1662   object_class->constructed = meta_seat_x11_constructed;
1663   object_class->finalize = meta_seat_x11_finalize;
1664 
1665   seat_class->get_pointer = meta_seat_x11_get_pointer;
1666   seat_class->get_keyboard = meta_seat_x11_get_keyboard;
1667   seat_class->peek_devices = meta_seat_x11_peek_devices;
1668   seat_class->bell_notify = meta_seat_x11_bell_notify;
1669   seat_class->get_keymap = meta_seat_x11_get_keymap;
1670   seat_class->create_virtual_device = meta_seat_x11_create_virtual_device;
1671   seat_class->get_supported_virtual_device_types = meta_seat_x11_get_supported_virtual_device_types;
1672   seat_class->warp_pointer = meta_seat_x11_warp_pointer;
1673   seat_class->handle_event_post = meta_seat_x11_handle_event_post;
1674   seat_class->query_state = meta_seat_x11_query_state;
1675 
1676   props[PROP_OPCODE] =
1677     g_param_spec_int ("opcode",
1678                       "Opcode",
1679                       "Opcode",
1680                       0, G_MAXINT, 0,
1681                       G_PARAM_READWRITE |
1682                       G_PARAM_CONSTRUCT_ONLY);
1683   props[PROP_POINTER_ID] =
1684     g_param_spec_int ("pointer-id",
1685                       "Pointer ID",
1686                       "Pointer ID",
1687                       2, G_MAXINT, 2,
1688                       G_PARAM_READWRITE |
1689                       G_PARAM_CONSTRUCT_ONLY);
1690   props[PROP_KEYBOARD_ID] =
1691     g_param_spec_int ("keyboard-id",
1692                       "Keyboard ID",
1693                       "Keyboard ID",
1694                       2, G_MAXINT, 2,
1695                       G_PARAM_READWRITE |
1696                       G_PARAM_CONSTRUCT_ONLY);
1697 
1698   g_object_class_install_properties (object_class, N_PROPS, props);
1699 
1700   g_object_class_override_property (object_class, PROP_TOUCH_MODE,
1701                                     "touch-mode");
1702 }
1703 
1704 static void
meta_seat_x11_init(MetaSeatX11 * seat)1705 meta_seat_x11_init (MetaSeatX11 *seat)
1706 {
1707   seat->devices_by_id = g_hash_table_new_full (NULL, NULL,
1708                                                NULL,
1709                                                (GDestroyNotify) g_object_unref);
1710   seat->tools_by_serial = g_hash_table_new_full (NULL, NULL, NULL,
1711                                                  (GDestroyNotify) g_object_unref);
1712   seat->touch_coords = g_hash_table_new_full (NULL, NULL, NULL,
1713                                               (GDestroyNotify) meta_touch_info_free);
1714 }
1715 
1716 MetaSeatX11 *
meta_seat_x11_new(int opcode,int logical_pointer,int logical_keyboard)1717 meta_seat_x11_new (int opcode,
1718                    int logical_pointer,
1719                    int logical_keyboard)
1720 {
1721   return g_object_new (META_TYPE_SEAT_X11,
1722                        "opcode", opcode,
1723                        "pointer-id", logical_pointer,
1724                        "keyboard-id", logical_keyboard,
1725                        NULL);
1726 }
1727 
1728 static ClutterInputDevice *
get_source_device_checked(MetaSeatX11 * seat,XIDeviceEvent * xev)1729 get_source_device_checked (MetaSeatX11   *seat,
1730                            XIDeviceEvent *xev)
1731 {
1732   ClutterInputDevice *source_device;
1733 
1734   source_device = g_hash_table_lookup (seat->devices_by_id,
1735                                        GINT_TO_POINTER (xev->sourceid));
1736 
1737   if (!source_device)
1738     g_warning ("Impossible to get the source device with id %d for event of "
1739                "type %d", xev->sourceid, xev->evtype);
1740 
1741   return source_device;
1742 }
1743 #ifdef __linux__
1744 static uint32_t
evdev_button_code(uint32_t x_button)1745 evdev_button_code (uint32_t x_button)
1746 {
1747   uint32_t button;
1748 
1749   switch (x_button)
1750     {
1751     case 1:
1752       button = BTN_LEFT;
1753       break;
1754 
1755       /* The evdev input right and middle button numbers are swapped
1756          relative to how Clutter numbers them */
1757     case 2:
1758       button = BTN_MIDDLE;
1759       break;
1760 
1761     case 3:
1762       button = BTN_RIGHT;
1763       break;
1764 
1765     default:
1766       button = x_button + (BTN_LEFT - 1) + 4;
1767       break;
1768     }
1769 
1770   return button;
1771 }
1772 #endif
1773 gboolean
meta_seat_x11_translate_event(MetaSeatX11 * seat,XEvent * xevent,ClutterEvent * event)1774 meta_seat_x11_translate_event (MetaSeatX11  *seat,
1775                                XEvent       *xevent,
1776                                ClutterEvent *event)
1777 {
1778   gboolean retval = FALSE;
1779   ClutterBackend *backend = clutter_get_default_backend ();
1780   ClutterStage *stage = NULL;
1781   MetaStageX11 *stage_x11 = NULL;
1782   ClutterInputDevice *device, *source_device;
1783   XGenericEventCookie *cookie;
1784   XIEvent *xi_event;
1785 
1786   if (meta_keymap_x11_handle_event (seat->keymap, xevent))
1787     return FALSE;
1788 
1789   cookie = &xevent->xcookie;
1790 
1791   if (cookie->type != GenericEvent ||
1792       cookie->extension != seat->opcode)
1793     return FALSE;
1794 
1795   xi_event = (XIEvent *) cookie->data;
1796 
1797   if (!xi_event)
1798     return FALSE;
1799 
1800   if (cookie->evtype == XI_RawMotion ||
1801       cookie->evtype == XI_RawButtonPress ||
1802       cookie->evtype == XI_RawButtonRelease)
1803     {
1804       translate_raw_event (seat, xevent);
1805       return FALSE;
1806     }
1807 
1808   if (!(xi_event->evtype == XI_DeviceChanged ||
1809         xi_event->evtype == XI_PropertyEvent))
1810     {
1811       stage = get_event_stage (seat, xi_event);
1812       if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
1813         return FALSE;
1814       else
1815         stage_x11 = META_STAGE_X11 (_clutter_stage_get_window (stage));
1816     }
1817 
1818   event->any.stage = stage;
1819 
1820   switch (xi_event->evtype)
1821     {
1822     case XI_HierarchyChanged:
1823       {
1824         XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event;
1825 
1826         retval = translate_hierarchy_event (backend, seat, xev, event);
1827       }
1828       break;
1829 
1830     case XI_DeviceChanged:
1831       {
1832         XIDeviceChangedEvent *xev = (XIDeviceChangedEvent *) xi_event;
1833 
1834         device = g_hash_table_lookup (seat->devices_by_id,
1835                                       GINT_TO_POINTER (xev->deviceid));
1836         source_device = g_hash_table_lookup (seat->devices_by_id,
1837                                              GINT_TO_POINTER (xev->sourceid));
1838         if (device)
1839           {
1840             meta_input_device_x11_reset_axes (device);
1841             translate_device_classes (meta_clutter_x11_get_default_display (),
1842                                       device,
1843                                       xev->classes,
1844                                       xev->num_classes);
1845           }
1846 
1847         if (source_device)
1848           meta_input_device_x11_reset_scroll_info (source_device);
1849       }
1850       retval = FALSE;
1851       break;
1852     case XI_KeyPress:
1853     case XI_KeyRelease:
1854       {
1855         XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
1856         MetaKeymapX11 *keymap_x11 = seat->keymap;
1857         char buffer[7] = { 0, };
1858         gunichar n;
1859 
1860         source_device = get_source_device_checked (seat, xev);
1861         if (!source_device)
1862           return FALSE;
1863 
1864         event->key.type = event->type = (xev->evtype == XI_KeyPress)
1865                                       ? CLUTTER_KEY_PRESS
1866                                       : CLUTTER_KEY_RELEASE;
1867 
1868         if (xev->evtype == XI_KeyPress && xev->flags & XIKeyRepeat)
1869           clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_REPEATED);
1870 
1871         event->key.time = xev->time;
1872         event->key.stage = stage;
1873         meta_input_device_x11_translate_state (event, &xev->mods, &xev->buttons, &xev->group);
1874         event->key.hardware_keycode = xev->detail;
1875 
1876         /* clutter-xkb-utils.c adds a fixed offset of 8 to go into XKB's
1877          * range, so we do the reverse here. */
1878         event->key.evdev_code = event->key.hardware_keycode - 8;
1879 
1880           /* keyval is the key ignoring all modifiers ('1' vs. '!') */
1881         event->key.keyval =
1882           meta_keymap_x11_translate_key_state (keymap_x11,
1883                                                event->key.hardware_keycode,
1884                                                &event->key.modifier_state,
1885                                                NULL);
1886 
1887         clutter_event_set_source_device (event, source_device);
1888 
1889         device = g_hash_table_lookup (seat->devices_by_id,
1890                                       GINT_TO_POINTER (xev->deviceid));
1891         clutter_event_set_device (event, device);
1892 
1893         /* XXX keep this in sync with the evdev device manager */
1894         n = print_keysym (event->key.keyval, buffer, sizeof (buffer));
1895         if (n == 0)
1896           {
1897             /* not printable */
1898             event->key.unicode_value = (gunichar) '\0';
1899           }
1900         else
1901           {
1902             event->key.unicode_value = g_utf8_get_char_validated (buffer, n);
1903             if (event->key.unicode_value == -1 ||
1904                 event->key.unicode_value == -2)
1905               event->key.unicode_value = (gunichar) '\0';
1906           }
1907 
1908         g_debug ("%s: win:0x%x device:%d source:%d, key: %12s (%d)",
1909                  event->any.type == CLUTTER_KEY_PRESS
1910                  ? "key press  "
1911                  : "key release",
1912                  (unsigned int) stage_x11->xwin,
1913                  xev->deviceid,
1914                  xev->sourceid,
1915                  event->key.keyval ? buffer : "(none)",
1916                  event->key.keyval);
1917 
1918         if (xi_event->evtype == XI_KeyPress)
1919           meta_stage_x11_set_user_time (stage_x11, event->key.time);
1920 
1921         retval = TRUE;
1922       }
1923       break;
1924 
1925     case XI_ButtonPress:
1926     case XI_ButtonRelease:
1927       {
1928         XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
1929 
1930         source_device = get_source_device_checked (seat, xev);
1931 	if (!source_device)
1932           return FALSE;
1933 
1934         device = g_hash_table_lookup (seat->devices_by_id,
1935                                       GINT_TO_POINTER (xev->deviceid));
1936 
1937 	if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE)
1938           {
1939             /* We got these events because of the passive button grab */
1940             XIAllowEvents (meta_clutter_x11_get_default_display (),
1941                            xev->sourceid,
1942                            XIAsyncDevice,
1943                            xev->time);
1944 
1945             event->any.stage = stage;
1946 
1947             if (xev->detail >= 4 && xev->detail <= 7)
1948               {
1949                 retval = FALSE;
1950 
1951                 if (xi_event->evtype == XI_ButtonPress &&
1952                     translate_pad_event (event, xev, source_device))
1953                   retval = TRUE;
1954 
1955                 break;
1956               }
1957 
1958             event->any.type =
1959               (xi_event->evtype == XI_ButtonPress) ? CLUTTER_PAD_BUTTON_PRESS
1960                                                    : CLUTTER_PAD_BUTTON_RELEASE;
1961             event->any.time = xev->time;
1962 
1963             /* The 4-7 button range is taken as non-existent on pad devices,
1964              * let the buttons above that take over this range.
1965              */
1966             if (xev->detail > 7)
1967               xev->detail -= 4;
1968 
1969             /* Pad buttons are 0-indexed */
1970             event->pad_button.button = xev->detail - 1;
1971 #ifdef HAVE_LIBWACOM
1972             meta_input_device_x11_update_pad_state (device,
1973                                                     event->pad_button.button,
1974                                                     (xi_event->evtype == XI_ButtonPress),
1975                                                     &event->pad_button.group,
1976                                                     &event->pad_button.mode);
1977 #endif
1978             clutter_event_set_device (event, device);
1979             clutter_event_set_source_device (event, source_device);
1980 
1981             g_debug ("%s: win:0x%x, device:%d '%s', time:%d "
1982                      "(button:%d)",
1983                      event->any.type == CLUTTER_BUTTON_PRESS
1984                      ? "pad button press  "
1985                      : "pad button release",
1986                      (unsigned int) stage_x11->xwin,
1987                      meta_input_device_x11_get_device_id (device),
1988                      clutter_input_device_get_device_name (device),
1989                      event->any.time,
1990                      event->pad_button.button);
1991             retval = TRUE;
1992             break;
1993           }
1994 
1995         switch (xev->detail)
1996           {
1997           case 4:
1998           case 5:
1999           case 6:
2000           case 7:
2001             /* we only generate Scroll events on ButtonPress */
2002             if (xi_event->evtype == XI_ButtonRelease)
2003               return FALSE;
2004 
2005             event->scroll.type = event->type = CLUTTER_SCROLL;
2006 
2007             if (xev->detail == 4)
2008               event->scroll.direction = CLUTTER_SCROLL_UP;
2009             else if (xev->detail == 5)
2010               event->scroll.direction = CLUTTER_SCROLL_DOWN;
2011             else if (xev->detail == 6)
2012               event->scroll.direction = CLUTTER_SCROLL_LEFT;
2013             else
2014               event->scroll.direction = CLUTTER_SCROLL_RIGHT;
2015 
2016             event->scroll.stage = stage;
2017 
2018             event->scroll.time = xev->time;
2019             translate_coords (stage_x11, xev->event_x, xev->event_y, &event->scroll.x, &event->scroll.y);
2020             meta_input_device_x11_translate_state (event,
2021                                                    &xev->mods,
2022                                                    &xev->buttons,
2023                                                    &xev->group);
2024 
2025             clutter_event_set_source_device (event, source_device);
2026             clutter_event_set_device (event, device);
2027 
2028             event->scroll.axes = translate_axes (event->scroll.device,
2029                                                  event->scroll.x,
2030                                                  event->scroll.y,
2031                                                  &xev->valuators);
2032             g_debug ("scroll: win:0x%x, device:%d '%s', time:%d "
2033                      "(direction:%s, "
2034                      "x:%.2f, y:%.2f, "
2035                      "emulated:%s)",
2036                      (unsigned int) stage_x11->xwin,
2037                      meta_input_device_x11_get_device_id (device),
2038                      clutter_input_device_get_device_name (device),
2039                      event->any.time,
2040                      event->scroll.direction == CLUTTER_SCROLL_UP ? "up" :
2041                      event->scroll.direction == CLUTTER_SCROLL_DOWN ? "down" :
2042                      event->scroll.direction == CLUTTER_SCROLL_LEFT ? "left" :
2043                      event->scroll.direction == CLUTTER_SCROLL_RIGHT ? "right" :
2044                      "invalid",
2045                      event->scroll.x,
2046                      event->scroll.y,
2047                      (xev->flags & XIPointerEmulated) ? "yes" : "no");
2048             break;
2049 
2050           default:
2051             event->button.type = event->type =
2052               (xi_event->evtype == XI_ButtonPress) ? CLUTTER_BUTTON_PRESS
2053                                                    : CLUTTER_BUTTON_RELEASE;
2054 
2055             event->button.stage = stage;
2056 
2057             event->button.time = xev->time;
2058             translate_coords (stage_x11, xev->event_x, xev->event_y, &event->button.x, &event->button.y);
2059             event->button.button = xev->detail;
2060 #ifdef __linux__
2061             event->button.evdev_code = evdev_button_code (xev->detail);
2062 #endif
2063             meta_input_device_x11_translate_state (event,
2064                                                    &xev->mods,
2065                                                    &xev->buttons,
2066                                                    &xev->group);
2067 
2068             clutter_event_set_source_device (event, source_device);
2069             clutter_event_set_device (event, device);
2070             clutter_event_set_device_tool (event,
2071                                            meta_input_device_x11_get_current_tool (source_device));
2072 
2073             event->button.axes = translate_axes (event->button.device,
2074                                                  event->button.x,
2075                                                  event->button.y,
2076                                                  &xev->valuators);
2077             g_debug ("%s: win:0x%x, device:%d '%s', time:%d "
2078                      "(button:%d, "
2079                      "x:%.2f, y:%.2f, "
2080                      "axes:%s, "
2081                      "emulated:%s)",
2082                      event->any.type == CLUTTER_BUTTON_PRESS
2083                      ? "button press  "
2084                      : "button release",
2085                      (unsigned int) stage_x11->xwin,
2086                      meta_input_device_x11_get_device_id (device),
2087                      clutter_input_device_get_device_name (device),
2088                      event->any.time,
2089                      event->button.button,
2090                      event->button.x,
2091                      event->button.y,
2092                      event->button.axes != NULL ? "yes" : "no",
2093                      (xev->flags & XIPointerEmulated) ? "yes" : "no");
2094             break;
2095           }
2096 
2097         if (xev->flags & XIPointerEmulated)
2098           _clutter_event_set_pointer_emulated (event, TRUE);
2099 
2100         if (xi_event->evtype == XI_ButtonPress)
2101           meta_stage_x11_set_user_time (stage_x11, event->button.time);
2102 
2103         retval = TRUE;
2104       }
2105       break;
2106 
2107     case XI_Motion:
2108       {
2109         XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
2110         double delta_x, delta_y;
2111 
2112         source_device = get_source_device_checked (seat, xev);
2113         if (!source_device)
2114           return FALSE;
2115 
2116         device = g_hash_table_lookup (seat->devices_by_id,
2117                                       GINT_TO_POINTER (xev->deviceid));
2118 
2119         if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE)
2120           {
2121             event->any.stage = stage;
2122 
2123             if (translate_pad_event (event, xev, source_device))
2124               retval = TRUE;
2125             break;
2126           }
2127 
2128         if (scroll_valuators_changed (source_device,
2129                                       &xev->valuators,
2130                                       &delta_x, &delta_y))
2131           {
2132             event->scroll.type = event->type = CLUTTER_SCROLL;
2133             event->scroll.direction = CLUTTER_SCROLL_SMOOTH;
2134 
2135             event->scroll.stage = stage;
2136             event->scroll.time = xev->time;
2137             translate_coords (stage_x11, xev->event_x, xev->event_y, &event->scroll.x, &event->scroll.y);
2138             meta_input_device_x11_translate_state (event,
2139                                                    &xev->mods,
2140                                                    &xev->buttons,
2141                                                    &xev->group);
2142 
2143             clutter_event_set_scroll_delta (event, delta_x, delta_y);
2144             clutter_event_set_source_device (event, source_device);
2145             clutter_event_set_device (event, device);
2146 
2147             g_debug ("smooth scroll: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, delta:%f, %f)",
2148                      (unsigned int) stage_x11->xwin,
2149                      meta_input_device_x11_get_device_id (event->scroll.device),
2150                      clutter_input_device_get_device_name (event->scroll.device),
2151                      event->scroll.x,
2152                      event->scroll.y,
2153                      delta_x, delta_y);
2154 
2155             retval = TRUE;
2156             break;
2157           }
2158 
2159         event->motion.type = event->type = CLUTTER_MOTION;
2160 
2161         event->motion.stage = stage;
2162 
2163         event->motion.time = xev->time;
2164         translate_coords (stage_x11, xev->event_x, xev->event_y, &event->motion.x, &event->motion.y);
2165         meta_input_device_x11_translate_state (event,
2166                                                &xev->mods,
2167                                                &xev->buttons,
2168                                                &xev->group);
2169 
2170         clutter_event_set_source_device (event, source_device);
2171         clutter_event_set_device (event, device);
2172         clutter_event_set_device_tool (event,
2173                                        meta_input_device_x11_get_current_tool (source_device));
2174 
2175         event->motion.axes = translate_axes (event->motion.device,
2176                                              event->motion.x,
2177                                              event->motion.y,
2178                                              &xev->valuators);
2179 
2180         if (xev->flags & XIPointerEmulated)
2181           _clutter_event_set_pointer_emulated (event, TRUE);
2182 
2183         g_debug ("motion: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, axes:%s)",
2184                  (unsigned int) stage_x11->xwin,
2185                  meta_input_device_x11_get_device_id (event->motion.device),
2186                  clutter_input_device_get_device_name (event->motion.device),
2187                  event->motion.x,
2188                  event->motion.y,
2189                  event->motion.axes != NULL ? "yes" : "no");
2190 
2191         retval = TRUE;
2192       }
2193       break;
2194 
2195     case XI_TouchBegin:
2196       {
2197         XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
2198         device = g_hash_table_lookup (seat->devices_by_id,
2199                                       GINT_TO_POINTER (xev->deviceid));
2200       }
2201       /* Fall through */
2202     case XI_TouchEnd:
2203       {
2204         XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
2205 
2206         source_device = g_hash_table_lookup (seat->devices_by_id,
2207                                              GINT_TO_POINTER (xev->sourceid));
2208 
2209         if (xi_event->evtype == XI_TouchBegin)
2210           event->touch.type = event->type = CLUTTER_TOUCH_BEGIN;
2211         else
2212           event->touch.type = event->type = CLUTTER_TOUCH_END;
2213 
2214         event->touch.stage = stage;
2215         event->touch.time = xev->time;
2216         translate_coords (stage_x11, xev->event_x, xev->event_y, &event->touch.x, &event->touch.y);
2217         meta_input_device_x11_translate_state (event,
2218                                                &xev->mods,
2219                                                &xev->buttons,
2220                                                &xev->group);
2221 
2222         clutter_event_set_source_device (event, source_device);
2223 
2224         device = g_hash_table_lookup (seat->devices_by_id,
2225                                       GINT_TO_POINTER (xev->deviceid));
2226         clutter_event_set_device (event, device);
2227 
2228         event->touch.axes = translate_axes (event->touch.device,
2229                                             event->motion.x,
2230                                             event->motion.y,
2231                                             &xev->valuators);
2232 
2233         if (xi_event->evtype == XI_TouchBegin)
2234           {
2235             event->touch.modifier_state |= CLUTTER_BUTTON1_MASK;
2236 
2237             meta_stage_x11_set_user_time (stage_x11, event->touch.time);
2238             meta_seat_x11_update_touchpoint (seat,
2239                                              GUINT_TO_POINTER (xev->detail),
2240                                              xev->root_x,
2241                                              xev->root_y);
2242           }
2243         else if (xi_event->evtype == XI_TouchEnd)
2244           {
2245             meta_seat_x11_remove_touchpoint (seat,
2246                                              GUINT_TO_POINTER (xev->detail));
2247           }
2248 
2249         /* "NULL" sequences are special cased in clutter */
2250         event->touch.sequence = GINT_TO_POINTER (MAX (1, xev->detail + 1));
2251 
2252         if (xev->flags & XITouchEmulatingPointer)
2253           _clutter_event_set_pointer_emulated (event, TRUE);
2254 
2255         g_debug ("touch %s: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f, axes:%s)",
2256                  event->type == CLUTTER_TOUCH_BEGIN ? "begin" : "end",
2257                  (unsigned int) stage_x11->xwin,
2258                  meta_input_device_x11_get_device_id (event->touch.device),
2259                  clutter_input_device_get_device_name (event->touch.device),
2260                  GPOINTER_TO_UINT (event->touch.sequence),
2261                  event->touch.x,
2262                  event->touch.y,
2263                  event->touch.axes != NULL ? "yes" : "no");
2264 
2265         retval = TRUE;
2266       }
2267       break;
2268 
2269     case XI_TouchUpdate:
2270       {
2271         XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
2272 
2273         source_device = g_hash_table_lookup (seat->devices_by_id,
2274                                              GINT_TO_POINTER (xev->sourceid));
2275 
2276         event->touch.type = event->type = CLUTTER_TOUCH_UPDATE;
2277         event->touch.stage = stage;
2278         event->touch.time = xev->time;
2279         /* "NULL" sequences are special cased in clutter */
2280         event->touch.sequence = GINT_TO_POINTER (MAX (1, xev->detail + 1));
2281         translate_coords (stage_x11, xev->event_x, xev->event_y, &event->touch.x, &event->touch.y);
2282 
2283         clutter_event_set_source_device (event, source_device);
2284 
2285         device = g_hash_table_lookup (seat->devices_by_id,
2286                                       GINT_TO_POINTER (xev->deviceid));
2287         clutter_event_set_device (event, device);
2288 
2289         event->touch.axes = translate_axes (event->touch.device,
2290                                             event->motion.x,
2291                                             event->motion.y,
2292                                             &xev->valuators);
2293 
2294         meta_input_device_x11_translate_state (event,
2295                                                &xev->mods,
2296                                                &xev->buttons,
2297                                                &xev->group);
2298         event->touch.modifier_state |= CLUTTER_BUTTON1_MASK;
2299 
2300         if (xev->flags & XITouchEmulatingPointer)
2301           _clutter_event_set_pointer_emulated (event, TRUE);
2302 
2303         meta_seat_x11_update_touchpoint (seat,
2304                                          event->touch.sequence,
2305                                          xev->root_x,
2306                                          xev->root_y);
2307 
2308         g_debug ("touch update: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f, axes:%s)",
2309                  (unsigned int) stage_x11->xwin,
2310                  meta_input_device_x11_get_device_id (event->touch.device),
2311                  clutter_input_device_get_device_name (event->touch.device),
2312                  GPOINTER_TO_UINT (event->touch.sequence),
2313                  event->touch.x,
2314                  event->touch.y,
2315                  event->touch.axes != NULL ? "yes" : "no");
2316 
2317         retval = TRUE;
2318       }
2319       break;
2320 
2321     case XI_Enter:
2322     case XI_Leave:
2323       {
2324         XIEnterEvent *xev = (XIEnterEvent *) xi_event;
2325 
2326         device = g_hash_table_lookup (seat->devices_by_id,
2327                                       GINT_TO_POINTER (xev->deviceid));
2328 
2329         source_device = g_hash_table_lookup (seat->devices_by_id,
2330                                              GINT_TO_POINTER (xev->sourceid));
2331 
2332         if (xi_event->evtype == XI_Enter)
2333           {
2334             event->crossing.type = event->type = CLUTTER_ENTER;
2335 
2336             event->crossing.stage = stage;
2337             event->crossing.source = CLUTTER_ACTOR (stage);
2338             event->crossing.related = NULL;
2339 
2340             event->crossing.time = xev->time;
2341             translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y);
2342 
2343             if (xev->deviceid == seat->pointer_id)
2344               seat->has_pointer_focus = TRUE;
2345           }
2346         else
2347           {
2348             event->crossing.type = event->type = CLUTTER_LEAVE;
2349 
2350             event->crossing.stage = stage;
2351             event->crossing.source = CLUTTER_ACTOR (stage);
2352             event->crossing.related = NULL;
2353 
2354             event->crossing.time = xev->time;
2355             translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y);
2356 
2357             if (xev->deviceid == seat->pointer_id)
2358               seat->has_pointer_focus = FALSE;
2359           }
2360 
2361         meta_input_device_x11_reset_scroll_info (source_device);
2362 
2363         clutter_event_set_device (event, device);
2364         clutter_event_set_source_device (event, source_device);
2365 
2366         retval = TRUE;
2367       }
2368       break;
2369 
2370     case XI_FocusIn:
2371     case XI_FocusOut:
2372       retval = FALSE;
2373       break;
2374     case XI_PropertyEvent:
2375       translate_property_event (seat, xi_event);
2376       retval = FALSE;
2377       break;
2378     }
2379 
2380   return retval;
2381 }
2382 
2383 ClutterInputDevice *
meta_seat_x11_lookup_device_id(MetaSeatX11 * seat_x11,int device_id)2384 meta_seat_x11_lookup_device_id (MetaSeatX11 *seat_x11,
2385                                 int          device_id)
2386 {
2387   return g_hash_table_lookup (seat_x11->devices_by_id,
2388                               GINT_TO_POINTER (device_id));
2389 }
2390 
2391 void
meta_seat_x11_select_stage_events(MetaSeatX11 * seat,ClutterStage * stage)2392 meta_seat_x11_select_stage_events (MetaSeatX11  *seat,
2393                                    ClutterStage *stage)
2394 {
2395   MetaStageX11 *stage_x11;
2396   XIEventMask xi_event_mask;
2397   unsigned char *mask;
2398   int len;
2399 
2400   stage_x11 = META_STAGE_X11 (_clutter_stage_get_window (stage));
2401 
2402   len = XIMaskLen (XI_LASTEVENT);
2403   mask = g_new0 (unsigned char, len);
2404 
2405   XISetMask (mask, XI_Motion);
2406   XISetMask (mask, XI_ButtonPress);
2407   XISetMask (mask, XI_ButtonRelease);
2408   XISetMask (mask, XI_KeyPress);
2409   XISetMask (mask, XI_KeyRelease);
2410   XISetMask (mask, XI_Enter);
2411   XISetMask (mask, XI_Leave);
2412 
2413   XISetMask (mask, XI_TouchBegin);
2414   XISetMask (mask, XI_TouchUpdate);
2415   XISetMask (mask, XI_TouchEnd);
2416 
2417   xi_event_mask.deviceid = XIAllMasterDevices;
2418   xi_event_mask.mask = mask;
2419   xi_event_mask.mask_len = len;
2420 
2421   XISelectEvents (meta_clutter_x11_get_default_display (),
2422                   stage_x11->xwin, &xi_event_mask, 1);
2423 
2424   g_free (mask);
2425 }
2426