]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdevicemanager-xi2.c
Merge branch 'master' into broadway
[~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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include "gdkdevicemanager-xi2.h"
23
24 #include <gdk/gdkdeviceprivate.h>
25 #include "gdkeventtranslator.h"
26 #include "gdkdevice-xi2.h"
27 #include "gdkkeysyms.h"
28 #include "gdkprivate-x11.h"
29 #include "gdkx.h"
30
31 #include <string.h>
32
33 #define HAS_FOCUS(toplevel) ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
34
35
36 static void    gdk_device_manager_xi2_constructed (GObject *object);
37 static void    gdk_device_manager_xi2_dispose     (GObject *object);
38
39 static GList * gdk_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
40                                                     GdkDeviceType     type);
41 static GdkDevice * gdk_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager);
42
43 static void     gdk_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
44
45 static gboolean gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
46                                                         GdkDisplay         *display,
47                                                         GdkEvent           *event,
48                                                         XEvent             *xevent);
49 static GdkEventMask gdk_device_manager_xi2_get_handled_events   (GdkEventTranslator *translator);
50 static void         gdk_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
51                                                                  Window              window,
52                                                                  GdkEventMask        event_mask);
53
54
55 G_DEFINE_TYPE_WITH_CODE (GdkDeviceManagerXI2, gdk_device_manager_xi2, GDK_TYPE_DEVICE_MANAGER,
56                          G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
57                                                 gdk_device_manager_xi2_event_translator_init))
58
59
60 static void
61 gdk_device_manager_xi2_class_init (GdkDeviceManagerXI2Class *klass)
62 {
63   GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
64   GObjectClass *object_class = G_OBJECT_CLASS (klass);
65
66   object_class->constructed = gdk_device_manager_xi2_constructed;
67   object_class->dispose = gdk_device_manager_xi2_dispose;
68
69   device_manager_class->list_devices = gdk_device_manager_xi2_list_devices;
70   device_manager_class->get_client_pointer = gdk_device_manager_xi2_get_client_pointer;
71 }
72
73 static void
74 gdk_device_manager_xi2_init (GdkDeviceManagerXI2 *device_manager)
75 {
76   device_manager->id_table = g_hash_table_new_full (g_direct_hash,
77                                                     g_direct_equal,
78                                                     NULL,
79                                                     (GDestroyNotify) g_object_unref);
80 }
81
82 static void
83 _gdk_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
84                                        Window            xwindow,
85                                        XIEventMask      *event_mask)
86 {
87   GdkDisplay *display;
88   Display *xdisplay;
89
90   display = gdk_device_manager_get_display (device_manager);
91   xdisplay = GDK_DISPLAY_XDISPLAY (display);
92
93   XISelectEvents (xdisplay, xwindow, event_mask, 1);
94 }
95
96 static void
97 translate_valuator_class (GdkDisplay          *display,
98                           GdkDevice           *device,
99                           XIValuatorClassInfo *info,
100                           gint                 n_valuator)
101 {
102   static gboolean initialized = FALSE;
103   static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
104   GdkAxisUse use = GDK_AXIS_IGNORE;
105   GdkAtom label;
106   gint i;
107
108   if (!initialized)
109     {
110       label_atoms [GDK_AXIS_X] = gdk_x11_get_xatom_by_name_for_display (display, "Abs X");
111       label_atoms [GDK_AXIS_Y] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Y");
112       label_atoms [GDK_AXIS_PRESSURE] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Pressure");
113       label_atoms [GDK_AXIS_XTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt X");
114       label_atoms [GDK_AXIS_YTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt Y");
115       label_atoms [GDK_AXIS_WHEEL] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Wheel");
116       initialized = TRUE;
117     }
118
119   for (i = GDK_AXIS_IGNORE; i <= GDK_AXIS_LAST; i++)
120     {
121       if (label_atoms[i] == info->label)
122         {
123           use = i;
124           break;
125         }
126     }
127
128   if (info->label != None)
129     label = gdk_x11_xatom_to_atom_for_display (display, info->label);
130   else
131     label = GDK_NONE;
132
133   _gdk_device_add_axis (device,
134                         label,
135                         use,
136                         info->min,
137                         info->max,
138                         info->resolution);
139 }
140
141 static void
142 translate_device_classes (GdkDisplay      *display,
143                           GdkDevice       *device,
144                           XIAnyClassInfo **classes,
145                           guint            n_classes)
146 {
147   gint i, n_valuator = 0;
148
149   g_object_freeze_notify (G_OBJECT (device));
150
151   for (i = 0; i < n_classes; i++)
152     {
153       XIAnyClassInfo *class_info = classes[i];
154
155       switch (class_info->type)
156         {
157         case XIKeyClass:
158           {
159             XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info;
160             gint i;
161
162             _gdk_device_set_keys (device, key_info->num_keycodes);
163
164             for (i = 0; i < key_info->num_keycodes; i++)
165               gdk_device_set_key (device, i, key_info->keycodes[i], 0);
166           }
167           break;
168         case XIValuatorClass:
169           translate_valuator_class (display, device,
170                                     (XIValuatorClassInfo *) class_info,
171                                     n_valuator);
172           n_valuator++;
173           break;
174         default:
175           /* Ignore */
176           break;
177         }
178     }
179
180   g_object_thaw_notify (G_OBJECT (device));
181 }
182
183 static GdkDevice *
184 create_device (GdkDeviceManager *device_manager,
185                GdkDisplay       *display,
186                XIDeviceInfo     *dev)
187 {
188   GdkInputSource input_source;
189   GdkDeviceType type;
190   GdkDevice *device;
191   GdkInputMode mode;
192
193   if (dev->use == XIMasterKeyboard || dev->use == XISlaveKeyboard)
194     input_source = GDK_SOURCE_KEYBOARD;
195   else
196     {
197       gchar *tmp_name;
198
199       tmp_name = g_ascii_strdown (dev->name, -1);
200
201       if (strstr (tmp_name, "eraser"))
202         input_source = GDK_SOURCE_ERASER;
203       else if (strstr (tmp_name, "cursor"))
204         input_source = GDK_SOURCE_CURSOR;
205       else if (strstr (tmp_name, "wacom") ||
206                strstr (tmp_name, "pen"))
207         input_source = GDK_SOURCE_PEN;
208       else
209         input_source = GDK_SOURCE_MOUSE;
210
211       g_free (tmp_name);
212     }
213
214   switch (dev->use)
215     {
216     case XIMasterKeyboard:
217     case XIMasterPointer:
218       type = GDK_DEVICE_TYPE_MASTER;
219       mode = GDK_MODE_SCREEN;
220       break;
221     case XISlaveKeyboard:
222     case XISlavePointer:
223       type = GDK_DEVICE_TYPE_SLAVE;
224       mode = GDK_MODE_DISABLED;
225       break;
226     case XIFloatingSlave:
227     default:
228       type = GDK_DEVICE_TYPE_FLOATING;
229       mode = GDK_MODE_DISABLED;
230       break;
231     }
232
233   device = g_object_new (GDK_TYPE_DEVICE_XI2,
234                          "name", dev->name,
235                          "type", type,
236                          "input-source", input_source,
237                          "input-mode", mode,
238                          "has-cursor", (dev->use == XIMasterPointer),
239                          "display", display,
240                          "device-manager", device_manager,
241                          "device-id", dev->deviceid,
242                          NULL);
243
244   translate_device_classes (display, device, dev->classes, dev->num_classes);
245
246   return device;
247 }
248
249 static GdkDevice *
250 add_device (GdkDeviceManagerXI2 *device_manager,
251             XIDeviceInfo        *dev,
252             gboolean             emit_signal)
253 {
254   GdkDisplay *display;
255   GdkDevice *device;
256
257   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
258   device = create_device (GDK_DEVICE_MANAGER (device_manager), display, dev);
259
260   g_hash_table_replace (device_manager->id_table,
261                         GINT_TO_POINTER (dev->deviceid),
262                         g_object_ref (device));
263
264   if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard)
265     device_manager->master_devices = g_list_append (device_manager->master_devices, device);
266   else if (dev->use == XISlavePointer || dev->use == XISlaveKeyboard)
267     device_manager->slave_devices = g_list_append (device_manager->slave_devices, device);
268   else if (dev->use == XIFloatingSlave)
269     device_manager->floating_devices = g_list_append (device_manager->floating_devices, device);
270   else
271     g_warning ("Unhandled device: %s\n", gdk_device_get_name (device));
272
273   if (emit_signal)
274     g_signal_emit_by_name (device_manager, "device-added", device);
275
276   return device;
277 }
278
279 static void
280 remove_device (GdkDeviceManagerXI2 *device_manager,
281                int                  device_id)
282 {
283   GdkDevice *device;
284
285   device = g_hash_table_lookup (device_manager->id_table,
286                                 GINT_TO_POINTER (device_id));
287
288   if (device)
289     {
290       device_manager->master_devices = g_list_remove (device_manager->master_devices, device);
291       device_manager->slave_devices = g_list_remove (device_manager->slave_devices, device);
292       device_manager->floating_devices = g_list_remove (device_manager->floating_devices, device);
293
294       g_signal_emit_by_name (device_manager, "device-removed", device);
295
296       g_object_run_dispose (G_OBJECT (device));
297
298       g_hash_table_remove (device_manager->id_table,
299                            GINT_TO_POINTER (device_id));
300     }
301 }
302
303 static void
304 relate_devices (gpointer key,
305                 gpointer value,
306                 gpointer user_data)
307 {
308   GdkDeviceManagerXI2 *device_manager;
309   GdkDevice *device, *relative;
310
311   device_manager = user_data;
312   device = g_hash_table_lookup (device_manager->id_table, key);
313   relative = g_hash_table_lookup (device_manager->id_table, value);
314
315   _gdk_device_set_associated_device (device, relative);
316   _gdk_device_set_associated_device (relative, device);
317 }
318
319 static void
320 gdk_device_manager_xi2_constructed (GObject *object)
321 {
322   GdkDeviceManagerXI2 *device_manager_xi2;
323   GdkDisplay *display;
324   GdkScreen *screen;
325   GHashTable *relations;
326   Display *xdisplay;
327   XIDeviceInfo *info, *dev;
328   int ndevices, i;
329   XIEventMask event_mask;
330   unsigned char mask[2] = { 0 };
331
332   device_manager_xi2 = GDK_DEVICE_MANAGER_XI2 (object);
333   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
334   xdisplay = GDK_DISPLAY_XDISPLAY (display);
335   relations = g_hash_table_new (NULL, NULL);
336
337   info = XIQueryDevice(xdisplay, XIAllDevices, &ndevices);
338
339   /* Initialize devices list */
340   for (i = 0; i < ndevices; i++)
341     {
342       GdkDevice *device;
343
344       dev = &info[i];
345       device = add_device (device_manager_xi2, dev, FALSE);
346
347       if (dev->use == XIMasterPointer ||
348           dev->use == XIMasterKeyboard)
349         {
350           g_hash_table_insert (relations,
351                                GINT_TO_POINTER (dev->deviceid),
352                                GINT_TO_POINTER (dev->attachment));
353         }
354     }
355
356   XIFreeDeviceInfo(info);
357
358   /* Stablish relationships between devices */
359   g_hash_table_foreach (relations, relate_devices, object);
360   g_hash_table_destroy (relations);
361
362   /* Connect to hierarchy change events */
363   screen = gdk_display_get_default_screen (display);
364   XISetMask (mask, XI_HierarchyChanged);
365   XISetMask (mask, XI_DeviceChanged);
366
367   event_mask.deviceid = XIAllDevices;
368   event_mask.mask_len = sizeof (mask);
369   event_mask.mask = mask;
370
371   _gdk_device_manager_xi2_select_events (GDK_DEVICE_MANAGER (object),
372                                          GDK_WINDOW_XID (gdk_screen_get_root_window (screen)),
373                                          &event_mask);
374 }
375
376 static void
377 gdk_device_manager_xi2_dispose (GObject *object)
378 {
379   GdkDeviceManagerXI2 *device_manager_xi2;
380
381   device_manager_xi2 = GDK_DEVICE_MANAGER_XI2 (object);
382
383   g_list_foreach (device_manager_xi2->master_devices, (GFunc) g_object_unref, NULL);
384   g_list_free (device_manager_xi2->master_devices);
385   device_manager_xi2->master_devices = NULL;
386
387   g_list_foreach (device_manager_xi2->slave_devices, (GFunc) g_object_unref, NULL);
388   g_list_free (device_manager_xi2->slave_devices);
389   device_manager_xi2->slave_devices = NULL;
390
391   g_list_foreach (device_manager_xi2->floating_devices, (GFunc) g_object_unref, NULL);
392   g_list_free (device_manager_xi2->floating_devices);
393   device_manager_xi2->floating_devices = NULL;
394
395   if (device_manager_xi2->id_table)
396     {
397       g_hash_table_destroy (device_manager_xi2->id_table);
398       device_manager_xi2->id_table = NULL;
399     }
400
401   G_OBJECT_CLASS (gdk_device_manager_xi2_parent_class)->dispose (object);
402 }
403
404 static GList *
405 gdk_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
406                                      GdkDeviceType     type)
407 {
408   GdkDeviceManagerXI2 *device_manager_xi2;
409   GList *list = NULL;
410
411   device_manager_xi2 = GDK_DEVICE_MANAGER_XI2 (device_manager);
412
413   switch (type)
414     {
415     case GDK_DEVICE_TYPE_MASTER:
416       list = device_manager_xi2->master_devices;
417       break;
418     case GDK_DEVICE_TYPE_SLAVE:
419       list = device_manager_xi2->slave_devices;
420       break;
421     case GDK_DEVICE_TYPE_FLOATING:
422       list = device_manager_xi2->floating_devices;
423       break;
424     default:
425       g_assert_not_reached ();
426     }
427
428   return g_list_copy (list);
429 }
430
431 static GdkDevice *
432 gdk_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager)
433 {
434   GdkDeviceManagerXI2 *device_manager_xi2;
435   GdkDisplay *display;
436   int device_id;
437
438   device_manager_xi2 = (GdkDeviceManagerXI2 *) device_manager;
439   display = gdk_device_manager_get_display (device_manager);
440
441   XIGetClientPointer (GDK_DISPLAY_XDISPLAY (display),
442                       None, &device_id);
443
444   return g_hash_table_lookup (device_manager_xi2->id_table,
445                               GINT_TO_POINTER (device_id));
446 }
447
448 static void
449 gdk_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
450 {
451   iface->translate_event = gdk_device_manager_xi2_translate_event;
452   iface->get_handled_events = gdk_device_manager_xi2_get_handled_events;
453   iface->select_window_events = gdk_device_manager_xi2_select_window_events;
454 }
455
456 static void
457 handle_hierarchy_changed (GdkDeviceManagerXI2 *device_manager,
458                           XIHierarchyEvent    *ev)
459 {
460   GdkDevice *device;
461   gint i;
462
463   /* We only care about enabled devices */
464   if (!(ev->flags & XIDeviceEnabled) &&
465       !(ev->flags & XIDeviceDisabled))
466     return;
467
468   for (i = 0; i < ev->num_info; i++)
469     {
470       if (ev->info[i].flags & XIDeviceEnabled)
471         {
472           GdkDisplay *display;
473           Display *xdisplay;
474           XIDeviceInfo *info;
475           int ndevices;
476
477           display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
478           xdisplay = GDK_DISPLAY_XDISPLAY (display);
479
480           info = XIQueryDevice(xdisplay, ev->info[i].deviceid, &ndevices);
481           device = add_device (device_manager, &info[0], TRUE);
482           XIFreeDeviceInfo(info);
483         }
484       else if (ev->info[i].flags & XIDeviceDisabled)
485         remove_device (device_manager, ev->info[i].deviceid);
486     }
487 }
488
489 static void
490 handle_device_changed (GdkDeviceManagerXI2  *device_manager,
491                        XIDeviceChangedEvent *ev)
492 {
493   GdkDisplay *display;
494   GdkDevice *device;
495
496   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
497   device = g_hash_table_lookup (device_manager->id_table,
498                                 GUINT_TO_POINTER (ev->deviceid));
499
500   _gdk_device_reset_axes (device);
501   translate_device_classes (display, device, ev->classes, ev->num_classes);
502 }
503
504 static GdkCrossingMode
505 translate_crossing_mode (int mode)
506 {
507   switch (mode)
508     {
509     case NotifyNormal:
510       return GDK_CROSSING_NORMAL;
511     case NotifyGrab:
512       return GDK_CROSSING_GRAB;
513     case NotifyUngrab:
514       return GDK_CROSSING_UNGRAB;
515     default:
516       g_assert_not_reached ();
517     }
518 }
519
520 static GdkNotifyType
521 translate_notify_type (int detail)
522 {
523   switch (detail)
524     {
525     case NotifyInferior:
526       return GDK_NOTIFY_INFERIOR;
527     case NotifyAncestor:
528       return GDK_NOTIFY_ANCESTOR;
529     case NotifyVirtual:
530       return GDK_NOTIFY_VIRTUAL;
531     case NotifyNonlinear:
532       return GDK_NOTIFY_NONLINEAR;
533     case NotifyNonlinearVirtual:
534       return GDK_NOTIFY_NONLINEAR_VIRTUAL;
535     default:
536       g_assert_not_reached ();
537     }
538 }
539
540 static gboolean
541 set_screen_from_root (GdkDisplay *display,
542                       GdkEvent   *event,
543                       Window      xrootwin)
544 {
545   GdkScreen *screen;
546
547   screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
548
549   if (screen)
550     {
551       gdk_event_set_screen (event, screen);
552
553       return TRUE;
554     }
555
556   return FALSE;
557 }
558
559 static void
560 set_user_time (GdkEvent *event)
561 {
562   GdkWindow *window;
563   guint32 time;
564
565   window = gdk_window_get_toplevel (event->any.window);
566   g_return_if_fail (GDK_IS_WINDOW (window));
567
568   time = gdk_event_get_time (event);
569
570   /* If an event doesn't have a valid timestamp, we shouldn't use it
571    * to update the latest user interaction time.
572    */
573   if (time != GDK_CURRENT_TIME)
574     gdk_x11_window_set_user_time (window, time);
575 }
576
577 static void
578 translate_keyboard_string (GdkEventKey *event)
579 {
580   gunichar c = 0;
581   gchar buf[7];
582
583   /* Fill in event->string crudely, since various programs
584    * depend on it.
585    */
586   event->string = NULL;
587
588   if (event->keyval != GDK_KEY_VoidSymbol)
589     c = gdk_keyval_to_unicode (event->keyval);
590
591   if (c)
592     {
593       gsize bytes_written;
594       gint len;
595
596       /* Apply the control key - Taken from Xlib
597        */
598       if (event->state & GDK_CONTROL_MASK)
599         {
600           if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
601           else if (c == '2')
602             {
603               event->string = g_memdup ("\0\0", 2);
604               event->length = 1;
605               buf[0] = '\0';
606               return;
607             }
608           else if (c >= '3' && c <= '7') c -= ('3' - '\033');
609           else if (c == '8') c = '\177';
610           else if (c == '/') c = '_' & 0x1F;
611         }
612
613       len = g_unichar_to_utf8 (c, buf);
614       buf[len] = '\0';
615
616       event->string = g_locale_from_utf8 (buf, len,
617                                           NULL, &bytes_written,
618                                           NULL);
619       if (event->string)
620         event->length = bytes_written;
621     }
622   else if (event->keyval == GDK_KEY_Escape)
623     {
624       event->length = 1;
625       event->string = g_strdup ("\033");
626     }
627   else if (event->keyval == GDK_KEY_Return ||
628           event->keyval == GDK_KEY_KP_Enter)
629     {
630       event->length = 1;
631       event->string = g_strdup ("\r");
632     }
633
634   if (!event->string)
635     {
636       event->length = 0;
637       event->string = g_strdup ("");
638     }
639 }
640
641 static void
642 generate_focus_event (GdkWindow *window,
643                       GdkDevice *device,
644                       gboolean   in)
645 {
646   GdkEvent *event;
647
648   event = gdk_event_new (GDK_FOCUS_CHANGE);
649   event->focus_change.window = g_object_ref (window);
650   event->focus_change.send_event = FALSE;
651   event->focus_change.in = in;
652   gdk_event_set_device (event, device);
653
654   gdk_event_put (event);
655   gdk_event_free (event);
656 }
657
658 static void
659 handle_focus_change (GdkWindow *window,
660                      GdkDevice *device,
661                      gint       detail,
662                      gint       mode,
663                      gboolean   in)
664 {
665   GdkToplevelX11 *toplevel;
666   gboolean had_focus;
667
668   toplevel = _gdk_x11_window_get_toplevel (window);
669
670   if (!toplevel)
671     return;
672
673   had_focus = HAS_FOCUS (toplevel);
674
675   switch (detail)
676     {
677     case NotifyAncestor:
678     case NotifyVirtual:
679       /* When the focus moves from an ancestor of the window to
680        * the window or a descendent of the window, *and* the
681        * pointer is inside the window, then we were previously
682        * receiving keystroke events in the has_pointer_focus
683        * case and are now receiving them in the
684        * has_focus_window case.
685        */
686       if (toplevel->has_pointer &&
687           mode != NotifyGrab &&
688           mode != NotifyUngrab)
689         toplevel->has_pointer_focus = (in) ? FALSE : TRUE;
690
691       /* fall through */
692     case NotifyNonlinear:
693     case NotifyNonlinearVirtual:
694       if (mode != NotifyGrab &&
695           mode != NotifyUngrab)
696         toplevel->has_focus_window = (in) ? TRUE : FALSE;
697       /* We pretend that the focus moves to the grab
698        * window, so we pay attention to NotifyGrab
699        * NotifyUngrab, and ignore NotifyWhileGrabbed
700        */
701       if (mode != NotifyWhileGrabbed)
702         toplevel->has_focus = (in) ? TRUE : FALSE;
703       break;
704     case NotifyPointer:
705       /* The X server sends NotifyPointer/NotifyGrab,
706        * but the pointer focus is ignored while a
707        * grab is in effect
708        */
709       if (mode != NotifyGrab &&
710           mode != NotifyUngrab)
711         toplevel->has_pointer_focus = (in) ? TRUE :FALSE;
712       break;
713     case NotifyInferior:
714     case NotifyPointerRoot:
715     case NotifyDetailNone:
716       break;
717     }
718
719   if (HAS_FOCUS (toplevel) != had_focus)
720     generate_focus_event (window, device, (in) ? TRUE : FALSE);
721 }
722
723 static gdouble *
724 translate_axes (GdkDevice       *device,
725                 gdouble          x,
726                 gdouble          y,
727                 GdkWindow       *window,
728                 XIValuatorState *valuators)
729 {
730   guint n_axes, i;
731   gint width, height;
732   gdouble *axes;
733   double *vals;
734
735   g_object_get (device, "n-axes", &n_axes, NULL);
736
737   axes = g_new0 (gdouble, n_axes);
738   vals = valuators->values;
739
740   width = gdk_window_get_width (window);
741   height = gdk_window_get_height (window);
742
743   for (i = 0; i < valuators->mask_len * 8; i++)
744     {
745       GdkAxisUse use;
746       gdouble val;
747
748       if (!XIMaskIsSet (valuators->mask, i))
749         continue;
750
751       use = _gdk_device_get_axis_use (device, i);
752       val = *vals++;
753
754       switch (use)
755         {
756         case GDK_AXIS_X:
757         case GDK_AXIS_Y:
758           if (gdk_device_get_mode (device) == GDK_MODE_WINDOW)
759             _gdk_device_translate_window_coord (device, window, i, val, &axes[i]);
760           else
761             {
762               if (use == GDK_AXIS_X)
763                 axes[i] = x;
764               else
765                 axes[i] = y;
766             }
767           break;
768         default:
769           _gdk_device_translate_axis (device, i, val, &axes[i]);
770           break;
771         }
772     }
773
774   return axes;
775 }
776
777 static gboolean
778 is_parent_of (GdkWindow *parent,
779               GdkWindow *child)
780 {
781   GdkWindow *w;
782
783   w = child;
784   while (w != NULL)
785     {
786       if (w == parent)
787         return TRUE;
788
789       w = gdk_window_get_parent (w);
790     }
791
792   return FALSE;
793 }
794
795 static GdkWindow *
796 get_event_window (GdkEventTranslator *translator,
797                   XIEvent            *ev)
798 {
799   GdkDisplay *display;
800   GdkWindow *window = NULL;
801
802   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (translator));
803
804   switch (ev->evtype)
805     {
806     case XI_KeyPress:
807     case XI_KeyRelease:
808     case XI_ButtonPress:
809     case XI_ButtonRelease:
810     case XI_Motion:
811       {
812         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
813
814         window = gdk_window_lookup_for_display (display, xev->event);
815
816         /* Apply keyboard grabs to non-native windows */
817         if (ev->evtype == XI_KeyPress || ev->evtype == XI_KeyRelease)
818           {
819             GdkDeviceGrabInfo *info;
820             GdkDevice *device;
821             gulong serial;
822
823             device = g_hash_table_lookup (GDK_DEVICE_MANAGER_XI2 (translator)->id_table,
824                                           GUINT_TO_POINTER (((XIDeviceEvent *) ev)->deviceid));
825
826             serial = _gdk_windowing_window_get_next_serial (display);
827             info = _gdk_display_has_device_grab (display, device, serial);
828
829             if (info &&
830                 (!is_parent_of (info->window, window) ||
831                  !info->owner_events))
832               {
833                 /* Report key event against grab window */
834                 window = info->window;
835               }
836           }
837       }
838       break;
839     case XI_Enter:
840     case XI_Leave:
841     case XI_FocusIn:
842     case XI_FocusOut:
843       {
844         XIEnterEvent *xev = (XIEnterEvent *) ev;
845
846         window = gdk_window_lookup_for_display (display, xev->event);
847       }
848       break;
849     }
850
851   return window;
852 }
853
854 static gboolean
855 gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
856                                         GdkDisplay         *display,
857                                         GdkEvent           *event,
858                                         XEvent             *xevent)
859 {
860   GdkDeviceManagerXI2 *device_manager;
861   XGenericEventCookie *cookie;
862   gboolean return_val = TRUE;
863   GdkWindow *window;
864   XIEvent *ev;
865   Display *dpy;
866
867   dpy = GDK_DISPLAY_XDISPLAY (display);
868   device_manager = (GdkDeviceManagerXI2 *) translator;
869   cookie = &xevent->xcookie;
870
871   if (!XGetEventData (dpy, cookie))
872     return FALSE;
873
874   if (cookie->type != GenericEvent ||
875       cookie->extension != device_manager->opcode)
876     {
877       XFreeEventData (dpy, cookie);
878       return FALSE;
879     }
880
881   ev = (XIEvent *) cookie->data;
882
883   window = get_event_window (translator, ev);
884
885   if (window && GDK_WINDOW_DESTROYED (window))
886     {
887       XFreeEventData (dpy, cookie);
888       return FALSE;
889     }
890
891   if (ev->evtype == XI_Motion ||
892       ev->evtype == XI_ButtonRelease)
893     {
894       if (_gdk_moveresize_handle_event (xevent))
895         {
896           XFreeEventData (dpy, cookie);
897           return FALSE;
898         }
899     }
900
901   switch (ev->evtype)
902     {
903     case XI_HierarchyChanged:
904       handle_hierarchy_changed (device_manager,
905                                 (XIHierarchyEvent *) ev);
906       return_val = FALSE;
907       break;
908     case XI_DeviceChanged:
909       handle_device_changed (device_manager,
910                              (XIDeviceChangedEvent *) ev);
911       return_val = FALSE;
912       break;
913     case XI_KeyPress:
914     case XI_KeyRelease:
915       {
916         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
917         GdkKeymap *keymap = gdk_keymap_get_for_display (display);
918         GdkModifierType consumed, state;
919         GdkDevice *device;
920
921         event->key.type = xev->evtype == XI_KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
922
923         event->key.window = window;
924
925         event->key.time = xev->time;
926         event->key.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
927         event->key.group = _gdk_x11_get_group_for_state (display, event->key.state);
928
929         event->key.hardware_keycode = xev->detail;
930         event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
931
932         device = g_hash_table_lookup (device_manager->id_table,
933                                       GUINT_TO_POINTER (xev->deviceid));
934         gdk_event_set_device (event, device);
935
936         event->key.keyval = GDK_KEY_VoidSymbol;
937
938         gdk_keymap_translate_keyboard_state (keymap,
939                                              event->key.hardware_keycode,
940                                              event->key.state,
941                                              event->key.group,
942                                              &event->key.keyval,
943                                              NULL, NULL, &consumed);
944
945         state = event->key.state & ~consumed;
946         _gdk_keymap_add_virtual_modifiers_compat (keymap, &state);
947         event->key.state |= state;
948
949         translate_keyboard_string ((GdkEventKey *) event);
950
951         if (ev->evtype == XI_KeyPress)
952           set_user_time (event);
953
954         /* FIXME: emulate autorepeat on key
955          * release? XI2 seems attached to Xkb.
956          */
957       }
958
959       break;
960     case XI_ButtonPress:
961     case XI_ButtonRelease:
962       {
963         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
964
965         switch (xev->detail)
966           {
967           case 4:
968           case 5:
969           case 6:
970           case 7:
971             event->scroll.type = GDK_SCROLL;
972
973             if (xev->detail == 4)
974               event->scroll.direction = GDK_SCROLL_UP;
975             else if (xev->detail == 5)
976               event->scroll.direction = GDK_SCROLL_DOWN;
977             else if (xev->detail == 6)
978               event->scroll.direction = GDK_SCROLL_LEFT;
979             else
980               event->scroll.direction = GDK_SCROLL_RIGHT;
981
982             event->scroll.window = window;
983             event->scroll.time = xev->time;
984             event->scroll.x = (gdouble) xev->event_x;
985             event->scroll.y = (gdouble) xev->event_y;
986             event->scroll.x_root = (gdouble) xev->root_x;
987             event->scroll.y_root = (gdouble) xev->root_y;
988
989             event->scroll.device = g_hash_table_lookup (device_manager->id_table,
990                                                         GUINT_TO_POINTER (xev->deviceid));
991
992             event->scroll.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
993             break;
994           default:
995             event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
996
997             event->button.window = window;
998             event->button.time = xev->time;
999             event->button.x = (gdouble) xev->event_x;
1000             event->button.y = (gdouble) xev->event_y;
1001             event->button.x_root = (gdouble) xev->root_x;
1002             event->button.y_root = (gdouble) xev->root_y;
1003
1004             event->button.device = g_hash_table_lookup (device_manager->id_table,
1005                                                         GUINT_TO_POINTER (xev->deviceid));
1006
1007             event->button.axes = translate_axes (event->button.device,
1008                                                  event->button.x,
1009                                                  event->button.y,
1010                                                  event->button.window,
1011                                                  &xev->valuators);
1012
1013             if (gdk_device_get_mode (event->button.device) == GDK_MODE_WINDOW)
1014               {
1015                 GdkDevice *device = event->button.device;
1016
1017                 /* Update event coordinates from axes */
1018                 gdk_device_get_axis (device, event->button.axes, GDK_AXIS_X, &event->button.x);
1019                 gdk_device_get_axis (device, event->button.axes, GDK_AXIS_Y, &event->button.y);
1020               }
1021
1022             event->button.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
1023             event->button.button = xev->detail;
1024           }
1025
1026         if (!set_screen_from_root (display, event, xev->root))
1027           {
1028             return_val = FALSE;
1029             break;
1030           }
1031
1032         set_user_time (event);
1033
1034         break;
1035       }
1036     case XI_Motion:
1037       {
1038         XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1039
1040         event->motion.type = GDK_MOTION_NOTIFY;
1041
1042         event->motion.window = window;
1043
1044         event->motion.time = xev->time;
1045         event->motion.x = (gdouble) xev->event_x;
1046         event->motion.y = (gdouble) xev->event_y;
1047         event->motion.x_root = (gdouble) xev->root_x;
1048         event->motion.y_root = (gdouble) xev->root_y;
1049
1050         event->motion.device = g_hash_table_lookup (device_manager->id_table,
1051                                                     GINT_TO_POINTER (xev->deviceid));
1052
1053         event->motion.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
1054
1055         /* There doesn't seem to be motion hints in XI */
1056         event->motion.is_hint = FALSE;
1057
1058         event->motion.axes = translate_axes (event->motion.device,
1059                                              event->motion.x,
1060                                              event->motion.y,
1061                                              event->motion.window,
1062                                              &xev->valuators);
1063
1064         if (gdk_device_get_mode (event->motion.device) == GDK_MODE_WINDOW)
1065           {
1066             GdkDevice *device = event->motion.device;
1067
1068             /* Update event coordinates from axes */
1069             gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_X, &event->motion.x);
1070             gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_Y, &event->motion.y);
1071           }
1072       }
1073       break;
1074     case XI_Enter:
1075     case XI_Leave:
1076       {
1077         XIEnterEvent *xev = (XIEnterEvent *) ev;
1078         GdkDevice *device;
1079
1080         event->crossing.type = (ev->evtype == XI_Enter) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
1081
1082         event->crossing.x = (gdouble) xev->event_x;
1083         event->crossing.y = (gdouble) xev->event_y;
1084         event->crossing.x_root = (gdouble) xev->root_x;
1085         event->crossing.y_root = (gdouble) xev->root_y;
1086         event->crossing.time = xev->time;
1087         event->crossing.focus = xev->focus;
1088
1089         event->crossing.window = window;
1090         event->crossing.subwindow = gdk_window_lookup_for_display (display, xev->child);
1091
1092         device = g_hash_table_lookup (device_manager->id_table,
1093                                       GINT_TO_POINTER (xev->deviceid));
1094         gdk_event_set_device (event, device);
1095
1096         event->crossing.mode = translate_crossing_mode (xev->mode);
1097         event->crossing.detail = translate_notify_type (xev->detail);
1098         event->crossing.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
1099       }
1100       break;
1101     case XI_FocusIn:
1102     case XI_FocusOut:
1103       {
1104         XIEnterEvent *xev = (XIEnterEvent *) ev;
1105         GdkDevice *device;
1106
1107         device = g_hash_table_lookup (device_manager->id_table,
1108                                       GINT_TO_POINTER (xev->deviceid));
1109
1110         handle_focus_change (window, device, xev->detail, xev->mode,
1111                              (ev->evtype == XI_FocusIn) ? TRUE : FALSE);
1112
1113         return_val = FALSE;
1114       }
1115     default:
1116       return_val = FALSE;
1117       break;
1118     }
1119
1120   event->any.send_event = cookie->send_event;
1121
1122   if (return_val)
1123     {
1124       if (event->any.window)
1125         g_object_ref (event->any.window);
1126
1127       if (((event->any.type == GDK_ENTER_NOTIFY) ||
1128            (event->any.type == GDK_LEAVE_NOTIFY)) &&
1129           (event->crossing.subwindow != NULL))
1130         g_object_ref (event->crossing.subwindow);
1131     }
1132   else
1133     {
1134       /* Mark this event as having no resources to be freed */
1135       event->any.window = NULL;
1136       event->any.type = GDK_NOTHING;
1137     }
1138
1139   XFreeEventData (dpy, cookie);
1140
1141   return return_val;
1142 }
1143
1144 static GdkEventMask
1145 gdk_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
1146 {
1147   return (GDK_KEY_PRESS_MASK |
1148           GDK_KEY_RELEASE_MASK |
1149           GDK_BUTTON_PRESS_MASK |
1150           GDK_BUTTON_RELEASE_MASK |
1151           GDK_SCROLL_MASK |
1152           GDK_ENTER_NOTIFY_MASK |
1153           GDK_LEAVE_NOTIFY_MASK |
1154           GDK_POINTER_MOTION_MASK |
1155           GDK_POINTER_MOTION_HINT_MASK |
1156           GDK_BUTTON1_MOTION_MASK |
1157           GDK_BUTTON2_MOTION_MASK |
1158           GDK_BUTTON3_MOTION_MASK |
1159           GDK_BUTTON_MOTION_MASK |
1160           GDK_FOCUS_CHANGE_MASK);
1161 }
1162
1163 static void
1164 gdk_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
1165                                              Window              window,
1166                                              GdkEventMask        evmask)
1167 {
1168   GdkDeviceManager *device_manager;
1169   XIEventMask event_mask;
1170
1171   device_manager = GDK_DEVICE_MANAGER (translator);
1172
1173   event_mask.deviceid = XIAllMasterDevices;
1174   event_mask.mask = gdk_device_xi2_translate_event_mask (evmask, &event_mask.mask_len);
1175
1176   _gdk_device_manager_xi2_select_events (device_manager, window, &event_mask);
1177   g_free (event_mask.mask);
1178 }