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