]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdevicemanager-xi2.c
wayland: Synthesize fullscreen window state change
[~andy/gtk] / gdk / x11 / gdkdevicemanager-xi2.c
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 "gdkdisplayprivate.h"
26 #include "gdkeventtranslator.h"
27 #include "gdkprivate-x11.h"
28 #include "gdkintl.h"
29 #include "gdkkeysyms.h"
30 #include "gdkinternals.h"
31
32 #include <X11/Xlib.h>
33 #include <X11/Xutil.h>
34 #include <X11/extensions/XInput2.h>
35
36 #include <string.h>
37
38 struct _GdkX11DeviceManagerXI2
39 {
40   GdkX11DeviceManagerCore parent_object;
41
42   GHashTable *id_table;
43
44   GList *devices;
45
46   gint opcode;
47   gint major;
48   gint minor;
49 };
50
51 struct _GdkX11DeviceManagerXI2Class
52 {
53   GdkDeviceManagerClass parent_class;
54 };
55
56 static void     gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
57
58 G_DEFINE_TYPE_WITH_CODE (GdkX11DeviceManagerXI2, gdk_x11_device_manager_xi2, GDK_TYPE_X11_DEVICE_MANAGER_CORE,
59                          G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
60                                                 gdk_x11_device_manager_xi2_event_translator_init))
61
62
63 #define HAS_FOCUS(toplevel) ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
64
65
66 static void    gdk_x11_device_manager_xi2_constructed  (GObject      *object);
67 static void    gdk_x11_device_manager_xi2_dispose      (GObject      *object);
68 static void    gdk_x11_device_manager_xi2_set_property (GObject      *object,
69                                                         guint         prop_id,
70                                                         const GValue *value,
71                                                         GParamSpec   *pspec);
72 static void    gdk_x11_device_manager_xi2_get_property (GObject      *object,
73                                                         guint         prop_id,
74                                                         GValue       *value,
75                                                         GParamSpec   *pspec);
76
77 static GList * gdk_x11_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
78                                                         GdkDeviceType     type);
79 static GdkDevice * gdk_x11_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager);
80
81 static gboolean gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
82                                                             GdkDisplay         *display,
83                                                             GdkEvent           *event,
84                                                             XEvent             *xevent);
85 static GdkEventMask gdk_x11_device_manager_xi2_get_handled_events   (GdkEventTranslator *translator);
86 static void         gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
87                                                                      Window              window,
88                                                                      GdkEventMask        event_mask);
89 static GdkWindow *  gdk_x11_device_manager_xi2_get_window           (GdkEventTranslator *translator,
90                                                                      XEvent             *xevent);
91
92 enum {
93   PROP_0,
94   PROP_OPCODE,
95   PROP_MAJOR,
96   PROP_MINOR
97 };
98
99 static void
100 gdk_x11_device_manager_xi2_class_init (GdkX11DeviceManagerXI2Class *klass)
101 {
102   GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
103   GObjectClass *object_class = G_OBJECT_CLASS (klass);
104
105   object_class->constructed = gdk_x11_device_manager_xi2_constructed;
106   object_class->dispose = gdk_x11_device_manager_xi2_dispose;
107   object_class->set_property = gdk_x11_device_manager_xi2_set_property;
108   object_class->get_property = gdk_x11_device_manager_xi2_get_property;
109
110   device_manager_class->list_devices = gdk_x11_device_manager_xi2_list_devices;
111   device_manager_class->get_client_pointer = gdk_x11_device_manager_xi2_get_client_pointer;
112
113   g_object_class_install_property (object_class,
114                                    PROP_OPCODE,
115                                    g_param_spec_int ("opcode",
116                                                      P_("Opcode"),
117                                                      P_("Opcode for XInput2 requests"),
118                                                      0, G_MAXINT, 0,
119                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
120   g_object_class_install_property (object_class,
121                                    PROP_MAJOR,
122                                    g_param_spec_int ("major",
123                                                      P_("Major"),
124                                                      P_("Major version number"),
125                                                      0, G_MAXINT, 0,
126                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
127   g_object_class_install_property (object_class,
128                                    PROP_MINOR,
129                                    g_param_spec_int ("minor",
130                                                      P_("Minor"),
131                                                      P_("Minor version number"),
132                                                      0, G_MAXINT, 0,
133                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
134 }
135
136 static void
137 gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
138 {
139   device_manager->id_table = g_hash_table_new_full (g_direct_hash,
140                                                     g_direct_equal,
141                                                     NULL,
142                                                     (GDestroyNotify) g_object_unref);
143 }
144
145 static void
146 _gdk_x11_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
147                                            Window            xwindow,
148                                            XIEventMask      *event_mask)
149 {
150   GdkDisplay *display;
151   Display *xdisplay;
152
153   display = gdk_device_manager_get_display (device_manager);
154   xdisplay = GDK_DISPLAY_XDISPLAY (display);
155
156   XISelectEvents (xdisplay, xwindow, event_mask, 1);
157 }
158
159 static void
160 translate_valuator_class (GdkDisplay          *display,
161                           GdkDevice           *device,
162                           Atom                 valuator_label,
163                           gdouble              min,
164                           gdouble              max,
165                           gdouble              resolution)
166 {
167   static gboolean initialized = FALSE;
168   static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
169   GdkAxisUse use = GDK_AXIS_IGNORE;
170   GdkAtom label;
171   gint i;
172
173   if (!initialized)
174     {
175       label_atoms [GDK_AXIS_X] = gdk_x11_get_xatom_by_name_for_display (display, "Abs X");
176       label_atoms [GDK_AXIS_Y] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Y");
177       label_atoms [GDK_AXIS_PRESSURE] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Pressure");
178       label_atoms [GDK_AXIS_XTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt X");
179       label_atoms [GDK_AXIS_YTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt Y");
180       label_atoms [GDK_AXIS_WHEEL] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Wheel");
181       initialized = TRUE;
182     }
183
184   for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
185     {
186       if (label_atoms[i] == valuator_label)
187         {
188           use = i;
189           break;
190         }
191     }
192
193   if (valuator_label != None)
194     label = gdk_x11_xatom_to_atom_for_display (display, valuator_label);
195   else
196     label = GDK_NONE;
197
198   _gdk_device_add_axis (device, label, use, min, max, resolution);
199 }
200
201 static void
202 translate_device_classes (GdkDisplay      *display,
203                           GdkDevice       *device,
204                           XIAnyClassInfo **classes,
205                           guint            n_classes)
206 {
207   gint i;
208
209   g_object_freeze_notify (G_OBJECT (device));
210
211   for (i = 0; i < n_classes; i++)
212     {
213       XIAnyClassInfo *class_info = classes[i];
214
215       switch (class_info->type)
216         {
217         case XIKeyClass:
218           {
219             XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info;
220             gint i;
221
222             _gdk_device_set_keys (device, key_info->num_keycodes);
223
224             for (i = 0; i < key_info->num_keycodes; i++)
225               gdk_device_set_key (device, i, key_info->keycodes[i], 0);
226           }
227           break;
228         case XIValuatorClass:
229           {
230             XIValuatorClassInfo *valuator_info = (XIValuatorClassInfo *) class_info;
231             translate_valuator_class (display, device,
232                                       valuator_info->label,
233                                       valuator_info->min,
234                                       valuator_info->max,
235                                       valuator_info->resolution);
236           }
237           break;
238 #ifdef XINPUT_2_2
239         case XIScrollClass:
240           {
241             XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info;
242             GdkScrollDirection direction;
243
244             if (scroll_info->scroll_type == XIScrollTypeVertical)
245               direction = GDK_SCROLL_DOWN;
246             else
247               direction = GDK_SCROLL_RIGHT;
248
249             GDK_NOTE (INPUT,
250                       g_message ("\n\tscroll valuator %d: %s, increment %f",
251                                  scroll_info->number,
252                                  scroll_info->scroll_type == XIScrollTypeVertical
253                                                 ? "vertical"
254                                                 : "horizontal",
255                                  scroll_info->increment));
256
257             _gdk_x11_device_xi2_add_scroll_valuator (GDK_X11_DEVICE_XI2 (device),
258                                                      scroll_info->number,
259                                                      direction,
260                                                      scroll_info->increment);
261           }
262 #endif /* XINPUT_2_2 */
263         default:
264           /* Ignore */
265           break;
266         }
267     }
268
269   g_object_thaw_notify (G_OBJECT (device));
270 }
271
272 static gboolean
273 is_touch_device (XIAnyClassInfo **classes,
274                  guint            n_classes,
275                  GdkInputSource  *device_type,
276                  gint            *num_touches)
277 {
278 #ifdef XINPUT_2_2
279   guint i;
280
281   for (i = 0; i < n_classes; i++)
282     {
283       XITouchClassInfo *class = (XITouchClassInfo *) classes[i];
284
285       if (class->type != XITouchClass)
286         continue;
287
288       if (class->num_touches > 0)
289         {
290           if (class->mode == XIDirectTouch)
291             *device_type = GDK_SOURCE_TOUCHSCREEN;
292           else if (class->mode == XIDependentTouch)
293             *device_type = GDK_SOURCE_TOUCHPAD;
294           else
295             continue;
296
297           *num_touches = class->num_touches;
298
299           return TRUE;
300         }
301     }
302 #endif
303
304   return FALSE;
305 }
306
307 static GdkDevice *
308 create_device (GdkDeviceManager *device_manager,
309                GdkDisplay       *display,
310                XIDeviceInfo     *dev)
311 {
312   GdkInputSource input_source;
313   GdkInputSource touch_source;
314   GdkDeviceType type;
315   GdkDevice *device;
316   GdkInputMode mode;
317   gint num_touches = 0;
318
319   if (dev->use == XIMasterKeyboard || dev->use == XISlaveKeyboard)
320     input_source = GDK_SOURCE_KEYBOARD;
321   else if (dev->use == XISlavePointer &&
322            is_touch_device (dev->classes, dev->num_classes, &touch_source, &num_touches))
323     input_source = touch_source;
324   else
325     {
326       gchar *tmp_name;
327
328       tmp_name = g_ascii_strdown (dev->name, -1);
329
330       if (strstr (tmp_name, "eraser"))
331         input_source = GDK_SOURCE_ERASER;
332       else if (strstr (tmp_name, "cursor"))
333         input_source = GDK_SOURCE_CURSOR;
334       else if (strstr (tmp_name, "wacom") ||
335                strstr (tmp_name, "pen"))
336         input_source = GDK_SOURCE_PEN;
337       else
338         input_source = GDK_SOURCE_MOUSE;
339
340       g_free (tmp_name);
341     }
342
343   switch (dev->use)
344     {
345     case XIMasterKeyboard:
346     case XIMasterPointer:
347       type = GDK_DEVICE_TYPE_MASTER;
348       mode = GDK_MODE_SCREEN;
349       break;
350     case XISlaveKeyboard:
351     case XISlavePointer:
352       type = GDK_DEVICE_TYPE_SLAVE;
353       mode = GDK_MODE_DISABLED;
354       break;
355     case XIFloatingSlave:
356     default:
357       type = GDK_DEVICE_TYPE_FLOATING;
358       mode = GDK_MODE_DISABLED;
359       break;
360     }
361
362   GDK_NOTE (INPUT,
363             ({
364               const gchar *type_names[] = { "master", "slave", "floating" };
365               const gchar *source_names[] = { "mouse", "pen", "eraser", "cursor", "keyboard", "direct touch", "indirect touch" };
366               const gchar *mode_names[] = { "disabled", "screen", "window" };
367               g_message ("input device:\n\tname: %s\n\ttype: %s\n\tsource: %s\n\tmode: %s\n\thas cursor: %d\n\ttouches: %d",
368                          dev->name,
369                          type_names[type],
370                          source_names[input_source],
371                          mode_names[mode],
372                          dev->use == XIMasterPointer,
373                          num_touches);
374             }));
375
376   device = g_object_new (GDK_TYPE_X11_DEVICE_XI2,
377                          "name", dev->name,
378                          "type", type,
379                          "input-source", input_source,
380                          "input-mode", mode,
381                          "has-cursor", (dev->use == XIMasterPointer),
382                          "display", display,
383                          "device-manager", device_manager,
384                          "device-id", dev->deviceid,
385                          NULL);
386
387   translate_device_classes (display, device, dev->classes, dev->num_classes);
388
389   return device;
390 }
391
392 static GdkDevice *
393 add_device (GdkX11DeviceManagerXI2 *device_manager,
394             XIDeviceInfo           *dev,
395             gboolean                emit_signal)
396 {
397   GdkDisplay *display;
398   GdkDevice *device;
399
400   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
401   device = create_device (GDK_DEVICE_MANAGER (device_manager), display, dev);
402
403   g_hash_table_replace (device_manager->id_table,
404                         GINT_TO_POINTER (dev->deviceid),
405                         g_object_ref (device));
406
407   device_manager->devices = g_list_append (device_manager->devices, device);
408
409   if (emit_signal)
410     {
411       if (dev->use == XISlavePointer || dev->use == XISlaveKeyboard)
412         {
413           GdkDevice *master;
414
415           /* The device manager is already constructed, then
416            * keep the hierarchy coherent for the added device.
417            */
418           master = g_hash_table_lookup (device_manager->id_table,
419                                         GINT_TO_POINTER (dev->attachment));
420
421           _gdk_device_set_associated_device (device, master);
422           _gdk_device_add_slave (master, device);
423         }
424
425       g_signal_emit_by_name (device_manager, "device-added", device);
426     }
427
428   return device;
429 }
430
431 static void
432 remove_device (GdkX11DeviceManagerXI2 *device_manager,
433                gint                    device_id)
434 {
435   GdkDevice *device;
436
437   device = g_hash_table_lookup (device_manager->id_table,
438                                 GINT_TO_POINTER (device_id));
439
440   if (device)
441     {
442       device_manager->devices = g_list_remove (device_manager->devices, device);
443
444       g_signal_emit_by_name (device_manager, "device-removed", device);
445
446       g_object_run_dispose (G_OBJECT (device));
447
448       g_hash_table_remove (device_manager->id_table,
449                            GINT_TO_POINTER (device_id));
450     }
451 }
452
453 static void
454 relate_masters (gpointer key,
455                 gpointer value,
456                 gpointer user_data)
457 {
458   GdkX11DeviceManagerXI2 *device_manager;
459   GdkDevice *device, *relative;
460
461   device_manager = user_data;
462   device = g_hash_table_lookup (device_manager->id_table, key);
463   relative = g_hash_table_lookup (device_manager->id_table, value);
464
465   _gdk_device_set_associated_device (device, relative);
466   _gdk_device_set_associated_device (relative, device);
467 }
468
469 static void
470 relate_slaves (gpointer key,
471                gpointer value,
472                gpointer user_data)
473 {
474   GdkX11DeviceManagerXI2 *device_manager;
475   GdkDevice *slave, *master;
476
477   device_manager = user_data;
478   slave = g_hash_table_lookup (device_manager->id_table, key);
479   master = g_hash_table_lookup (device_manager->id_table, value);
480
481   _gdk_device_set_associated_device (slave, master);
482   _gdk_device_add_slave (master, slave);
483 }
484
485 static void
486 gdk_x11_device_manager_xi2_constructed (GObject *object)
487 {
488   GdkX11DeviceManagerXI2 *device_manager;
489   GdkDisplay *display;
490   GdkScreen *screen;
491   GHashTable *masters, *slaves;
492   Display *xdisplay;
493   XIDeviceInfo *info, *dev;
494   int ndevices, i;
495   XIEventMask event_mask;
496   unsigned char mask[2] = { 0 };
497
498   device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
499   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
500   xdisplay = GDK_DISPLAY_XDISPLAY (display);
501
502   g_assert (device_manager->major == 2);
503
504   masters = g_hash_table_new (NULL, NULL);
505   slaves = g_hash_table_new (NULL, NULL);
506
507   info = XIQueryDevice (xdisplay, XIAllDevices, &ndevices);
508
509   /* Initialize devices list */
510   for (i = 0; i < ndevices; i++)
511     {
512       dev = &info[i];
513
514       if (!dev->enabled)
515               continue;
516
517       add_device (device_manager, dev, FALSE);
518
519       if (dev->use == XIMasterPointer ||
520           dev->use == XIMasterKeyboard)
521         {
522           g_hash_table_insert (masters,
523                                GINT_TO_POINTER (dev->deviceid),
524                                GINT_TO_POINTER (dev->attachment));
525         }
526       else if (dev->use == XISlavePointer ||
527                dev->use == XISlaveKeyboard)
528         {
529           g_hash_table_insert (slaves,
530                                GINT_TO_POINTER (dev->deviceid),
531                                GINT_TO_POINTER (dev->attachment));
532         }
533     }
534
535   XIFreeDeviceInfo (info);
536
537   /* Stablish relationships between devices */
538   g_hash_table_foreach (masters, relate_masters, object);
539   g_hash_table_destroy (masters);
540
541   g_hash_table_foreach (slaves, relate_slaves, object);
542   g_hash_table_destroy (slaves);
543
544   /* Connect to hierarchy change events */
545   screen = gdk_display_get_default_screen (display);
546   XISetMask (mask, XI_HierarchyChanged);
547   XISetMask (mask, XI_DeviceChanged);
548
549   event_mask.deviceid = XIAllDevices;
550   event_mask.mask_len = sizeof (mask);
551   event_mask.mask = mask;
552
553   _gdk_x11_device_manager_xi2_select_events (GDK_DEVICE_MANAGER (object),
554                                              GDK_WINDOW_XID (gdk_screen_get_root_window (screen)),
555                                              &event_mask);
556 }
557
558 static void
559 gdk_x11_device_manager_xi2_dispose (GObject *object)
560 {
561   GdkX11DeviceManagerXI2 *device_manager;
562
563   device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
564
565   g_list_free_full (device_manager->devices, g_object_unref);
566   device_manager->devices = NULL;
567
568   if (device_manager->id_table)
569     {
570       g_hash_table_destroy (device_manager->id_table);
571       device_manager->id_table = NULL;
572     }
573
574   G_OBJECT_CLASS (gdk_x11_device_manager_xi2_parent_class)->dispose (object);
575 }
576
577 static GList *
578 gdk_x11_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
579                                          GdkDeviceType     type)
580 {
581   GdkX11DeviceManagerXI2 *device_manager_xi2;
582   GList *cur, *list = NULL;
583
584   device_manager_xi2 = GDK_X11_DEVICE_MANAGER_XI2 (device_manager);
585
586   for (cur = device_manager_xi2->devices; cur; cur = cur->next)
587     {
588       GdkDevice *dev = cur->data;
589
590       if (type == gdk_device_get_device_type (dev))
591         list = g_list_prepend (list, dev);
592     }
593
594   return list;
595 }
596
597 static GdkDevice *
598 gdk_x11_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager)
599 {
600   GdkX11DeviceManagerXI2 *device_manager_xi2;
601   GdkDisplay *display;
602   int device_id;
603
604   device_manager_xi2 = (GdkX11DeviceManagerXI2 *) device_manager;
605   display = gdk_device_manager_get_display (device_manager);
606
607   XIGetClientPointer (GDK_DISPLAY_XDISPLAY (display),
608                       None, &device_id);
609
610   return g_hash_table_lookup (device_manager_xi2->id_table,
611                               GINT_TO_POINTER (device_id));
612 }
613
614 static void
615 gdk_x11_device_manager_xi2_set_property (GObject      *object,
616                                          guint         prop_id,
617                                          const GValue *value,
618                                          GParamSpec   *pspec)
619 {
620   GdkX11DeviceManagerXI2 *device_manager;
621
622   device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
623
624   switch (prop_id)
625     {
626     case PROP_OPCODE:
627       device_manager->opcode = g_value_get_int (value);
628       break;
629     case PROP_MAJOR:
630       device_manager->major = g_value_get_int (value);
631       break;
632     case PROP_MINOR:
633       device_manager->minor = g_value_get_int (value);
634       break;
635     default:
636       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
637       break;
638     }
639 }
640
641 static void
642 gdk_x11_device_manager_xi2_get_property (GObject    *object,
643                                          guint       prop_id,
644                                          GValue     *value,
645                                          GParamSpec *pspec)
646 {
647   GdkX11DeviceManagerXI2 *device_manager;
648
649   device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
650
651   switch (prop_id)
652     {
653     case PROP_OPCODE:
654       g_value_set_int (value, device_manager->opcode);
655       break;
656     case PROP_MAJOR:
657       g_value_set_int (value, device_manager->major);
658       break;
659     case PROP_MINOR:
660       g_value_set_int (value, device_manager->minor);
661       break;
662     default:
663       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
664       break;
665     }
666 }
667
668 static void
669 gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
670 {
671   iface->translate_event = gdk_x11_device_manager_xi2_translate_event;
672   iface->get_handled_events = gdk_x11_device_manager_xi2_get_handled_events;
673   iface->select_window_events = gdk_x11_device_manager_xi2_select_window_events;
674   iface->get_window = gdk_x11_device_manager_xi2_get_window;
675 }
676
677 static void
678 handle_hierarchy_changed (GdkX11DeviceManagerXI2 *device_manager,
679                           XIHierarchyEvent       *ev)
680 {
681   GdkDisplay *display;
682   Display *xdisplay;
683   XIDeviceInfo *info;
684   int ndevices;
685   gint i;
686
687   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
688   xdisplay = GDK_DISPLAY_XDISPLAY (display);
689
690   for (i = 0; i < ev->num_info; i++)
691     {
692       if (ev->info[i].flags & XIDeviceEnabled)
693         {
694           gdk_x11_display_error_trap_push (display);
695           info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
696           gdk_x11_display_error_trap_pop_ignored (display);
697           if (info)
698             {
699               add_device (device_manager, &info[0], TRUE);
700               XIFreeDeviceInfo (info);
701             }
702         }
703       else if (ev->info[i].flags & XIDeviceDisabled)
704         remove_device (device_manager, ev->info[i].deviceid);
705       else if (ev->info[i].flags & XISlaveAttached ||
706                ev->info[i].flags & XISlaveDetached)
707         {
708           GdkDevice *master, *slave;
709
710           slave = g_hash_table_lookup (device_manager->id_table,
711                                        GINT_TO_POINTER (ev->info[i].deviceid));
712
713           if (!slave)
714             continue;
715
716           /* Remove old master info */
717           master = gdk_device_get_associated_device (slave);
718
719           if (master)
720             {
721               _gdk_device_remove_slave (master, slave);
722               _gdk_device_set_associated_device (slave, NULL);
723
724               g_signal_emit_by_name (device_manager, "device-changed", master);
725             }
726
727           /* Add new master if it's an attachment event */
728           if (ev->info[i].flags & XISlaveAttached)
729             {
730               gdk_x11_display_error_trap_push (display);
731               info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
732               gdk_x11_display_error_trap_pop_ignored (display);
733               if (info)
734                 {
735                   master = g_hash_table_lookup (device_manager->id_table,
736                                                 GINT_TO_POINTER (info->attachment));
737                   XIFreeDeviceInfo (info);
738                 }
739
740               if (master)
741                 {
742                   _gdk_device_set_associated_device (slave, master);
743                   _gdk_device_add_slave (master, slave);
744
745                   g_signal_emit_by_name (device_manager, "device-changed", master);
746                 }
747             }
748
749           g_signal_emit_by_name (device_manager, "device-changed", slave);
750         }
751     }
752 }
753
754 static void
755 handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
756                        XIDeviceChangedEvent   *ev)
757 {
758   GdkDisplay *display;
759   GdkDevice *device, *source_device;
760
761   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
762   device = g_hash_table_lookup (device_manager->id_table,
763                                 GUINT_TO_POINTER (ev->deviceid));
764   source_device = g_hash_table_lookup (device_manager->id_table,
765                                        GUINT_TO_POINTER (ev->sourceid));
766
767   if (device)
768     {
769       _gdk_device_reset_axes (device);
770       translate_device_classes (display, device, ev->classes, ev->num_classes);
771
772       g_signal_emit_by_name (G_OBJECT (device), "changed");
773     }
774
775   if (source_device)
776     _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
777 }
778
779 static GdkCrossingMode
780 translate_crossing_mode (gint mode)
781 {
782   switch (mode)
783     {
784     case NotifyNormal:
785       return GDK_CROSSING_NORMAL;
786     case NotifyGrab:
787       return GDK_CROSSING_GRAB;
788     case NotifyUngrab:
789       return GDK_CROSSING_UNGRAB;
790     default:
791       g_assert_not_reached ();
792     }
793 }
794
795 static GdkNotifyType
796 translate_notify_type (gint detail)
797 {
798   switch (detail)
799     {
800     case NotifyInferior:
801       return GDK_NOTIFY_INFERIOR;
802     case NotifyAncestor:
803       return GDK_NOTIFY_ANCESTOR;
804     case NotifyVirtual:
805       return GDK_NOTIFY_VIRTUAL;
806     case NotifyNonlinear:
807       return GDK_NOTIFY_NONLINEAR;
808     case NotifyNonlinearVirtual:
809       return GDK_NOTIFY_NONLINEAR_VIRTUAL;
810     default:
811       g_assert_not_reached ();
812     }
813 }
814
815 static gboolean
816 set_screen_from_root (GdkDisplay *display,
817                       GdkEvent   *event,
818                       Window      xrootwin)
819 {
820   GdkScreen *screen;
821
822   screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
823
824   if (screen)
825     {
826       gdk_event_set_screen (event, screen);
827
828       return TRUE;
829     }
830
831   return FALSE;
832 }
833
834 static void
835 set_user_time (GdkEvent *event)
836 {
837   GdkWindow *window;
838   guint32 time;
839
840   window = gdk_window_get_toplevel (event->any.window);
841   g_return_if_fail (GDK_IS_WINDOW (window));
842
843   time = gdk_event_get_time (event);
844
845   /* If an event doesn't have a valid timestamp, we shouldn't use it
846    * to update the latest user interaction time.
847    */
848   if (time != GDK_CURRENT_TIME)
849     gdk_x11_window_set_user_time (window, time);
850 }
851
852 static gdouble *
853 translate_axes (GdkDevice       *device,
854                 gdouble          x,
855                 gdouble          y,
856                 GdkWindow       *window,
857                 XIValuatorState *valuators)
858 {
859   guint n_axes, i;
860   gdouble *axes;
861   gdouble *vals;
862
863   g_object_get (device, "n-axes", &n_axes, NULL);
864
865   axes = g_new0 (gdouble, n_axes);
866   vals = valuators->values;
867
868   for (i = 0; i < valuators->mask_len * 8; i++)
869     {
870       GdkAxisUse use;
871       gdouble val;
872
873       if (!XIMaskIsSet (valuators->mask, i))
874         continue;
875
876       use = gdk_device_get_axis_use (device, i);
877       val = *vals++;
878
879       switch (use)
880         {
881         case GDK_AXIS_X:
882         case GDK_AXIS_Y:
883           if (gdk_device_get_mode (device) == GDK_MODE_WINDOW)
884             _gdk_device_translate_window_coord (device, window, i, val, &axes[i]);
885           else
886             {
887               if (use == GDK_AXIS_X)
888                 axes[i] = x;
889               else
890                 axes[i] = y;
891             }
892           break;
893         default:
894           _gdk_device_translate_axis (device, i, val, &axes[i]);
895           break;
896         }
897     }
898
899   return axes;
900 }
901
902 static gboolean
903 is_parent_of (GdkWindow *parent,
904               GdkWindow *child)
905 {
906   GdkWindow *w;
907
908   w = child;
909   while (w != NULL)
910     {
911       if (w == parent)
912         return TRUE;
913
914       w = gdk_window_get_parent (w);
915     }
916
917   return FALSE;
918 }
919
920 static gboolean
921 get_event_window (GdkEventTranslator *translator,
922                   XIEvent            *ev,
923                   GdkWindow         **window_p)
924 {
925   GdkDisplay *display;
926   GdkWindow *window = NULL;
927   gboolean should_have_window = TRUE;
928
929   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (translator));
930
931   switch (ev->evtype)
932     {
933     case XI_KeyPress:
934     case XI_KeyRelease:
935     case XI_ButtonPress:
936     case XI_ButtonRelease:
937     case XI_Motion:
938 #ifdef XINPUT_2_2
939     case XI_TouchUpdate:
940     case XI_TouchBegin:
941     case XI_TouchEnd:
942 #endif /* XINPUT_2_2 */
943       {
944         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
945
946         window = gdk_x11_window_lookup_for_display (display, xev->event);
947
948         /* Apply keyboard grabs to non-native windows */
949         if (ev->evtype == XI_KeyPress || ev->evtype == XI_KeyRelease)
950           {
951             GdkDeviceGrabInfo *info;
952             GdkDevice *device;
953             gulong serial;
954
955             device = g_hash_table_lookup (GDK_X11_DEVICE_MANAGER_XI2 (translator)->id_table,
956                                           GUINT_TO_POINTER (((XIDeviceEvent *) ev)->deviceid));
957
958             serial = _gdk_display_get_next_serial (display);
959             info = _gdk_display_has_device_grab (display, device, serial);
960
961             if (info &&
962                 (!is_parent_of (info->window, window) ||
963                  !info->owner_events))
964               {
965                 /* Report key event against grab window */
966                 window = info->window;
967               }
968           }
969       }
970       break;
971     case XI_Enter:
972     case XI_Leave:
973     case XI_FocusIn:
974     case XI_FocusOut:
975       {
976         XIEnterEvent *xev = (XIEnterEvent *) ev;
977
978         window = gdk_x11_window_lookup_for_display (display, xev->event);
979       }
980       break;
981     default:
982       should_have_window = FALSE;
983       break;
984     }
985
986   *window_p = window;
987
988   if (should_have_window && !window)
989     return FALSE;
990
991   return TRUE;
992 }
993
994 static gboolean
995 gdk_x11_device_manager_xi2_translate_core_event (GdkEventTranslator *translator,
996                                                  GdkDisplay         *display,
997                                                  GdkEvent           *event,
998                                                  XEvent             *xevent)
999 {
1000   GdkEventTranslatorIface *parent_iface;
1001   gboolean keyboard = FALSE;
1002   GdkDevice *device;
1003
1004   if ((xevent->type == KeyPress || xevent->type == KeyRelease) &&
1005       (xevent->xkey.keycode == 0 || xevent->xkey.serial == 0))
1006     {
1007       /* The X input methods (when triggered via XFilterEvent)
1008        * generate a core key press event with keycode 0 to signal the
1009        * end of a key sequence. We use the core translate_event
1010        * implementation to translate this event.
1011        *
1012        * Other less educated IM modules like to filter every keypress,
1013        * only to have these replaced by their own homegrown events,
1014        * these events oddly have serial=0, so we try to catch these.
1015        *
1016        * This is just a bandaid fix to keep xim working with a single
1017        * keyboard until XFilterEvent learns about XI2.
1018        */
1019       keyboard = TRUE;
1020     }
1021   else if (xevent->xany.send_event)
1022     {
1023       /* If another process sends us core events, process them; we
1024        * assume that it won't send us redundant core and XI2 events.
1025        * (At the moment, it's not possible to send XI2 events anyway.
1026        * In the future, an app that was trying to decide whether to
1027        * send core or XI2 events could look at the event mask on the
1028        * window to see which kind we are listening to.)
1029        */
1030       switch (xevent->type)
1031         {
1032         case KeyPress:
1033         case KeyRelease:
1034         case FocusIn:
1035         case FocusOut:
1036           keyboard = TRUE;
1037           break;
1038
1039         case ButtonPress:
1040         case ButtonRelease:
1041         case MotionNotify:
1042         case EnterNotify:
1043         case LeaveNotify:
1044           break;
1045
1046         default:
1047           return FALSE;
1048         }
1049     }
1050   else
1051     return FALSE;
1052
1053   parent_iface = g_type_interface_peek_parent (GDK_EVENT_TRANSLATOR_GET_IFACE (translator));
1054   if (!parent_iface->translate_event (translator, display, event, xevent))
1055     return FALSE;
1056
1057   /* The core device manager sets a core device on the event.
1058    * We need to override that with an XI2 device, since we are
1059    * using XI2.
1060    */
1061   device = gdk_x11_device_manager_xi2_get_client_pointer ((GdkDeviceManager *)translator);
1062   if (keyboard)
1063     device = gdk_device_get_associated_device (device);
1064   gdk_event_set_device (event, device);
1065
1066   return TRUE;
1067 }
1068
1069 static gboolean
1070 scroll_valuators_changed (GdkX11DeviceXI2 *device,
1071                           XIValuatorState *valuators,
1072                           gdouble         *dx,
1073                           gdouble         *dy)
1074 {
1075   gboolean has_scroll_valuators = FALSE;
1076   GdkScrollDirection direction;
1077   guint n_axes, i, n_val;
1078   gdouble *vals;
1079
1080   n_axes = gdk_device_get_n_axes (GDK_DEVICE (device));
1081   vals = valuators->values;
1082   *dx = *dy = 0;
1083   n_val = 0;
1084
1085   for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
1086     {
1087       gdouble delta;
1088
1089       if (!XIMaskIsSet (valuators->mask, i))
1090         continue;
1091
1092       if (_gdk_x11_device_xi2_get_scroll_delta (device, i, vals[n_val],
1093                                                 &direction, &delta))
1094         {
1095           has_scroll_valuators = TRUE;
1096
1097           if (direction == GDK_SCROLL_UP ||
1098               direction == GDK_SCROLL_DOWN)
1099             *dy = delta;
1100           else
1101             *dx = delta;
1102         }
1103
1104       n_val++;
1105     }
1106
1107   return has_scroll_valuators;
1108 }
1109
1110 static gboolean
1111 gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
1112                                             GdkDisplay         *display,
1113                                             GdkEvent           *event,
1114                                             XEvent             *xevent)
1115 {
1116   GdkX11DeviceManagerXI2 *device_manager;
1117   XGenericEventCookie *cookie;
1118   gboolean return_val = TRUE;
1119   GdkWindow *window;
1120   XIEvent *ev;
1121
1122   device_manager = (GdkX11DeviceManagerXI2 *) translator;
1123   cookie = &xevent->xcookie;
1124
1125   if (xevent->type != GenericEvent)
1126     return gdk_x11_device_manager_xi2_translate_core_event (translator, display, event, xevent);
1127   else if (cookie->extension != device_manager->opcode)
1128     return FALSE;
1129
1130   ev = (XIEvent *) cookie->data;
1131
1132   if (!ev)
1133     return FALSE;
1134
1135   if (!get_event_window (translator, ev, &window))
1136     return FALSE;
1137
1138   if (window && GDK_WINDOW_DESTROYED (window))
1139     return FALSE;
1140
1141   if (ev->evtype == XI_Motion ||
1142       ev->evtype == XI_ButtonRelease)
1143     {
1144       if (_gdk_x11_moveresize_handle_event (xevent))
1145         return FALSE;
1146     }
1147
1148   switch (ev->evtype)
1149     {
1150     case XI_HierarchyChanged:
1151       handle_hierarchy_changed (device_manager,
1152                                 (XIHierarchyEvent *) ev);
1153       return_val = FALSE;
1154       break;
1155     case XI_DeviceChanged:
1156       handle_device_changed (device_manager,
1157                              (XIDeviceChangedEvent *) ev);
1158       return_val = FALSE;
1159       break;
1160     case XI_KeyPress:
1161     case XI_KeyRelease:
1162       {
1163         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1164         GdkKeymap *keymap = gdk_keymap_get_for_display (display);
1165         GdkModifierType consumed, state;
1166         GdkDevice *device, *source_device;
1167
1168         event->key.type = xev->evtype == XI_KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
1169
1170         event->key.window = window;
1171
1172         event->key.time = xev->time;
1173         event->key.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1174         event->key.group = xev->group.effective;
1175
1176         event->key.hardware_keycode = xev->detail;
1177         event->key.is_modifier = gdk_x11_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
1178
1179         device = g_hash_table_lookup (device_manager->id_table,
1180                                       GUINT_TO_POINTER (xev->deviceid));
1181         gdk_event_set_device (event, device);
1182
1183         source_device = g_hash_table_lookup (device_manager->id_table,
1184                                              GUINT_TO_POINTER (xev->sourceid));
1185         gdk_event_set_source_device (event, source_device);
1186
1187         event->key.keyval = GDK_KEY_VoidSymbol;
1188
1189         gdk_keymap_translate_keyboard_state (keymap,
1190                                              event->key.hardware_keycode,
1191                                              event->key.state,
1192                                              event->key.group,
1193                                              &event->key.keyval,
1194                                              NULL, NULL, &consumed);
1195
1196         state = event->key.state & ~consumed;
1197         _gdk_x11_keymap_add_virt_mods (keymap, &state);
1198         event->key.state |= state;
1199
1200         _gdk_x11_event_translate_keyboard_string (&event->key);
1201
1202         if (ev->evtype == XI_KeyPress)
1203           set_user_time (event);
1204
1205         /* FIXME: emulate autorepeat on key
1206          * release? XI2 seems attached to Xkb.
1207          */
1208       }
1209
1210       break;
1211     case XI_ButtonPress:
1212     case XI_ButtonRelease:
1213       {
1214         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1215         GdkDevice *source_device;
1216
1217         if (ev->evtype == XI_ButtonRelease &&
1218             (xev->detail >= 4 && xev->detail <= 7))
1219           return FALSE;
1220         else if (ev->evtype == XI_ButtonPress &&
1221                  (xev->detail >= 4 && xev->detail <= 7))
1222           {
1223             /* Button presses of button 4-7 are scroll events */
1224             event->scroll.type = GDK_SCROLL;
1225
1226             if (xev->detail == 4)
1227               event->scroll.direction = GDK_SCROLL_UP;
1228             else if (xev->detail == 5)
1229               event->scroll.direction = GDK_SCROLL_DOWN;
1230             else if (xev->detail == 6)
1231               event->scroll.direction = GDK_SCROLL_LEFT;
1232             else
1233               event->scroll.direction = GDK_SCROLL_RIGHT;
1234
1235             event->scroll.window = window;
1236             event->scroll.time = xev->time;
1237             event->scroll.x = (gdouble) xev->event_x;
1238             event->scroll.y = (gdouble) xev->event_y;
1239             event->scroll.x_root = (gdouble) xev->root_x;
1240             event->scroll.y_root = (gdouble) xev->root_y;
1241             event->scroll.delta_x = 0;
1242             event->scroll.delta_y = 0;
1243
1244             event->scroll.device = g_hash_table_lookup (device_manager->id_table,
1245                                                         GUINT_TO_POINTER (xev->deviceid));
1246
1247             source_device = g_hash_table_lookup (device_manager->id_table,
1248                                                  GUINT_TO_POINTER (xev->sourceid));
1249             gdk_event_set_source_device (event, source_device);
1250
1251             event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1252
1253 #ifdef XINPUT_2_2
1254             if (xev->flags & XIPointerEmulated)
1255               _gdk_event_set_pointer_emulated (event, TRUE);
1256 #endif
1257           }
1258         else
1259           {
1260             event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
1261
1262             event->button.window = window;
1263             event->button.time = xev->time;
1264             event->button.x = (gdouble) xev->event_x;
1265             event->button.y = (gdouble) xev->event_y;
1266             event->button.x_root = (gdouble) xev->root_x;
1267             event->button.y_root = (gdouble) xev->root_y;
1268
1269             event->button.device = g_hash_table_lookup (device_manager->id_table,
1270                                                         GUINT_TO_POINTER (xev->deviceid));
1271
1272             source_device = g_hash_table_lookup (device_manager->id_table,
1273                                                  GUINT_TO_POINTER (xev->sourceid));
1274             gdk_event_set_source_device (event, source_device);
1275
1276             event->button.axes = translate_axes (event->button.device,
1277                                                  event->button.x,
1278                                                  event->button.y,
1279                                                  event->button.window,
1280                                                  &xev->valuators);
1281
1282             if (gdk_device_get_mode (event->button.device) == GDK_MODE_WINDOW)
1283               {
1284                 GdkDevice *device = event->button.device;
1285
1286                 /* Update event coordinates from axes */
1287                 gdk_device_get_axis (device, event->button.axes, GDK_AXIS_X, &event->button.x);
1288                 gdk_device_get_axis (device, event->button.axes, GDK_AXIS_Y, &event->button.y);
1289               }
1290
1291             event->button.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1292
1293             event->button.button = xev->detail;
1294           }
1295
1296 #ifdef XINPUT_2_2
1297         if (xev->flags & XIPointerEmulated)
1298           _gdk_event_set_pointer_emulated (event, TRUE);
1299 #endif
1300
1301         if (return_val == FALSE)
1302           break;
1303
1304         if (!set_screen_from_root (display, event, xev->root))
1305           {
1306             return_val = FALSE;
1307             break;
1308           }
1309
1310         if (ev->evtype == XI_ButtonPress)
1311           set_user_time (event);
1312
1313         break;
1314       }
1315
1316     case XI_Motion:
1317       {
1318         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1319         GdkDevice *source_device, *device;
1320         gdouble delta_x, delta_y;
1321
1322         source_device = g_hash_table_lookup (device_manager->id_table,
1323                                              GUINT_TO_POINTER (xev->sourceid));
1324         device = g_hash_table_lookup (device_manager->id_table,
1325                                       GUINT_TO_POINTER (xev->deviceid));
1326
1327         /* When scrolling, X might send events twice here; once with both the
1328          * device and the source device set to the physical device, and once
1329          * with the device set to the master device.
1330          * Since we are only interested in the latter, and
1331          * scroll_valuators_changed() updates the valuator cache for the
1332          * source device, we need to explicitly ignore the first event in
1333          * order to get the correct delta for the second.
1334          */
1335         if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_SLAVE &&
1336             scroll_valuators_changed (GDK_X11_DEVICE_XI2 (source_device),
1337                                       &xev->valuators, &delta_x, &delta_y))
1338           {
1339             event->scroll.type = GDK_SCROLL;
1340             event->scroll.direction = GDK_SCROLL_SMOOTH;
1341
1342             GDK_NOTE(EVENTS,
1343                      g_message ("smooth scroll: %s\n\tdevice: %u\n\tsource device: %u\n\twindow %ld\n\tdeltas: %f %f",
1344 #ifdef XINPUT_2_2
1345                                 (xev->flags & XIPointerEmulated) ? "emulated" : "",
1346 #else
1347                                  "",
1348 #endif
1349                                 xev->deviceid, xev->sourceid,
1350                                 xev->event, delta_x, delta_y));
1351
1352
1353             event->scroll.window = window;
1354             event->scroll.time = xev->time;
1355             event->scroll.x = (gdouble) xev->event_x;
1356             event->scroll.y = (gdouble) xev->event_y;
1357             event->scroll.x_root = (gdouble) xev->root_x;
1358             event->scroll.y_root = (gdouble) xev->root_y;
1359             event->scroll.delta_x = delta_x;
1360             event->scroll.delta_y = delta_y;
1361
1362             event->scroll.device = device;
1363             gdk_event_set_source_device (event, source_device);
1364
1365             event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1366             break;
1367           }
1368
1369         event->motion.type = GDK_MOTION_NOTIFY;
1370         event->motion.window = window;
1371         event->motion.time = xev->time;
1372         event->motion.x = (gdouble) xev->event_x;
1373         event->motion.y = (gdouble) xev->event_y;
1374         event->motion.x_root = (gdouble) xev->root_x;
1375         event->motion.y_root = (gdouble) xev->root_y;
1376
1377         event->motion.device = device;
1378         gdk_event_set_source_device (event, source_device);
1379
1380         event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1381
1382 #ifdef XINPUT_2_2
1383         if (xev->flags & XIPointerEmulated)
1384           _gdk_event_set_pointer_emulated (event, TRUE);
1385 #endif
1386
1387         /* There doesn't seem to be motion hints in XI */
1388         event->motion.is_hint = FALSE;
1389
1390         event->motion.axes = translate_axes (event->motion.device,
1391                                              event->motion.x,
1392                                              event->motion.y,
1393                                              event->motion.window,
1394                                              &xev->valuators);
1395
1396         if (gdk_device_get_mode (event->motion.device) == GDK_MODE_WINDOW)
1397           {
1398             GdkDevice *device = event->motion.device;
1399
1400             /* Update event coordinates from axes */
1401             gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_X, &event->motion.x);
1402             gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_Y, &event->motion.y);
1403           }
1404       }
1405       break;
1406
1407 #ifdef XINPUT_2_2
1408     case XI_TouchBegin:
1409     case XI_TouchEnd:
1410       {
1411         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1412         GdkDevice *source_device;
1413
1414         GDK_NOTE(EVENTS,
1415                  g_message ("touch %s:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %d",
1416                             ev->evtype == XI_TouchBegin ? "begin" : "end",
1417                             xev->event,
1418                             xev->detail,
1419                             xev->flags & XITouchEmulatingPointer));
1420
1421         if (ev->evtype == XI_TouchBegin)
1422           event->touch.type = GDK_TOUCH_BEGIN;
1423         else if (ev->evtype == XI_TouchEnd)
1424           event->touch.type = GDK_TOUCH_END;
1425
1426         event->touch.window = window;
1427         event->touch.time = xev->time;
1428         event->touch.x = (gdouble) xev->event_x;
1429         event->touch.y = (gdouble) xev->event_y;
1430         event->touch.x_root = (gdouble) xev->root_x;
1431         event->touch.y_root = (gdouble) xev->root_y;
1432
1433         event->touch.device = g_hash_table_lookup (device_manager->id_table,
1434                                                    GUINT_TO_POINTER (xev->deviceid));
1435
1436         source_device = g_hash_table_lookup (device_manager->id_table,
1437                                              GUINT_TO_POINTER (xev->sourceid));
1438         gdk_event_set_source_device (event, source_device);
1439
1440         event->touch.axes = translate_axes (event->touch.device,
1441                                             event->touch.x,
1442                                             event->touch.y,
1443                                             event->touch.window,
1444                                             &xev->valuators);
1445
1446         if (gdk_device_get_mode (event->touch.device) == GDK_MODE_WINDOW)
1447           {
1448             GdkDevice *device = event->touch.device;
1449
1450             /* Update event coordinates from axes */
1451             gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_X, &event->touch.x);
1452             gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_Y, &event->touch.y);
1453           }
1454
1455         event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1456
1457         if (ev->evtype == XI_TouchBegin)
1458           event->touch.state |= GDK_BUTTON1_MASK;
1459
1460         event->touch.sequence = GUINT_TO_POINTER (xev->detail);
1461
1462         if (xev->flags & XITouchEmulatingPointer)
1463           {
1464             event->touch.emulating_pointer = TRUE;
1465             _gdk_event_set_pointer_emulated (event, TRUE);
1466           }
1467
1468         if (return_val == FALSE)
1469           break;
1470
1471         if (!set_screen_from_root (display, event, xev->root))
1472           {
1473             return_val = FALSE;
1474             break;
1475           }
1476
1477         if (ev->evtype == XI_TouchBegin)
1478           set_user_time (event);
1479       }
1480       break;
1481
1482     case XI_TouchUpdate:
1483       {
1484         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1485         GdkDevice *source_device;
1486
1487         GDK_NOTE(EVENTS,
1488                  g_message ("touch update:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %d",
1489                             xev->event,
1490                             xev->detail,
1491                             xev->flags & XITouchEmulatingPointer));
1492
1493         event->touch.window = window;
1494         event->touch.sequence = GUINT_TO_POINTER (xev->detail);
1495         event->touch.type = GDK_TOUCH_UPDATE;
1496         event->touch.time = xev->time;
1497         event->touch.x = (gdouble) xev->event_x;
1498         event->touch.y = (gdouble) xev->event_y;
1499         event->touch.x_root = (gdouble) xev->root_x;
1500         event->touch.y_root = (gdouble) xev->root_y;
1501
1502         event->touch.device = g_hash_table_lookup (device_manager->id_table,
1503                                                    GINT_TO_POINTER (xev->deviceid));
1504
1505         source_device = g_hash_table_lookup (device_manager->id_table,
1506                                              GUINT_TO_POINTER (xev->sourceid));
1507         gdk_event_set_source_device (event, source_device);
1508
1509         event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1510
1511         event->touch.state |= GDK_BUTTON1_MASK;
1512
1513         if (xev->flags & XITouchEmulatingPointer)
1514           {
1515             event->touch.emulating_pointer = TRUE;
1516             _gdk_event_set_pointer_emulated (event, TRUE);
1517           }
1518
1519         event->touch.axes = translate_axes (event->touch.device,
1520                                             event->touch.x,
1521                                             event->touch.y,
1522                                             event->touch.window,
1523                                             &xev->valuators);
1524
1525         if (gdk_device_get_mode (event->touch.device) == GDK_MODE_WINDOW)
1526           {
1527             GdkDevice *device = event->touch.device;
1528
1529             /* Update event coordinates from axes */
1530             gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_X, &event->touch.x);
1531             gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_Y, &event->touch.y);
1532           }
1533       }
1534       break;
1535 #endif  /* XINPUT_2_2 */
1536
1537     case XI_Enter:
1538     case XI_Leave:
1539       {
1540         XIEnterEvent *xev = (XIEnterEvent *) ev;
1541         GdkDevice *device, *source_device;
1542
1543         event->crossing.type = (ev->evtype == XI_Enter) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
1544
1545         event->crossing.x = (gdouble) xev->event_x;
1546         event->crossing.y = (gdouble) xev->event_y;
1547         event->crossing.x_root = (gdouble) xev->root_x;
1548         event->crossing.y_root = (gdouble) xev->root_y;
1549         event->crossing.time = xev->time;
1550         event->crossing.focus = xev->focus;
1551
1552         event->crossing.window = window;
1553         event->crossing.subwindow = gdk_x11_window_lookup_for_display (display, xev->child);
1554
1555         device = g_hash_table_lookup (device_manager->id_table,
1556                                       GINT_TO_POINTER (xev->deviceid));
1557         gdk_event_set_device (event, device);
1558
1559         source_device = g_hash_table_lookup (device_manager->id_table,
1560                                              GUINT_TO_POINTER (xev->sourceid));
1561         gdk_event_set_source_device (event, source_device);
1562         _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
1563
1564         event->crossing.mode = translate_crossing_mode (xev->mode);
1565         event->crossing.detail = translate_notify_type (xev->detail);
1566         event->crossing.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1567       }
1568       break;
1569     case XI_FocusIn:
1570     case XI_FocusOut:
1571       {
1572         if (window)
1573           {
1574             XIEnterEvent *xev = (XIEnterEvent *) ev;
1575             GdkDevice *device, *source_device;
1576
1577             device = g_hash_table_lookup (device_manager->id_table,
1578                                           GINT_TO_POINTER (xev->deviceid));
1579
1580             source_device = g_hash_table_lookup (device_manager->id_table,
1581                                                  GUINT_TO_POINTER (xev->sourceid));
1582
1583             _gdk_device_manager_core_handle_focus (window,
1584                                                    xev->event,
1585                                                    device,
1586                                                    source_device,
1587                                                    (ev->evtype == XI_FocusIn) ? TRUE : FALSE,
1588                                                    xev->detail,
1589                                                    xev->mode);
1590           }
1591
1592         return_val = FALSE;
1593       }
1594       break;
1595     default:
1596       return_val = FALSE;
1597       break;
1598     }
1599
1600   event->any.send_event = cookie->send_event;
1601
1602   if (return_val)
1603     {
1604       if (event->any.window)
1605         g_object_ref (event->any.window);
1606
1607       if (((event->any.type == GDK_ENTER_NOTIFY) ||
1608            (event->any.type == GDK_LEAVE_NOTIFY)) &&
1609           (event->crossing.subwindow != NULL))
1610         g_object_ref (event->crossing.subwindow);
1611     }
1612   else
1613     {
1614       /* Mark this event as having no resources to be freed */
1615       event->any.window = NULL;
1616       event->any.type = GDK_NOTHING;
1617     }
1618
1619   return return_val;
1620 }
1621
1622 static GdkEventMask
1623 gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
1624 {
1625   return (GDK_KEY_PRESS_MASK |
1626           GDK_KEY_RELEASE_MASK |
1627           GDK_BUTTON_PRESS_MASK |
1628           GDK_BUTTON_RELEASE_MASK |
1629           GDK_SCROLL_MASK |
1630           GDK_ENTER_NOTIFY_MASK |
1631           GDK_LEAVE_NOTIFY_MASK |
1632           GDK_POINTER_MOTION_MASK |
1633           GDK_POINTER_MOTION_HINT_MASK |
1634           GDK_BUTTON1_MOTION_MASK |
1635           GDK_BUTTON2_MOTION_MASK |
1636           GDK_BUTTON3_MOTION_MASK |
1637           GDK_BUTTON_MOTION_MASK |
1638           GDK_FOCUS_CHANGE_MASK |
1639           GDK_TOUCH_MASK);
1640 }
1641
1642 static void
1643 gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
1644                                                  Window              window,
1645                                                  GdkEventMask        evmask)
1646 {
1647   GdkDeviceManager *device_manager;
1648   XIEventMask event_mask;
1649
1650   device_manager = GDK_DEVICE_MANAGER (translator);
1651
1652   event_mask.deviceid = XIAllMasterDevices;
1653   event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (GDK_X11_DEVICE_MANAGER_XI2 (device_manager),
1654                                                               evmask,
1655                                                               &event_mask.mask_len);
1656
1657   _gdk_x11_device_manager_xi2_select_events (device_manager, window, &event_mask);
1658   g_free (event_mask.mask);
1659 }
1660
1661 static GdkWindow *
1662 gdk_x11_device_manager_xi2_get_window (GdkEventTranslator *translator,
1663                                        XEvent             *xevent)
1664 {
1665   GdkX11DeviceManagerXI2 *device_manager;
1666   XIEvent *ev;
1667   GdkWindow *window = NULL;
1668
1669   device_manager = (GdkX11DeviceManagerXI2 *) translator;
1670
1671   if (xevent->type != GenericEvent ||
1672       xevent->xcookie.extension != device_manager->opcode)
1673     return NULL;
1674
1675   ev = (XIEvent *) xevent->xcookie.data;
1676
1677   get_event_window (translator, ev, &window);
1678   return window;
1679 }
1680
1681 GdkDevice *
1682 _gdk_x11_device_manager_xi2_lookup (GdkX11DeviceManagerXI2 *device_manager_xi2,
1683                                     gint                    device_id)
1684 {
1685   return g_hash_table_lookup (device_manager_xi2->id_table,
1686                               GINT_TO_POINTER (device_id));
1687 }