1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
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 
18 #include "config.h"
19 
20 #include "gdkx11devicemanager-xi2.h"
21 
22 #include "gdkdevice-xi2-private.h"
23 #include "gdkdeviceprivate.h"
24 #include "gdkdevicetoolprivate.h"
25 #include "gdkdisplayprivate.h"
26 #include "gdkeventtranslator.h"
27 #include "gdkkeys-x11.h"
28 #include "gdkprivate-x11.h"
29 #include "gdkdisplay-x11.h"
30 #include "gdkintl.h"
31 #include "gdkkeysyms.h"
32 #include "gdkinternals.h"
33 #include "gdkseatdefaultprivate.h"
34 
35 #include <X11/Xlib.h>
36 #include <X11/Xutil.h>
37 #include <X11/extensions/XInput2.h>
38 #include <X11/Xatom.h>
39 
40 #include <string.h>
41 
42 #ifdef G_ENABLE_DEBUG
43 static const char notify_modes[][19] = {
44   "NotifyNormal",
45   "NotifyGrab",
46   "NotifyUngrab",
47   "NotifyWhileGrabbed"
48 };
49 
50 static const char notify_details[][23] = {
51   "NotifyAncestor",
52   "NotifyVirtual",
53   "NotifyInferior",
54   "NotifyNonlinear",
55   "NotifyNonlinearVirtual",
56   "NotifyPointer",
57   "NotifyPointerRoot",
58   "NotifyDetailNone"
59 };
60 #endif
61 
62 #define HAS_FOCUS(toplevel)                           \
63   ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
64 
65 static const char *wacom_type_atoms[] = {
66   "STYLUS",
67   "CURSOR",
68   "ERASER",
69   "PAD",
70   "TOUCH"
71 };
72 #define N_WACOM_TYPE_ATOMS G_N_ELEMENTS (wacom_type_atoms)
73 
74 enum {
75   WACOM_TYPE_STYLUS,
76   WACOM_TYPE_CURSOR,
77   WACOM_TYPE_ERASER,
78   WACOM_TYPE_PAD,
79   WACOM_TYPE_TOUCH,
80 };
81 
82 struct _GdkX11DeviceManagerXI2
83 {
84   GObject parent_object;
85 
86   GdkDisplay *display;
87   GHashTable *id_table;
88 
89   GList *devices;
90 
91   int opcode;
92   int major;
93   int minor;
94 };
95 
96 struct _GdkX11DeviceManagerXI2Class
97 {
98   GObjectClass parent_class;
99 };
100 
101 static void     gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
102 
103 G_DEFINE_TYPE_WITH_CODE (GdkX11DeviceManagerXI2, gdk_x11_device_manager_xi2, G_TYPE_OBJECT,
104                          G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
105                                                 gdk_x11_device_manager_xi2_event_translator_init))
106 
107 static void    gdk_x11_device_manager_xi2_constructed  (GObject      *object);
108 static void    gdk_x11_device_manager_xi2_dispose      (GObject      *object);
109 static void    gdk_x11_device_manager_xi2_set_property (GObject      *object,
110                                                         guint         prop_id,
111                                                         const GValue *value,
112                                                         GParamSpec   *pspec);
113 static void    gdk_x11_device_manager_xi2_get_property (GObject      *object,
114                                                         guint         prop_id,
115                                                         GValue       *value,
116                                                         GParamSpec   *pspec);
117 
118 static GdkEvent * gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
119                                                                GdkDisplay         *display,
120                                                                const XEvent       *xevent);
121 static GdkEventMask gdk_x11_device_manager_xi2_get_handled_events   (GdkEventTranslator *translator);
122 static void         gdk_x11_device_manager_xi2_select_surface_events (GdkEventTranslator *translator,
123                                                                      Window              window,
124                                                                      GdkEventMask        event_mask);
125 static GdkSurface *  gdk_x11_device_manager_xi2_get_surface         (GdkEventTranslator *translator,
126                                                                      const XEvent       *xevent);
127 
128 enum {
129   PROP_0,
130   PROP_DISPLAY,
131   PROP_OPCODE,
132   PROP_MAJOR,
133   PROP_MINOR
134 };
135 
136 static void
gdk_x11_device_manager_xi2_class_init(GdkX11DeviceManagerXI2Class * klass)137 gdk_x11_device_manager_xi2_class_init (GdkX11DeviceManagerXI2Class *klass)
138 {
139   GObjectClass *object_class = G_OBJECT_CLASS (klass);
140 
141   object_class->constructed = gdk_x11_device_manager_xi2_constructed;
142   object_class->dispose = gdk_x11_device_manager_xi2_dispose;
143   object_class->set_property = gdk_x11_device_manager_xi2_set_property;
144   object_class->get_property = gdk_x11_device_manager_xi2_get_property;
145 
146   g_object_class_install_property (object_class,
147                                    PROP_DISPLAY,
148                                    g_param_spec_object ("display",
149                                                         "Display",
150                                                         "Display for the device manager",
151                                                         GDK_TYPE_DISPLAY,
152                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
153                                                         G_PARAM_STATIC_STRINGS));
154   g_object_class_install_property (object_class,
155                                    PROP_OPCODE,
156                                    g_param_spec_int ("opcode",
157                                                      P_("Opcode"),
158                                                      P_("Opcode for XInput2 requests"),
159                                                      0, G_MAXINT, 0,
160                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
161                                                      G_PARAM_STATIC_STRINGS));
162   g_object_class_install_property (object_class,
163                                    PROP_MAJOR,
164                                    g_param_spec_int ("major",
165                                                      P_("Major"),
166                                                      P_("Major version number"),
167                                                      0, G_MAXINT, 0,
168                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
169                                                      G_PARAM_STATIC_STRINGS));
170   g_object_class_install_property (object_class,
171                                    PROP_MINOR,
172                                    g_param_spec_int ("minor",
173                                                      P_("Minor"),
174                                                      P_("Minor version number"),
175                                                      0, G_MAXINT, 0,
176                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
177                                                      G_PARAM_STATIC_STRINGS));
178 }
179 
180 static void
gdk_x11_device_manager_xi2_init(GdkX11DeviceManagerXI2 * device_manager)181 gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
182 {
183   device_manager->id_table = g_hash_table_new_full (g_direct_hash,
184                                                     g_direct_equal,
185                                                     NULL,
186                                                     (GDestroyNotify) g_object_unref);
187 }
188 
189 static void
_gdk_x11_device_manager_xi2_select_events(GdkX11DeviceManagerXI2 * device_manager,Window xwindow,XIEventMask * event_mask)190 _gdk_x11_device_manager_xi2_select_events (GdkX11DeviceManagerXI2 *device_manager,
191                                            Window                  xwindow,
192                                            XIEventMask            *event_mask)
193 {
194   GdkDisplay *display;
195   Display *xdisplay;
196 
197   display = device_manager->display;
198   xdisplay = GDK_DISPLAY_XDISPLAY (display);
199 
200   XISelectEvents (xdisplay, xwindow, event_mask, 1);
201 }
202 
203 static void
translate_valuator_class(GdkDisplay * display,GdkDevice * device,Atom valuator_label,double min,double max,double resolution)204 translate_valuator_class (GdkDisplay          *display,
205                           GdkDevice           *device,
206                           Atom                 valuator_label,
207                           double               min,
208                           double               max,
209                           double               resolution)
210 {
211   static gboolean initialized = FALSE;
212   static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
213   GdkAxisUse use = GDK_AXIS_IGNORE;
214   int i;
215 
216   if (!initialized)
217     {
218       label_atoms [GDK_AXIS_X] = gdk_x11_get_xatom_by_name_for_display (display, "Abs X");
219       label_atoms [GDK_AXIS_Y] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Y");
220       label_atoms [GDK_AXIS_PRESSURE] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Pressure");
221       label_atoms [GDK_AXIS_XTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt X");
222       label_atoms [GDK_AXIS_YTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt Y");
223       label_atoms [GDK_AXIS_WHEEL] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Wheel");
224       initialized = TRUE;
225     }
226 
227   for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
228     {
229       if (label_atoms[i] == valuator_label)
230         {
231           use = i;
232           break;
233         }
234     }
235 
236   _gdk_device_add_axis (device, use, min, max, resolution);
237   GDK_DISPLAY_NOTE (display, INPUT,
238     {
239       const char *label;
240 
241       if (valuator_label != None)
242         label = gdk_x11_get_xatom_name_for_display (display, valuator_label);
243       else
244         label = NULL;
245 
246       g_message ("\n\taxis: %s %s", label, use == GDK_AXIS_IGNORE ? "(ignored)" : "(used)");
247   });
248 }
249 
250 static void
translate_device_classes(GdkDisplay * display,GdkDevice * device,XIAnyClassInfo ** classes,guint n_classes)251 translate_device_classes (GdkDisplay      *display,
252                           GdkDevice       *device,
253                           XIAnyClassInfo **classes,
254                           guint            n_classes)
255 {
256   int i;
257 
258   g_object_freeze_notify (G_OBJECT (device));
259 
260   for (i = 0; i < n_classes; i++)
261     {
262       XIAnyClassInfo *class_info = classes[i];
263 
264       switch (class_info->type)
265         {
266         case XIKeyClass:
267           {
268             /* Not used */
269           }
270           break;
271         case XIValuatorClass:
272           {
273             XIValuatorClassInfo *valuator_info = (XIValuatorClassInfo *) class_info;
274             translate_valuator_class (display, device,
275                                       valuator_info->label,
276                                       valuator_info->min,
277                                       valuator_info->max,
278                                       valuator_info->resolution);
279           }
280           break;
281 #ifdef XINPUT_2_2
282         case XIScrollClass:
283           {
284             XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info;
285             GdkScrollDirection direction;
286 
287             if (scroll_info->scroll_type == XIScrollTypeVertical)
288               direction = GDK_SCROLL_DOWN;
289             else
290               direction = GDK_SCROLL_RIGHT;
291 
292             GDK_DISPLAY_NOTE (display, INPUT,
293                       g_message ("\n\tscroll valuator %d: %s, increment %f",
294                                  scroll_info->number,
295                                  scroll_info->scroll_type == XIScrollTypeVertical
296                                                 ? "vertical"
297                                                 : "horizontal",
298                                  scroll_info->increment));
299 
300             _gdk_x11_device_xi2_add_scroll_valuator (GDK_X11_DEVICE_XI2 (device),
301                                                      scroll_info->number,
302                                                      direction,
303                                                      scroll_info->increment);
304           }
305           break;
306 #endif /* XINPUT_2_2 */
307         default:
308           /* Ignore */
309           break;
310         }
311     }
312 
313   g_object_thaw_notify (G_OBJECT (device));
314 }
315 
316 static gboolean
is_touch_device(XIAnyClassInfo ** classes,guint n_classes,GdkInputSource * device_type,int * num_touches)317 is_touch_device (XIAnyClassInfo **classes,
318                  guint            n_classes,
319                  GdkInputSource  *device_type,
320                  int             *num_touches)
321 {
322 #ifdef XINPUT_2_2
323   guint i;
324 
325   for (i = 0; i < n_classes; i++)
326     {
327       XITouchClassInfo *class = (XITouchClassInfo *) classes[i];
328 
329       if (class->type != XITouchClass)
330         continue;
331 
332       if (class->num_touches > 0)
333         {
334           if (class->mode == XIDirectTouch)
335             *device_type = GDK_SOURCE_TOUCHSCREEN;
336           else if (class->mode == XIDependentTouch)
337             *device_type = GDK_SOURCE_TOUCHPAD;
338           else
339             continue;
340 
341           *num_touches = class->num_touches;
342 
343           return TRUE;
344         }
345     }
346 #endif
347 
348   return FALSE;
349 }
350 
351 static gboolean
has_abs_axes(GdkDisplay * display,XIAnyClassInfo ** classes,guint n_classes)352 has_abs_axes (GdkDisplay      *display,
353               XIAnyClassInfo **classes,
354               guint            n_classes)
355 {
356   gboolean has_x = FALSE, has_y = FALSE;
357   Atom abs_x, abs_y;
358   guint i;
359 
360   abs_x = gdk_x11_get_xatom_by_name_for_display (display, "Abs X");
361   abs_y = gdk_x11_get_xatom_by_name_for_display (display, "Abs Y");
362 
363   for (i = 0; i < n_classes; i++)
364     {
365       XIValuatorClassInfo *class = (XIValuatorClassInfo *) classes[i];
366 
367       if (class->type != XIValuatorClass)
368         continue;
369       if (class->mode != XIModeAbsolute)
370         continue;
371 
372       if (class->label == abs_x)
373         has_x = TRUE;
374       else if (class->label == abs_y)
375         has_y = TRUE;
376 
377       if (has_x && has_y)
378         break;
379     }
380 
381   return (has_x && has_y);
382 }
383 
384 static gboolean
get_device_ids(GdkDisplay * display,XIDeviceInfo * info,char ** vendor_id,char ** product_id)385 get_device_ids (GdkDisplay    *display,
386                 XIDeviceInfo  *info,
387                 char         **vendor_id,
388                 char         **product_id)
389 {
390   gulong nitems, bytes_after;
391   guint32 *data;
392   int rc, format;
393   Atom prop, type;
394 
395   gdk_x11_display_error_trap_push (display);
396 
397   prop = XInternAtom (GDK_DISPLAY_XDISPLAY (display), "Device Product ID", True);
398 
399   if (prop == None)
400     {
401       gdk_x11_display_error_trap_pop_ignored (display);
402       return 0;
403     }
404 
405   rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
406                       info->deviceid, prop,
407                       0, 2, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
408                       (guchar **) &data);
409   gdk_x11_display_error_trap_pop_ignored (display);
410 
411   if (rc != Success || type != XA_INTEGER || format != 32 || nitems != 2)
412     return FALSE;
413 
414   if (vendor_id)
415     *vendor_id = g_strdup_printf ("%.4x", data[0]);
416   if (product_id)
417     *product_id = g_strdup_printf ("%.4x", data[1]);
418 
419   XFree (data);
420 
421   return TRUE;
422 }
423 
424 static gboolean
has_bool_prop(GdkDisplay * display,XIDeviceInfo * info,const char * prop_name)425 has_bool_prop (GdkDisplay   *display,
426                XIDeviceInfo *info,
427                const char   *prop_name)
428 {
429   gulong nitems, bytes_after;
430   guint32 *data;
431   int rc, format;
432   Atom type;
433 
434   gdk_x11_display_error_trap_push (display);
435 
436   rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
437                       info->deviceid,
438                       gdk_x11_get_xatom_by_name_for_display (display, prop_name),
439                       0, 1, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
440                       (guchar **) &data);
441   gdk_x11_display_error_trap_pop_ignored (display);
442 
443   if (rc != Success || type != XA_INTEGER || format != 8 || nitems != 1)
444     return FALSE;
445 
446   XFree (data);
447 
448   return TRUE;
449 }
450 
451 static gboolean
is_touchpad_device(GdkDisplay * display,XIDeviceInfo * info)452 is_touchpad_device (GdkDisplay   *display,
453                     XIDeviceInfo *info)
454 {
455   /*
456    * Touchpads are heuristically recognized via XI properties that the various
457    * Xorg drivers expose:
458    *   libinput:  libinput Tapping Enabled
459    *   synaptics: Synaptics Off
460    *   cmt:       Raw Touch Passthrough
461    */
462   return has_bool_prop (display, info, "libinput Tapping Enabled") ||
463          has_bool_prop (display, info, "Synaptics Off") ||
464          has_bool_prop (display, info, "Raw Touch Passthrough");
465 }
466 
467 static GdkDevice *
create_device(GdkX11DeviceManagerXI2 * device_manager,GdkDisplay * display,XIDeviceInfo * dev)468 create_device (GdkX11DeviceManagerXI2 *device_manager,
469                GdkDisplay             *display,
470                XIDeviceInfo           *dev)
471 {
472   GdkInputSource input_source;
473   GdkInputSource touch_source;
474   GdkX11DeviceType type;
475   GdkDevice *device;
476   int num_touches = 0;
477   char *vendor_id = NULL, *product_id = NULL;
478 
479   if (dev->use == XIMasterKeyboard || dev->use == XISlaveKeyboard)
480     input_source = GDK_SOURCE_KEYBOARD;
481   else if (is_touchpad_device (display, dev))
482     input_source = GDK_SOURCE_TOUCHPAD;
483   else if (dev->use == XISlavePointer &&
484            is_touch_device (dev->classes, dev->num_classes, &touch_source, &num_touches))
485     input_source = touch_source;
486   else
487     {
488       char *tmp_name;
489 
490       tmp_name = g_ascii_strdown (dev->name, -1);
491 
492       if (strstr (tmp_name, " pad"))
493         input_source = GDK_SOURCE_TABLET_PAD;
494       else if (strstr (tmp_name, "wacom") ||
495                strstr (tmp_name, "pen") ||
496                strstr (tmp_name, "eraser"))
497         input_source = GDK_SOURCE_PEN;
498       else if (!strstr (tmp_name, "mouse") &&
499                !strstr (tmp_name, "pointer") &&
500                !strstr (tmp_name, "qemu usb tablet") &&
501                !strstr (tmp_name, "spice vdagent tablet") &&
502                !strstr (tmp_name, "virtualbox usb tablet") &&
503                has_abs_axes (display, dev->classes, dev->num_classes))
504         input_source = GDK_SOURCE_TOUCHSCREEN;
505       else if (strstr (tmp_name, "trackpoint") ||
506                strstr (tmp_name, "dualpoint stick"))
507         input_source = GDK_SOURCE_TRACKPOINT;
508       else
509         input_source = GDK_SOURCE_MOUSE;
510 
511       g_free (tmp_name);
512     }
513 
514   switch (dev->use)
515     {
516     case XIMasterKeyboard:
517     case XIMasterPointer:
518       type = GDK_X11_DEVICE_TYPE_LOGICAL;
519       break;
520     case XISlaveKeyboard:
521     case XISlavePointer:
522       type = GDK_X11_DEVICE_TYPE_PHYSICAL;
523       break;
524     case XIFloatingSlave:
525     default:
526       type = GDK_X11_DEVICE_TYPE_FLOATING;
527       break;
528     }
529 
530   GDK_DISPLAY_NOTE (display, INPUT,
531             ({
532               const char *type_names[] = { "logical", "physical", "floating" };
533               const char *source_names[] = { "mouse", "pen", "eraser", "cursor", "keyboard", "direct touch", "indirect touch", "trackpoint", "pad" };
534               g_message ("input device:\n\tname: %s\n\ttype: %s\n\tsource: %s\n\thas cursor: %d\n\ttouches: %d",
535                          dev->name,
536                          type_names[type],
537                          source_names[input_source],
538                          dev->use == XIMasterPointer,
539                          num_touches);
540             }));
541 
542   if (dev->use != XIMasterKeyboard &&
543       dev->use != XIMasterPointer)
544     get_device_ids (display, dev, &vendor_id, &product_id);
545 
546   device = g_object_new (GDK_TYPE_X11_DEVICE_XI2,
547                          "name", dev->name,
548                          "source", input_source,
549                          "has-cursor", (dev->use == XIMasterPointer),
550                          "display", display,
551                          "device-id", dev->deviceid,
552                          "vendor-id", vendor_id,
553                          "product-id", product_id,
554                          "num-touches", num_touches,
555                          NULL);
556   gdk_x11_device_xi2_set_device_type ((GdkX11DeviceXI2 *) device, type);
557 
558   translate_device_classes (display, device, dev->classes, dev->num_classes);
559   g_free (vendor_id);
560   g_free (product_id);
561 
562   return device;
563 }
564 
565 static void
ensure_seat_for_device_pair(GdkX11DeviceManagerXI2 * device_manager,GdkDevice * device1,GdkDevice * device2)566 ensure_seat_for_device_pair (GdkX11DeviceManagerXI2 *device_manager,
567                              GdkDevice              *device1,
568                              GdkDevice              *device2)
569 {
570   GdkDevice *pointer, *keyboard;
571   GdkDisplay *display;
572   GdkSeat *seat;
573 
574   display = device_manager->display;
575   seat = gdk_device_get_seat (device1);
576 
577   if (!seat)
578     {
579       if (gdk_device_get_source (device1) == GDK_SOURCE_KEYBOARD)
580         {
581           keyboard = device1;
582           pointer = device2;
583         }
584       else
585         {
586           pointer = device1;
587           keyboard = device2;
588         }
589 
590       seat = gdk_seat_default_new_for_logical_pair (pointer, keyboard);
591       gdk_display_add_seat (display, seat);
592       g_object_unref (seat);
593     }
594 }
595 
596 static GdkDevice *
add_device(GdkX11DeviceManagerXI2 * device_manager,XIDeviceInfo * dev,gboolean emit_signal)597 add_device (GdkX11DeviceManagerXI2 *device_manager,
598             XIDeviceInfo           *dev,
599             gboolean                emit_signal)
600 {
601   GdkDisplay *display;
602   GdkDevice *device;
603 
604   display = device_manager->display;
605   device = create_device (device_manager, display, dev);
606 
607   g_hash_table_replace (device_manager->id_table,
608                         GINT_TO_POINTER (dev->deviceid),
609                         g_object_ref (device));
610 
611   device_manager->devices = g_list_append (device_manager->devices, device);
612 
613   if (emit_signal)
614     {
615       if (dev->use == XISlavePointer || dev->use == XISlaveKeyboard)
616         {
617           GdkDevice *logical;
618           GdkSeat *seat;
619 
620           /* The device manager is already constructed, then
621            * keep the hierarchy coherent for the added device.
622            */
623           logical = g_hash_table_lookup (device_manager->id_table,
624                                          GINT_TO_POINTER (dev->attachment));
625 
626           _gdk_device_set_associated_device (device, logical);
627           _gdk_device_add_physical_device (logical, device);
628 
629           seat = gdk_device_get_seat (logical);
630           gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), device);
631         }
632       else if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard)
633         {
634           GdkDevice *relative;
635 
636           relative = g_hash_table_lookup (device_manager->id_table,
637                                           GINT_TO_POINTER (dev->attachment));
638 
639           if (relative)
640             {
641               _gdk_device_set_associated_device (device, relative);
642               _gdk_device_set_associated_device (relative, device);
643               ensure_seat_for_device_pair (device_manager, device, relative);
644             }
645         }
646     }
647 
648   return device;
649 }
650 
651 static void
detach_from_seat(GdkDevice * device)652 detach_from_seat (GdkDevice *device)
653 {
654   GdkSeat *seat = gdk_device_get_seat (device);
655   GdkX11DeviceXI2 *device_xi2 = (GdkX11DeviceXI2 *) device;
656 
657   if (!seat)
658     return;
659 
660   if (gdk_x11_device_xi2_get_device_type (device_xi2) == GDK_X11_DEVICE_TYPE_LOGICAL)
661     gdk_display_remove_seat (gdk_device_get_display (device), seat);
662   else if (gdk_x11_device_xi2_get_device_type (device_xi2) == GDK_X11_DEVICE_TYPE_PHYSICAL)
663     gdk_seat_default_remove_physical_device (GDK_SEAT_DEFAULT (seat), device);
664 }
665 
666 static void
remove_device(GdkX11DeviceManagerXI2 * device_manager,int device_id)667 remove_device (GdkX11DeviceManagerXI2 *device_manager,
668                int                     device_id)
669 {
670   GdkDevice *device;
671 
672   device = g_hash_table_lookup (device_manager->id_table,
673                                 GINT_TO_POINTER (device_id));
674 
675   if (device)
676     {
677       detach_from_seat (device);
678 
679       g_hash_table_remove (device_manager->id_table,
680                            GINT_TO_POINTER (device_id));
681 
682       device_manager->devices = g_list_remove (device_manager->devices, device);
683       g_object_run_dispose (G_OBJECT (device));
684       g_object_unref (device);
685     }
686 }
687 
688 static void
relate_logical_devices(gpointer key,gpointer value,gpointer user_data)689 relate_logical_devices (gpointer key,
690                         gpointer value,
691                         gpointer user_data)
692 {
693   GdkX11DeviceManagerXI2 *device_manager;
694   GdkDevice *device, *relative;
695 
696   device_manager = user_data;
697   device = g_hash_table_lookup (device_manager->id_table, key);
698   relative = g_hash_table_lookup (device_manager->id_table, value);
699 
700   _gdk_device_set_associated_device (device, relative);
701   _gdk_device_set_associated_device (relative, device);
702   ensure_seat_for_device_pair (device_manager, device, relative);
703 }
704 
705 static void
relate_physical_devices(gpointer key,gpointer value,gpointer user_data)706 relate_physical_devices (gpointer key,
707                          gpointer value,
708                          gpointer user_data)
709 {
710   GdkX11DeviceManagerXI2 *device_manager;
711   GdkDevice *physical, *logical;
712   GdkSeat *seat;
713 
714   device_manager = user_data;
715   physical = g_hash_table_lookup (device_manager->id_table, key);
716   logical = g_hash_table_lookup (device_manager->id_table, value);
717 
718   _gdk_device_set_associated_device (physical, logical);
719   _gdk_device_add_physical_device (logical, physical);
720 
721   seat = gdk_device_get_seat (logical);
722   gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), physical);
723 }
724 
725 static void
gdk_x11_device_manager_xi2_constructed(GObject * object)726 gdk_x11_device_manager_xi2_constructed (GObject *object)
727 {
728   GdkX11DeviceManagerXI2 *device_manager;
729   GdkDisplay *display;
730   GHashTable *logical_devices, *physical_devices;
731   Display *xdisplay;
732   XIDeviceInfo *info, *dev;
733   int ndevices, i;
734   XIEventMask event_mask;
735   unsigned char mask[2] = { 0 };
736 
737   G_OBJECT_CLASS (gdk_x11_device_manager_xi2_parent_class)->constructed (object);
738 
739   device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
740   display = device_manager->display;
741   xdisplay = GDK_DISPLAY_XDISPLAY (display);
742 
743   g_assert (device_manager->major == 2);
744 
745   logical_devices = g_hash_table_new (NULL, NULL);
746   physical_devices = g_hash_table_new (NULL, NULL);
747 
748   info = XIQueryDevice (xdisplay, XIAllDevices, &ndevices);
749 
750   /* Initialize devices list */
751   for (i = 0; i < ndevices; i++)
752     {
753       dev = &info[i];
754 
755       if (!dev->enabled)
756 	      continue;
757 
758       add_device (device_manager, dev, FALSE);
759 
760       if (dev->use == XIMasterPointer ||
761           dev->use == XIMasterKeyboard)
762         {
763           g_hash_table_insert (logical_devices,
764                                GINT_TO_POINTER (dev->deviceid),
765                                GINT_TO_POINTER (dev->attachment));
766         }
767       else if (dev->use == XISlavePointer ||
768                dev->use == XISlaveKeyboard)
769         {
770           g_hash_table_insert (physical_devices,
771                                GINT_TO_POINTER (dev->deviceid),
772                                GINT_TO_POINTER (dev->attachment));
773         }
774     }
775 
776   XIFreeDeviceInfo (info);
777 
778   /* Stablish relationships between devices */
779   g_hash_table_foreach (logical_devices, relate_logical_devices, object);
780   g_hash_table_destroy (logical_devices);
781 
782   g_hash_table_foreach (physical_devices, relate_physical_devices, object);
783   g_hash_table_destroy (physical_devices);
784 
785   /* Connect to hierarchy change events */
786   XISetMask (mask, XI_HierarchyChanged);
787   XISetMask (mask, XI_DeviceChanged);
788   XISetMask (mask, XI_PropertyEvent);
789 
790   event_mask.deviceid = XIAllDevices;
791   event_mask.mask_len = sizeof (mask);
792   event_mask.mask = mask;
793 
794   _gdk_x11_device_manager_xi2_select_events (device_manager,
795                                              GDK_DISPLAY_XROOTWIN (display),
796                                              &event_mask);
797 }
798 
799 static void
gdk_x11_device_manager_xi2_dispose(GObject * object)800 gdk_x11_device_manager_xi2_dispose (GObject *object)
801 {
802   GdkX11DeviceManagerXI2 *device_manager;
803 
804   device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
805 
806   g_list_free_full (device_manager->devices, g_object_unref);
807   device_manager->devices = NULL;
808 
809   if (device_manager->id_table)
810     {
811       g_hash_table_destroy (device_manager->id_table);
812       device_manager->id_table = NULL;
813     }
814 
815   G_OBJECT_CLASS (gdk_x11_device_manager_xi2_parent_class)->dispose (object);
816 }
817 
818 static void
gdk_x11_device_manager_xi2_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)819 gdk_x11_device_manager_xi2_set_property (GObject      *object,
820                                          guint         prop_id,
821                                          const GValue *value,
822                                          GParamSpec   *pspec)
823 {
824   GdkX11DeviceManagerXI2 *device_manager;
825 
826   device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
827 
828   switch (prop_id)
829     {
830     case PROP_DISPLAY:
831       device_manager->display = g_value_get_object (value);
832       break;
833     case PROP_OPCODE:
834       device_manager->opcode = g_value_get_int (value);
835       break;
836     case PROP_MAJOR:
837       device_manager->major = g_value_get_int (value);
838       break;
839     case PROP_MINOR:
840       device_manager->minor = g_value_get_int (value);
841       break;
842     default:
843       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
844       break;
845     }
846 }
847 
848 static void
gdk_x11_device_manager_xi2_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)849 gdk_x11_device_manager_xi2_get_property (GObject    *object,
850                                          guint       prop_id,
851                                          GValue     *value,
852                                          GParamSpec *pspec)
853 {
854   GdkX11DeviceManagerXI2 *device_manager;
855 
856   device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
857 
858   switch (prop_id)
859     {
860     case PROP_DISPLAY:
861       g_value_set_object (value, device_manager->display);
862       break;
863     case PROP_OPCODE:
864       g_value_set_int (value, device_manager->opcode);
865       break;
866     case PROP_MAJOR:
867       g_value_set_int (value, device_manager->major);
868       break;
869     case PROP_MINOR:
870       g_value_set_int (value, device_manager->minor);
871       break;
872     default:
873       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
874       break;
875     }
876 }
877 
878 static void
gdk_x11_device_manager_xi2_event_translator_init(GdkEventTranslatorIface * iface)879 gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
880 {
881   iface->translate_event = gdk_x11_device_manager_xi2_translate_event;
882   iface->get_handled_events = gdk_x11_device_manager_xi2_get_handled_events;
883   iface->select_surface_events = gdk_x11_device_manager_xi2_select_surface_events;
884   iface->get_surface = gdk_x11_device_manager_xi2_get_surface;
885 }
886 
887 static void
handle_hierarchy_changed(GdkX11DeviceManagerXI2 * device_manager,XIHierarchyEvent * ev)888 handle_hierarchy_changed (GdkX11DeviceManagerXI2 *device_manager,
889                           XIHierarchyEvent       *ev)
890 {
891   GdkDisplay *display;
892   Display *xdisplay;
893   XIDeviceInfo *info;
894   int ndevices;
895   int i;
896 
897   display = device_manager->display;
898   xdisplay = GDK_DISPLAY_XDISPLAY (display);
899 
900   for (i = 0; i < ev->num_info; i++)
901     {
902       if (ev->info[i].flags & XIDeviceEnabled)
903         {
904           gdk_x11_display_error_trap_push (display);
905           info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
906           gdk_x11_display_error_trap_pop_ignored (display);
907           if (info)
908             {
909               add_device (device_manager, &info[0], TRUE);
910               XIFreeDeviceInfo (info);
911             }
912         }
913       else if (ev->info[i].flags & XIDeviceDisabled)
914         remove_device (device_manager, ev->info[i].deviceid);
915       else if (ev->info[i].flags & XISlaveAttached ||
916                ev->info[i].flags & XISlaveDetached)
917         {
918           GdkDevice *logical = NULL, *physical;
919           GdkSeat *seat;
920 
921           physical = g_hash_table_lookup (device_manager->id_table,
922                                           GINT_TO_POINTER (ev->info[i].deviceid));
923 
924           if (!physical)
925             continue;
926 
927           seat = gdk_device_get_seat (physical);
928           gdk_seat_default_remove_physical_device (GDK_SEAT_DEFAULT (seat), physical);
929 
930           /* Add new logical device if it's an attachment event */
931           if (ev->info[i].flags & XISlaveAttached)
932             {
933               gdk_x11_display_error_trap_push (display);
934               info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
935               gdk_x11_display_error_trap_pop_ignored (display);
936               if (info)
937                 {
938                   logical = g_hash_table_lookup (device_manager->id_table,
939                                                  GINT_TO_POINTER (info->attachment));
940                   XIFreeDeviceInfo (info);
941                 }
942 
943               if (logical != NULL)
944                 {
945                   _gdk_device_set_associated_device (physical, logical);
946                   _gdk_device_add_physical_device (logical, physical);
947 
948                   seat = gdk_device_get_seat (logical);
949                   gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), physical);
950                 }
951             }
952         }
953     }
954 }
955 
956 static void
handle_device_changed(GdkX11DeviceManagerXI2 * device_manager,XIDeviceChangedEvent * ev)957 handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
958                        XIDeviceChangedEvent   *ev)
959 {
960   GdkDisplay *display;
961   GdkDevice *device, *source_device;
962 
963   display = device_manager->display;
964   device = g_hash_table_lookup (device_manager->id_table,
965                                 GUINT_TO_POINTER (ev->deviceid));
966   source_device = g_hash_table_lookup (device_manager->id_table,
967                                        GUINT_TO_POINTER (ev->sourceid));
968 
969   if (device)
970     {
971       _gdk_device_reset_axes (device);
972       _gdk_device_xi2_unset_scroll_valuators ((GdkX11DeviceXI2 *) device);
973       gdk_x11_device_xi2_store_axes (GDK_X11_DEVICE_XI2 (device), NULL, 0);
974       translate_device_classes (display, device, ev->classes, ev->num_classes);
975 
976       g_signal_emit_by_name (G_OBJECT (device), "changed");
977     }
978 
979   if (source_device)
980     _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
981 }
982 
983 static gboolean
device_get_tool_serial_and_id(GdkDevice * device,guint * serial_id,guint * id)984 device_get_tool_serial_and_id (GdkDevice *device,
985                                guint     *serial_id,
986                                guint     *id)
987 {
988   GdkDisplay *display;
989   gulong nitems, bytes_after;
990   guint32 *data;
991   int rc, format;
992   Atom type;
993 
994   display = gdk_device_get_display (device);
995 
996   gdk_x11_display_error_trap_push (display);
997 
998   rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
999                       gdk_x11_device_get_id (device),
1000                       gdk_x11_get_xatom_by_name_for_display (display, "Wacom Serial IDs"),
1001                       0, 5, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
1002                       (guchar **) &data);
1003   gdk_x11_display_error_trap_pop_ignored (display);
1004 
1005   if (rc != Success)
1006     return FALSE;
1007 
1008   if (type == XA_INTEGER && format == 32)
1009     {
1010       if (nitems >= 4)
1011         *serial_id = data[3];
1012       if (nitems >= 5)
1013         *id = data[4];
1014     }
1015 
1016   XFree (data);
1017 
1018   return TRUE;
1019 }
1020 
1021 static GdkDeviceToolType
device_get_tool_type(GdkDevice * device)1022 device_get_tool_type (GdkDevice *device)
1023 {
1024   GdkDisplay *display;
1025   gulong nitems, bytes_after;
1026   guint32 *data;
1027   int rc, format;
1028   Atom type;
1029   Atom device_type;
1030   Atom types[N_WACOM_TYPE_ATOMS];
1031   GdkDeviceToolType tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1032 
1033   display = gdk_device_get_display (device);
1034   gdk_x11_display_error_trap_push (display);
1035 
1036   rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
1037                       gdk_x11_device_get_id (device),
1038                       gdk_x11_get_xatom_by_name_for_display (display, "Wacom Tool Type"),
1039                       0, 1, False, XA_ATOM, &type, &format, &nitems, &bytes_after,
1040                       (guchar **) &data);
1041   gdk_x11_display_error_trap_pop_ignored (display);
1042 
1043   if (rc != Success)
1044     return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1045 
1046   if (type != XA_ATOM || format != 32 || nitems != 1)
1047     {
1048       XFree (data);
1049       return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1050     }
1051 
1052   device_type = *data;
1053   XFree (data);
1054 
1055   if (device_type == 0)
1056     return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1057 
1058   gdk_x11_display_error_trap_push (display);
1059   rc = XInternAtoms (GDK_DISPLAY_XDISPLAY (display),
1060                      (char **) wacom_type_atoms,
1061                      N_WACOM_TYPE_ATOMS,
1062                      False,
1063                      types);
1064   gdk_x11_display_error_trap_pop_ignored (display);
1065 
1066   if (rc == 0)
1067     return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1068 
1069   if (device_type == types[WACOM_TYPE_STYLUS])
1070     tool_type = GDK_DEVICE_TOOL_TYPE_PEN;
1071   else if (device_type == types[WACOM_TYPE_CURSOR])
1072     tool_type = GDK_DEVICE_TOOL_TYPE_MOUSE;
1073   else if (device_type == types[WACOM_TYPE_ERASER])
1074     tool_type = GDK_DEVICE_TOOL_TYPE_ERASER;
1075   else if (device_type == types[WACOM_TYPE_TOUCH])
1076     tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1077 
1078   return tool_type;
1079 }
1080 
1081 static void
handle_property_change(GdkX11DeviceManagerXI2 * device_manager,XIPropertyEvent * ev)1082 handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
1083                         XIPropertyEvent        *ev)
1084 {
1085   GdkDevice *device;
1086 
1087   device = g_hash_table_lookup (device_manager->id_table,
1088                                 GUINT_TO_POINTER (ev->deviceid));
1089 
1090   if (device != NULL &&
1091       ev->property == gdk_x11_get_xatom_by_name_for_display (gdk_device_get_display (device), "Wacom Serial IDs"))
1092     {
1093       GdkDeviceTool *tool = NULL;
1094       guint serial_id = 0, tool_id = 0;
1095       GdkSeat *seat;
1096 
1097       if (ev->what != XIPropertyDeleted &&
1098           device_get_tool_serial_and_id (device, &serial_id, &tool_id))
1099         {
1100           GdkDeviceToolType tool_type;
1101 
1102           seat = gdk_device_get_seat (device);
1103           tool_type = device_get_tool_type (device);
1104 
1105           if (tool_type != GDK_DEVICE_TOOL_TYPE_UNKNOWN)
1106             {
1107               tool = gdk_seat_get_tool (seat, serial_id, tool_id, tool_type);
1108 
1109               if (!tool && serial_id > 0)
1110                 {
1111                   tool = gdk_device_tool_new (serial_id, tool_id, tool_type, 0);
1112                   gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
1113                 }
1114             }
1115         }
1116 
1117       gdk_device_update_tool (device, tool);
1118     }
1119 }
1120 
1121 static GdkCrossingMode
translate_crossing_mode(int mode)1122 translate_crossing_mode (int mode)
1123 {
1124   switch (mode)
1125     {
1126     case XINotifyNormal:
1127       return GDK_CROSSING_NORMAL;
1128     case XINotifyGrab:
1129     case XINotifyPassiveGrab:
1130       return GDK_CROSSING_GRAB;
1131     case XINotifyUngrab:
1132     case XINotifyPassiveUngrab:
1133       return GDK_CROSSING_UNGRAB;
1134     case XINotifyWhileGrabbed:
1135       /* Fall through, unexpected in pointer crossing events */
1136     default:
1137       g_assert_not_reached ();
1138       return GDK_CROSSING_NORMAL;
1139     }
1140 }
1141 
1142 static GdkNotifyType
translate_notify_type(int detail)1143 translate_notify_type (int detail)
1144 {
1145   switch (detail)
1146     {
1147     case NotifyInferior:
1148       return GDK_NOTIFY_INFERIOR;
1149     case NotifyAncestor:
1150       return GDK_NOTIFY_ANCESTOR;
1151     case NotifyVirtual:
1152       return GDK_NOTIFY_VIRTUAL;
1153     case NotifyNonlinear:
1154       return GDK_NOTIFY_NONLINEAR;
1155     case NotifyNonlinearVirtual:
1156       return GDK_NOTIFY_NONLINEAR_VIRTUAL;
1157     default:
1158       g_assert_not_reached ();
1159       return GDK_NOTIFY_UNKNOWN;
1160     }
1161 }
1162 
1163 static void
set_user_time(GdkEvent * event)1164 set_user_time (GdkEvent *event)
1165 {
1166   GdkSurface *surface;
1167   guint32 time;
1168 
1169   surface = gdk_event_get_surface (event);
1170   g_return_if_fail (GDK_IS_SURFACE (surface));
1171 
1172   time = gdk_event_get_time (event);
1173 
1174   /* If an event doesn't have a valid timestamp, we shouldn't use it
1175    * to update the latest user interaction time.
1176    */
1177   if (time != GDK_CURRENT_TIME)
1178     gdk_x11_surface_set_user_time (surface, time);
1179 }
1180 
1181 static double *
translate_axes(GdkDevice * device,double x,double y,GdkSurface * surface,XIValuatorState * valuators)1182 translate_axes (GdkDevice       *device,
1183                 double           x,
1184                 double           y,
1185                 GdkSurface       *surface,
1186                 XIValuatorState *valuators)
1187 {
1188   guint n_axes, i;
1189   double *axes;
1190   double *vals;
1191 
1192   n_axes = gdk_device_get_n_axes (device);
1193   axes = g_new0 (double, GDK_AXIS_LAST);
1194   vals = valuators->values;
1195 
1196   for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
1197     {
1198       GdkAxisUse use;
1199       double val;
1200 
1201       if (!XIMaskIsSet (valuators->mask, i))
1202         continue;
1203 
1204       use = gdk_device_get_axis_use (device, i);
1205       val = *vals++;
1206 
1207       switch ((guint) use)
1208         {
1209         case GDK_AXIS_X:
1210         case GDK_AXIS_Y:
1211             {
1212               if (use == GDK_AXIS_X)
1213                 axes[use] = x;
1214               else
1215                 axes[use] = y;
1216             }
1217           break;
1218         default:
1219           _gdk_device_translate_axis (device, i, val, &axes[use]);
1220           break;
1221         }
1222     }
1223 
1224   gdk_x11_device_xi2_store_axes (GDK_X11_DEVICE_XI2 (device), axes, n_axes);
1225 
1226   return axes;
1227 }
1228 
1229 static gboolean
get_event_surface(GdkEventTranslator * translator,XIEvent * ev,GdkSurface ** surface_p)1230 get_event_surface (GdkEventTranslator *translator,
1231                   XIEvent            *ev,
1232                   GdkSurface         **surface_p)
1233 {
1234   GdkDisplay *display;
1235   GdkSurface *surface = NULL;
1236   gboolean should_have_window = TRUE;
1237 
1238   display = GDK_X11_DEVICE_MANAGER_XI2 (translator)->display;
1239 
1240   switch (ev->evtype)
1241     {
1242     case XI_KeyPress:
1243     case XI_KeyRelease:
1244     case XI_ButtonPress:
1245     case XI_ButtonRelease:
1246     case XI_Motion:
1247 #ifdef XINPUT_2_2
1248     case XI_TouchUpdate:
1249     case XI_TouchBegin:
1250     case XI_TouchEnd:
1251 #endif /* XINPUT_2_2 */
1252       {
1253         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1254 
1255         surface = gdk_x11_surface_lookup_for_display (display, xev->event);
1256 
1257         /* Apply keyboard grabs to non-native windows */
1258         if (ev->evtype == XI_KeyPress || ev->evtype == XI_KeyRelease)
1259           {
1260             GdkDeviceGrabInfo *info;
1261             GdkDevice *device;
1262             gulong serial;
1263 
1264             device = g_hash_table_lookup (GDK_X11_DEVICE_MANAGER_XI2 (translator)->id_table,
1265                                           GUINT_TO_POINTER (((XIDeviceEvent *) ev)->deviceid));
1266 
1267             serial = _gdk_display_get_next_serial (display);
1268             info = _gdk_display_has_device_grab (display, device, serial);
1269 
1270             if (info && !info->owner_events)
1271               {
1272                 /* Report key event against grab surface */
1273                 surface = info->surface;
1274               }
1275           }
1276       }
1277       break;
1278     case XI_Enter:
1279     case XI_Leave:
1280     case XI_FocusIn:
1281     case XI_FocusOut:
1282       {
1283         XIEnterEvent *xev = (XIEnterEvent *) ev;
1284 
1285         surface = gdk_x11_surface_lookup_for_display (display, xev->event);
1286       }
1287       break;
1288     default:
1289       should_have_window = FALSE;
1290       break;
1291     }
1292 
1293   *surface_p = surface;
1294 
1295   if (should_have_window && !surface)
1296     return FALSE;
1297 
1298   return TRUE;
1299 }
1300 
1301 static gboolean
scroll_valuators_changed(GdkX11DeviceXI2 * device,XIValuatorState * valuators,double * dx,double * dy)1302 scroll_valuators_changed (GdkX11DeviceXI2 *device,
1303                           XIValuatorState *valuators,
1304                           double          *dx,
1305                           double          *dy)
1306 {
1307   gboolean has_scroll_valuators = FALSE;
1308   GdkScrollDirection direction;
1309   guint n_axes, i, n_val;
1310   double *vals;
1311 
1312   n_axes = gdk_device_get_n_axes (GDK_DEVICE (device));
1313   vals = valuators->values;
1314   *dx = *dy = 0;
1315   n_val = 0;
1316 
1317   for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
1318     {
1319       double delta;
1320 
1321       if (!XIMaskIsSet (valuators->mask, i))
1322         continue;
1323 
1324       if (_gdk_x11_device_xi2_get_scroll_delta (device, i, vals[n_val],
1325                                                 &direction, &delta))
1326         {
1327           has_scroll_valuators = TRUE;
1328 
1329           if (direction == GDK_SCROLL_UP ||
1330               direction == GDK_SCROLL_DOWN)
1331             *dy = delta;
1332           else
1333             *dx = delta;
1334         }
1335 
1336       n_val++;
1337     }
1338 
1339   return has_scroll_valuators;
1340 }
1341 
1342 /* We only care about focus events that indicate that _this_
1343  * surface (not an ancestor or child) got or lost the focus
1344  */
1345 static void
_gdk_device_manager_xi2_handle_focus(GdkSurface * surface,Window original,GdkDevice * device,GdkDevice * source_device,gboolean focus_in,int detail,int mode)1346 _gdk_device_manager_xi2_handle_focus (GdkSurface *surface,
1347                                       Window      original,
1348                                       GdkDevice  *device,
1349                                       GdkDevice  *source_device,
1350                                       gboolean    focus_in,
1351                                       int         detail,
1352                                       int         mode)
1353 {
1354   GdkToplevelX11 *toplevel;
1355   GdkX11Screen *x11_screen;
1356   gboolean had_focus;
1357 
1358   g_return_if_fail (GDK_IS_SURFACE (surface));
1359   g_return_if_fail (GDK_IS_DEVICE (device));
1360   g_return_if_fail (source_device == NULL || GDK_IS_DEVICE (source_device));
1361 
1362   GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS,
1363             g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
1364                        GDK_SURFACE_XID (surface),
1365                        notify_details[detail],
1366                        notify_modes[mode]));
1367 
1368   toplevel = _gdk_x11_surface_get_toplevel (surface);
1369 
1370   if (!toplevel)
1371     return;
1372 
1373   if (toplevel->focus_window == original)
1374     return;
1375 
1376   had_focus = HAS_FOCUS (toplevel);
1377   x11_screen = GDK_X11_SCREEN (GDK_SURFACE_SCREEN (surface));
1378 
1379   switch (detail)
1380     {
1381     case NotifyAncestor:
1382     case NotifyVirtual:
1383       /* When the focus moves from an ancestor of the window to
1384        * the window or a descendent of the window, *and* the
1385        * pointer is inside the window, then we were previously
1386        * receiving keystroke events in the has_pointer_focus
1387        * case and are now receiving them in the
1388        * has_focus_window case.
1389        */
1390       if (toplevel->has_pointer &&
1391           !x11_screen->wmspec_check_window &&
1392           mode != NotifyGrab &&
1393           mode != XINotifyPassiveGrab &&
1394           mode != XINotifyPassiveUngrab &&
1395           mode != NotifyUngrab)
1396         toplevel->has_pointer_focus = (focus_in) ? FALSE : TRUE;
1397       G_GNUC_FALLTHROUGH;
1398 
1399     case NotifyNonlinear:
1400     case NotifyNonlinearVirtual:
1401       if (mode != NotifyGrab &&
1402           mode != XINotifyPassiveGrab &&
1403           mode != XINotifyPassiveUngrab &&
1404           mode != NotifyUngrab)
1405         toplevel->has_focus_window = (focus_in) ? TRUE : FALSE;
1406       /* We pretend that the focus moves to the grab
1407        * window, so we pay attention to NotifyGrab
1408        * NotifyUngrab, and ignore NotifyWhileGrabbed
1409        */
1410       if (mode != NotifyWhileGrabbed)
1411         toplevel->has_focus = (focus_in) ? TRUE : FALSE;
1412       break;
1413     case NotifyPointer:
1414       /* The X server sends NotifyPointer/NotifyGrab,
1415        * but the pointer focus is ignored while a
1416        * grab is in effect
1417        */
1418       if (!x11_screen->wmspec_check_window &&
1419           mode != NotifyGrab &&
1420           mode != XINotifyPassiveGrab &&
1421           mode != XINotifyPassiveUngrab &&
1422           mode != NotifyUngrab)
1423         toplevel->has_pointer_focus = (focus_in) ? TRUE : FALSE;
1424       break;
1425     case NotifyInferior:
1426     case NotifyPointerRoot:
1427     case NotifyDetailNone:
1428     default:
1429       break;
1430     }
1431 
1432   if (HAS_FOCUS (toplevel) != had_focus)
1433     {
1434       GdkEvent *event;
1435 
1436       event = gdk_focus_event_new (surface, device, focus_in);
1437       gdk_display_put_event (gdk_surface_get_display (surface), event);
1438       gdk_event_unref (event);
1439     }
1440 }
1441 
1442 static GdkEvent *
gdk_x11_device_manager_xi2_translate_event(GdkEventTranslator * translator,GdkDisplay * display,const XEvent * xevent)1443 gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
1444                                             GdkDisplay         *display,
1445                                             const XEvent       *xevent)
1446 {
1447   GdkX11DeviceManagerXI2 *device_manager;
1448   const XGenericEventCookie *cookie;
1449   GdkDevice *device, *source_device;
1450   GdkSurface *surface;
1451   GdkX11Surface *impl;
1452   int scale;
1453   XIEvent *ev;
1454   GdkEvent *event;
1455 
1456   event = NULL;
1457 
1458   device_manager = (GdkX11DeviceManagerXI2 *) translator;
1459   cookie = &xevent->xcookie;
1460 
1461   if (xevent->type != GenericEvent ||
1462       cookie->extension != device_manager->opcode)
1463     return event;
1464 
1465   ev = (XIEvent *) cookie->data;
1466 
1467   if (!ev)
1468     return NULL;
1469 
1470   if (!get_event_surface (translator, ev, &surface))
1471     return NULL;
1472 
1473   if (surface && GDK_SURFACE_DESTROYED (surface))
1474     return NULL;
1475 
1476   scale = 1;
1477   if (surface)
1478     {
1479       impl = GDK_X11_SURFACE (surface);
1480       scale = impl->surface_scale;
1481     }
1482 
1483   if (ev->evtype == XI_Motion ||
1484       ev->evtype == XI_ButtonRelease)
1485     {
1486       if (_gdk_x11_moveresize_handle_event (xevent))
1487         return NULL;
1488     }
1489 
1490   switch (ev->evtype)
1491     {
1492     case XI_HierarchyChanged:
1493       handle_hierarchy_changed (device_manager,
1494                                 (XIHierarchyEvent *) ev);
1495       break;
1496     case XI_DeviceChanged:
1497       handle_device_changed (device_manager,
1498                              (XIDeviceChangedEvent *) ev);
1499       break;
1500     case XI_PropertyEvent:
1501       handle_property_change (device_manager,
1502                               (XIPropertyEvent *) ev);
1503       break;
1504     case XI_KeyPress:
1505     case XI_KeyRelease:
1506       {
1507         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1508         GdkKeymap *keymap = gdk_display_get_keymap (display);
1509         GdkModifierType consumed, state, orig_state;
1510         int layout, level;
1511         guint keyval;
1512         GdkTranslatedKey translated;
1513         GdkTranslatedKey no_lock;
1514 
1515         GDK_DISPLAY_NOTE (display, EVENTS,
1516                   g_message ("key %s:\twindow %ld\n"
1517                              "\tdevice:%u\n"
1518                              "\tsource device:%u\n"
1519                              "\tkey number: %u\n",
1520                              (ev->evtype == XI_KeyPress) ? "press" : "release",
1521                              xev->event,
1522                              xev->deviceid,
1523                              xev->sourceid,
1524                              xev->detail));
1525 
1526         state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1527 
1528         device = g_hash_table_lookup (device_manager->id_table,
1529                                       GUINT_TO_POINTER (xev->deviceid));
1530 
1531         source_device = g_hash_table_lookup (device_manager->id_table,
1532                                              GUINT_TO_POINTER (xev->sourceid));
1533 
1534         keyval = GDK_KEY_VoidSymbol;
1535 
1536         gdk_keymap_translate_keyboard_state (keymap,
1537                                              xev->detail,
1538                                              state,
1539                                              xev->group.effective,
1540                                              &keyval,
1541                                              &layout, &level, &consumed);
1542         orig_state = state;
1543         state &= ~consumed;
1544         _gdk_x11_keymap_add_virt_mods (keymap, &state);
1545         state |= orig_state;
1546 
1547         translated.keyval = keyval;
1548         translated.consumed = consumed;
1549         translated.layout = layout;
1550         translated.level = level;
1551 
1552         if (orig_state & GDK_LOCK_MASK)
1553           {
1554             orig_state &= ~GDK_LOCK_MASK;
1555 
1556             gdk_keymap_translate_keyboard_state (keymap,
1557                                                  xev->detail,
1558                                                  orig_state,
1559                                                  xev->group.effective,
1560                                                  &keyval,
1561                                                  &layout, &level, &consumed);
1562 
1563             no_lock.keyval = keyval;
1564             no_lock.consumed = consumed;
1565             no_lock.layout = layout;
1566             no_lock.level = level;
1567           }
1568         else
1569           {
1570             no_lock = translated;
1571           }
1572         event = gdk_key_event_new (xev->evtype == XI_KeyPress
1573                                      ? GDK_KEY_PRESS
1574                                      : GDK_KEY_RELEASE,
1575                                    surface,
1576                                    device,
1577                                    xev->time,
1578                                    xev->detail,
1579                                    state,
1580                                    gdk_x11_keymap_key_is_modifier (keymap, xev->detail),
1581                                    &translated,
1582                                    &no_lock);
1583 
1584         if (ev->evtype == XI_KeyPress)
1585           set_user_time (event);
1586 
1587         /* FIXME: emulate autorepeat on key
1588          * release? XI2 seems attached to Xkb.
1589          */
1590       }
1591 
1592       break;
1593     case XI_ButtonPress:
1594     case XI_ButtonRelease:
1595       {
1596         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1597 
1598         GDK_DISPLAY_NOTE (display, EVENTS,
1599                   g_message ("button %s:\twindow %ld\n"
1600                              "\tdevice:%u\n"
1601                              "\tsource device:%u\n"
1602                              "\tbutton number: %u\n"
1603                              "\tx,y: %.2f %.2f",
1604                              (ev->evtype == XI_ButtonPress) ? "press" : "release",
1605                              xev->event,
1606                              xev->deviceid,
1607                              xev->sourceid,
1608                              xev->detail,
1609                              xev->event_x, xev->event_y));
1610 
1611 #ifdef XINPUT_2_2
1612         if (xev->flags & XIPointerEmulated)
1613           return FALSE;
1614 #endif
1615 
1616         if (ev->evtype == XI_ButtonRelease &&
1617             (xev->detail >= 4 && xev->detail <= 7))
1618           return FALSE;
1619         else if (ev->evtype == XI_ButtonPress &&
1620                  (xev->detail >= 4 && xev->detail <= 7))
1621           {
1622             GdkScrollDirection direction;
1623 
1624             /* Button presses of button 4-7 are scroll events */
1625 
1626             if (xev->detail == 4)
1627               direction = GDK_SCROLL_UP;
1628             else if (xev->detail == 5)
1629               direction = GDK_SCROLL_DOWN;
1630             else if (xev->detail == 6)
1631               direction = GDK_SCROLL_LEFT;
1632             else
1633               direction = GDK_SCROLL_RIGHT;
1634 
1635             device = g_hash_table_lookup (device_manager->id_table,
1636                                           GUINT_TO_POINTER (xev->deviceid));
1637 
1638             source_device = g_hash_table_lookup (device_manager->id_table,
1639                                                  GUINT_TO_POINTER (xev->sourceid));
1640 
1641             event = gdk_scroll_event_new_discrete (surface,
1642                                                    source_device,
1643                                                    NULL,
1644                                                    xev->time,
1645                                                    _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
1646                                                    direction,
1647                                                    FALSE);
1648 
1649           }
1650         else
1651           {
1652             double x, y;
1653             double *axes;
1654 
1655             device = g_hash_table_lookup (device_manager->id_table,
1656                                           GUINT_TO_POINTER (xev->deviceid));
1657 
1658             source_device = g_hash_table_lookup (device_manager->id_table,
1659                                                  GUINT_TO_POINTER (xev->sourceid));
1660 
1661             axes = translate_axes (device,
1662                                    (double) xev->event_x / scale,
1663                                    (double) xev->event_y / scale,
1664                                    surface,
1665                                    &xev->valuators);
1666 
1667              x = (double) xev->event_x / scale;
1668              y = (double) xev->event_y / scale;
1669 
1670             event = gdk_button_event_new (ev->evtype == XI_ButtonPress
1671                                             ? GDK_BUTTON_PRESS
1672                                             : GDK_BUTTON_RELEASE,
1673                                           surface,
1674                                           device,
1675                                           source_device->last_tool,
1676                                           xev->time,
1677                                           _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
1678                                           xev->detail,
1679                                           x, y,
1680                                           axes);
1681           }
1682 
1683         if (ev->evtype == XI_ButtonPress)
1684 	  set_user_time (event);
1685 
1686         break;
1687       }
1688 
1689     case XI_Motion:
1690       {
1691         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1692         double delta_x, delta_y;
1693 
1694         double x, y;
1695         double *axes;
1696 
1697 #ifdef XINPUT_2_2
1698         if (xev->flags & XIPointerEmulated)
1699           return FALSE;
1700 #endif
1701 
1702         source_device = g_hash_table_lookup (device_manager->id_table,
1703                                              GUINT_TO_POINTER (xev->sourceid));
1704         device = g_hash_table_lookup (device_manager->id_table,
1705                                       GUINT_TO_POINTER (xev->deviceid));
1706 
1707         /* When scrolling, X might send events twice here; once with both the
1708          * device and the source device set to the physical device, and once
1709          * with the device set to the logical device.
1710          *
1711          * Since we are only interested in the latter, and
1712          * scroll_valuators_changed() updates the valuator cache for the
1713          * source device, we need to explicitly ignore the first event in
1714          * order to get the correct delta for the second.
1715          */
1716         if (gdk_x11_device_xi2_get_device_type ((GdkX11DeviceXI2 *) device) != GDK_X11_DEVICE_TYPE_PHYSICAL &&
1717             scroll_valuators_changed (GDK_X11_DEVICE_XI2 (source_device),
1718                                       &xev->valuators, &delta_x, &delta_y))
1719           {
1720             GdkModifierType state;
1721 
1722             GDK_DISPLAY_NOTE (display, EVENTS,
1723                      g_message ("smooth scroll: \n\tdevice: %u\n\tsource device: %u\n\twindow %ld\n\tdeltas: %f %f",
1724                                 xev->deviceid, xev->sourceid,
1725                                 xev->event, delta_x, delta_y));
1726 
1727             state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1728 
1729             if (gdk_device_get_source (source_device) != GDK_SOURCE_TOUCHPAD &&
1730                 ((delta_x == 0.0 && ABS (delta_y) == 1.0) ||
1731                  (ABS (delta_x) == 1.0 && delta_y == 0.0)))
1732               {
1733                 GdkScrollDirection direction;
1734 
1735                 if (delta_x > 0)
1736                   direction = GDK_SCROLL_RIGHT;
1737                 else if (delta_x < 0)
1738                   direction = GDK_SCROLL_LEFT;
1739                 else if (delta_y > 0)
1740                   direction = GDK_SCROLL_DOWN;
1741                 else
1742                   direction = GDK_SCROLL_UP;
1743 
1744                 event = gdk_scroll_event_new_discrete (surface,
1745                                                        device,
1746                                                        NULL,
1747                                                        xev->time,
1748                                                        state,
1749                                                        direction,
1750                                                        FALSE);
1751               }
1752             else
1753               {
1754                 event = gdk_scroll_event_new (surface,
1755                                               device,
1756                                               NULL,
1757                                               xev->time,
1758                                               state,
1759                                               delta_x,
1760                                               delta_y,
1761                                               delta_x == 0.0 && delta_y == 0.0);
1762               }
1763             break;
1764           }
1765 
1766         axes = translate_axes (device,
1767                                (double) xev->event_x / scale,
1768                                (double) xev->event_y / scale,
1769                                surface,
1770                                &xev->valuators);
1771 
1772         x = (double) xev->event_x / scale;
1773         y = (double) xev->event_y / scale;
1774 
1775         event = gdk_motion_event_new (surface,
1776                                       device,
1777                                       source_device->last_tool,
1778                                       xev->time,
1779                                       _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
1780                                       x, y,
1781                                       axes);
1782 
1783       }
1784       break;
1785 
1786 #ifdef XINPUT_2_2
1787     case XI_TouchBegin:
1788     case XI_TouchEnd:
1789       {
1790         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1791         GdkModifierType state;
1792 
1793         double x, y;
1794         double *axes;
1795 
1796         GDK_DISPLAY_NOTE (display, EVENTS,
1797                  g_message ("touch %s:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %s",
1798                             ev->evtype == XI_TouchBegin ? "begin" : "end",
1799                             xev->event,
1800                             xev->detail,
1801                             xev->flags & XITouchEmulatingPointer ? "true" : "false"));
1802 
1803         device = g_hash_table_lookup (device_manager->id_table,
1804                                       GUINT_TO_POINTER (xev->deviceid));
1805 
1806         source_device = g_hash_table_lookup (device_manager->id_table,
1807                                              GUINT_TO_POINTER (xev->sourceid));
1808 
1809         state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1810         if (ev->evtype == XI_TouchBegin)
1811           state |= GDK_BUTTON1_MASK;
1812 
1813         axes = translate_axes (device,
1814                                (double) xev->event_x / scale,
1815                                (double) xev->event_y / scale,
1816                                surface,
1817                                &xev->valuators);
1818 
1819         x = (double) xev->event_x / scale;
1820         y = (double) xev->event_y / scale;
1821 
1822         event = gdk_touch_event_new (ev->evtype == XI_TouchBegin
1823                                        ? GDK_TOUCH_BEGIN
1824                                        : GDK_TOUCH_END,
1825                                      GUINT_TO_POINTER (xev->detail),
1826                                      surface,
1827                                      device,
1828                                      xev->time,
1829                                      state,
1830                                      x, y,
1831                                      axes,
1832                                      xev->flags & XITouchEmulatingPointer);
1833 
1834         if (ev->evtype == XI_TouchBegin)
1835           set_user_time (event);
1836       }
1837       break;
1838 
1839     case XI_TouchUpdate:
1840       {
1841         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1842         GdkModifierType state;
1843 
1844         double x, y;
1845         double *axes;
1846 
1847         GDK_DISPLAY_NOTE (display, EVENTS,
1848                  g_message ("touch update:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %s",
1849                             xev->event,
1850                             xev->detail,
1851                             xev->flags & XITouchEmulatingPointer ? "true" : "false"));
1852 
1853         device = g_hash_table_lookup (device_manager->id_table,
1854                                       GINT_TO_POINTER (xev->deviceid));
1855 
1856         source_device = g_hash_table_lookup (device_manager->id_table,
1857                                              GUINT_TO_POINTER (xev->sourceid));
1858 
1859         state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1860         state |= GDK_BUTTON1_MASK;
1861 
1862         axes = translate_axes (device,
1863                                (double) xev->event_x / scale,
1864                                (double) xev->event_y / scale,
1865                                surface,
1866                                &xev->valuators);
1867 
1868         x = (double) xev->event_x / scale;
1869         y = (double) xev->event_y / scale;
1870 
1871         event = gdk_touch_event_new (GDK_TOUCH_UPDATE,
1872                                      GUINT_TO_POINTER (xev->detail),
1873                                      surface,
1874                                      device,
1875                                      xev->time,
1876                                      state,
1877                                      x, y,
1878                                      axes,
1879                                      xev->flags & XITouchEmulatingPointer);
1880       }
1881       break;
1882 #endif  /* XINPUT_2_2 */
1883 
1884     case XI_Enter:
1885     case XI_Leave:
1886       {
1887         XIEnterEvent *xev = (XIEnterEvent *) ev;
1888         GdkModifierType state;
1889 
1890         GDK_DISPLAY_NOTE (display, EVENTS,
1891                   g_message ("%s notify:\twindow %ld\n\tsubwindow:%ld\n"
1892                              "\tdevice: %u\n\tsource device: %u\n"
1893                              "\tnotify type: %u\n\tcrossing mode: %u",
1894                              (ev->evtype == XI_Enter) ? "enter" : "leave",
1895                              xev->event, xev->child,
1896                              xev->deviceid, xev->sourceid,
1897                              xev->detail, xev->mode));
1898 
1899         device = g_hash_table_lookup (device_manager->id_table,
1900                                       GINT_TO_POINTER (xev->deviceid));
1901 
1902         source_device = g_hash_table_lookup (device_manager->id_table,
1903                                              GUINT_TO_POINTER (xev->sourceid));
1904 
1905         state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1906 
1907         /* Ignore normal crossing events while there is an implicit grab.
1908          * We will receive a crossing event with one of the other details if
1909          * the implicit grab were finished (eg. releasing the button outside
1910          * the window triggers a XINotifyUngrab leave).
1911          */
1912         if (xev->mode == XINotifyNormal &&
1913             (state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
1914                       GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)))
1915           break;
1916 
1917         if (ev->evtype == XI_Enter &&
1918             xev->detail != XINotifyInferior && xev->mode != XINotifyPassiveUngrab &&
1919             GDK_IS_TOPLEVEL (surface))
1920           {
1921             if (gdk_x11_device_xi2_get_device_type ((GdkX11DeviceXI2 *) device) != GDK_X11_DEVICE_TYPE_LOGICAL)
1922               _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
1923             else
1924               {
1925                 GList *physical_devices, *l;
1926 
1927                 physical_devices = gdk_device_list_physical_devices (source_device);
1928 
1929                 for (l = physical_devices; l; l = l->next)
1930                   _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (l->data));
1931 
1932                 g_list_free (physical_devices);
1933               }
1934           }
1935 
1936         event = gdk_crossing_event_new (ev->evtype == XI_Enter
1937                                           ? GDK_ENTER_NOTIFY
1938                                           : GDK_LEAVE_NOTIFY,
1939                                         surface,
1940                                         device,
1941                                         xev->time,
1942                                         state,
1943                                         (double) xev->event_x / scale,
1944                                         (double) xev->event_y / scale,
1945                                         translate_crossing_mode (xev->mode),
1946                                         translate_notify_type (xev->detail));
1947       }
1948       break;
1949     case XI_FocusIn:
1950     case XI_FocusOut:
1951       {
1952         if (surface)
1953           {
1954             XIEnterEvent *xev = (XIEnterEvent *) ev;
1955 
1956             device = g_hash_table_lookup (device_manager->id_table,
1957                                           GINT_TO_POINTER (xev->deviceid));
1958 
1959             source_device = g_hash_table_lookup (device_manager->id_table,
1960                                                  GUINT_TO_POINTER (xev->sourceid));
1961 
1962             _gdk_device_manager_xi2_handle_focus (surface,
1963                                                   xev->event,
1964                                                   device,
1965                                                   source_device,
1966                                                   (ev->evtype == XI_FocusIn) ? TRUE : FALSE,
1967                                                   xev->detail,
1968                                                   xev->mode);
1969           }
1970       }
1971       break;
1972     default:
1973       break;
1974     }
1975 
1976   return event;
1977 }
1978 
1979 static GdkEventMask
gdk_x11_device_manager_xi2_get_handled_events(GdkEventTranslator * translator)1980 gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
1981 {
1982   return (GDK_KEY_PRESS_MASK |
1983           GDK_KEY_RELEASE_MASK |
1984           GDK_BUTTON_PRESS_MASK |
1985           GDK_BUTTON_RELEASE_MASK |
1986           GDK_SCROLL_MASK |
1987           GDK_ENTER_NOTIFY_MASK |
1988           GDK_LEAVE_NOTIFY_MASK |
1989           GDK_POINTER_MOTION_MASK |
1990           GDK_BUTTON1_MOTION_MASK |
1991           GDK_BUTTON2_MOTION_MASK |
1992           GDK_BUTTON3_MOTION_MASK |
1993           GDK_BUTTON_MOTION_MASK |
1994           GDK_FOCUS_CHANGE_MASK |
1995           GDK_TOUCH_MASK);
1996 }
1997 
1998 static void
gdk_x11_device_manager_xi2_select_surface_events(GdkEventTranslator * translator,Window window,GdkEventMask evmask)1999 gdk_x11_device_manager_xi2_select_surface_events (GdkEventTranslator *translator,
2000                                                  Window              window,
2001                                                  GdkEventMask        evmask)
2002 {
2003   XIEventMask event_mask;
2004 
2005   event_mask.deviceid = XIAllMasterDevices;
2006   event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (GDK_X11_DEVICE_MANAGER_XI2 (translator),
2007                                                               evmask,
2008                                                               &event_mask.mask_len);
2009 
2010   _gdk_x11_device_manager_xi2_select_events (GDK_X11_DEVICE_MANAGER_XI2 (translator), window, &event_mask);
2011   g_free (event_mask.mask);
2012 }
2013 
2014 static GdkSurface *
gdk_x11_device_manager_xi2_get_surface(GdkEventTranslator * translator,const XEvent * xevent)2015 gdk_x11_device_manager_xi2_get_surface (GdkEventTranslator *translator,
2016                                         const XEvent       *xevent)
2017 {
2018   GdkX11DeviceManagerXI2 *device_manager;
2019   XIEvent *ev;
2020   GdkSurface *surface = NULL;
2021 
2022   device_manager = (GdkX11DeviceManagerXI2 *) translator;
2023 
2024   if (xevent->type != GenericEvent ||
2025       xevent->xcookie.extension != device_manager->opcode)
2026     return NULL;
2027 
2028   ev = (XIEvent *) xevent->xcookie.data;
2029   if (!ev)
2030     return NULL;
2031 
2032   get_event_surface (translator, ev, &surface);
2033   return surface;
2034 }
2035 
2036 GdkDevice *
_gdk_x11_device_manager_xi2_lookup(GdkX11DeviceManagerXI2 * device_manager_xi2,int device_id)2037 _gdk_x11_device_manager_xi2_lookup (GdkX11DeviceManagerXI2 *device_manager_xi2,
2038                                     int                     device_id)
2039 {
2040   return g_hash_table_lookup (device_manager_xi2->id_table,
2041                               GINT_TO_POINTER (device_id));
2042 }
2043