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