1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
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.
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.
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.
22 #include "gdkx11devicemanager-xi2.h"
23 #include "gdkx11device-xi2.h"
25 #include "gdkdevicemanagerprivate-core.h"
26 #include "gdkdeviceprivate.h"
27 #include "gdkdisplayprivate.h"
28 #include "gdkeventtranslator.h"
29 #include "gdkprivate-x11.h"
31 #include "gdkkeysyms.h"
36 #include <X11/Xutil.h>
37 #include <X11/extensions/XInput2.h>
43 struct _GdkX11DeviceManagerXI2
45 GdkX11DeviceManagerCore parent_object;
54 struct _GdkX11DeviceManagerXI2Class
56 GdkDeviceManagerClass parent_class;
59 static void gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
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))
68 #define HAS_FOCUS(toplevel) ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
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,
77 static void gdk_x11_device_manager_xi2_get_property (GObject *object,
82 static GList * gdk_x11_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
84 static GdkDevice * gdk_x11_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager);
86 static gboolean gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
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,
93 GdkEventMask event_mask);
102 gdk_x11_device_manager_xi2_class_init (GdkX11DeviceManagerXI2Class *klass)
104 GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
105 GObjectClass *object_class = G_OBJECT_CLASS (klass);
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;
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;
115 g_object_class_install_property (object_class,
117 g_param_spec_int ("opcode",
119 P_("Opcode for XInput2 requests"),
121 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
125 gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
127 device_manager->id_table = g_hash_table_new_full (g_direct_hash,
130 (GDestroyNotify) g_object_unref);
134 _gdk_x11_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
136 XIEventMask *event_mask)
141 display = gdk_device_manager_get_display (device_manager);
142 xdisplay = GDK_DISPLAY_XDISPLAY (display);
144 XISelectEvents (xdisplay, xwindow, event_mask, 1);
148 translate_valuator_class (GdkDisplay *display,
150 XIValuatorClassInfo *info,
153 static gboolean initialized = FALSE;
154 static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
155 GdkAxisUse use = GDK_AXIS_IGNORE;
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");
170 for (i = GDK_AXIS_IGNORE; i <= GDK_AXIS_LAST; i++)
172 if (label_atoms[i] == info->label)
179 if (info->label != None)
180 label = gdk_x11_xatom_to_atom_for_display (display, info->label);
184 _gdk_device_add_axis (device,
193 translate_device_classes (GdkDisplay *display,
195 XIAnyClassInfo **classes,
198 gint i, n_valuator = 0;
200 g_object_freeze_notify (G_OBJECT (device));
202 for (i = 0; i < n_classes; i++)
204 XIAnyClassInfo *class_info = classes[i];
206 switch (class_info->type)
210 XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info;
213 _gdk_device_set_keys (device, key_info->num_keycodes);
215 for (i = 0; i < key_info->num_keycodes; i++)
216 gdk_device_set_key (device, i, key_info->keycodes[i], 0);
219 case XIValuatorClass:
220 translate_valuator_class (display, device,
221 (XIValuatorClassInfo *) class_info,
231 g_object_thaw_notify (G_OBJECT (device));
235 create_device (GdkDeviceManager *device_manager,
239 GdkInputSource input_source;
244 if (dev->use == XIMasterKeyboard || dev->use == XISlaveKeyboard)
245 input_source = GDK_SOURCE_KEYBOARD;
250 tmp_name = g_ascii_strdown (dev->name, -1);
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;
260 input_source = GDK_SOURCE_MOUSE;
267 case XIMasterKeyboard:
268 case XIMasterPointer:
269 type = GDK_DEVICE_TYPE_MASTER;
270 mode = GDK_MODE_SCREEN;
272 case XISlaveKeyboard:
274 type = GDK_DEVICE_TYPE_SLAVE;
275 mode = GDK_MODE_DISABLED;
277 case XIFloatingSlave:
279 type = GDK_DEVICE_TYPE_FLOATING;
280 mode = GDK_MODE_DISABLED;
284 device = g_object_new (GDK_TYPE_X11_DEVICE_XI2,
287 "input-source", input_source,
289 "has-cursor", (dev->use == XIMasterPointer),
291 "device-manager", device_manager,
292 "device-id", dev->deviceid,
295 translate_device_classes (display, device, dev->classes, dev->num_classes);
301 add_device (GdkX11DeviceManagerXI2 *device_manager,
303 gboolean emit_signal)
308 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
309 device = create_device (GDK_DEVICE_MANAGER (device_manager), display, dev);
311 g_hash_table_replace (device_manager->id_table,
312 GINT_TO_POINTER (dev->deviceid),
313 g_object_ref (device));
315 device_manager->devices = g_list_append (device_manager->devices, device);
319 if (dev->use == XISlavePointer || dev->use == XISlaveKeyboard)
323 /* The device manager is already constructed, then
324 * keep the hierarchy coherent for the added device.
326 master = g_hash_table_lookup (device_manager->id_table,
327 GINT_TO_POINTER (dev->attachment));
329 _gdk_device_set_associated_device (device, master);
330 _gdk_device_add_slave (master, device);
333 g_signal_emit_by_name (device_manager, "device-added", device);
340 remove_device (GdkX11DeviceManagerXI2 *device_manager,
345 device = g_hash_table_lookup (device_manager->id_table,
346 GINT_TO_POINTER (device_id));
350 device_manager->devices = g_list_remove (device_manager->devices, device);
352 g_signal_emit_by_name (device_manager, "device-removed", device);
354 g_object_run_dispose (G_OBJECT (device));
356 g_hash_table_remove (device_manager->id_table,
357 GINT_TO_POINTER (device_id));
362 relate_masters (gpointer key,
366 GdkX11DeviceManagerXI2 *device_manager;
367 GdkDevice *device, *relative;
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);
373 _gdk_device_set_associated_device (device, relative);
374 _gdk_device_set_associated_device (relative, device);
378 relate_slaves (gpointer key,
382 GdkX11DeviceManagerXI2 *device_manager;
383 GdkDevice *slave, *master;
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);
389 _gdk_device_set_associated_device (slave, master);
390 _gdk_device_add_slave (master, slave);
394 gdk_x11_device_manager_xi2_constructed (GObject *object)
396 GdkX11DeviceManagerXI2 *device_manager;
399 GHashTable *masters, *slaves;
401 XIDeviceInfo *info, *dev;
403 XIEventMask event_mask;
404 unsigned char mask[2] = { 0 };
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);
410 masters = g_hash_table_new (NULL, NULL);
411 slaves = g_hash_table_new (NULL, NULL);
413 info = XIQueryDevice (xdisplay, XIAllDevices, &ndevices);
415 /* Initialize devices list */
416 for (i = 0; i < ndevices; i++)
419 add_device (device_manager, dev, FALSE);
421 if (dev->use == XIMasterPointer ||
422 dev->use == XIMasterKeyboard)
424 g_hash_table_insert (masters,
425 GINT_TO_POINTER (dev->deviceid),
426 GINT_TO_POINTER (dev->attachment));
428 else if (dev->use == XISlavePointer ||
429 dev->use == XISlaveKeyboard)
431 g_hash_table_insert (slaves,
432 GINT_TO_POINTER (dev->deviceid),
433 GINT_TO_POINTER (dev->attachment));
437 XIFreeDeviceInfo (info);
439 /* Stablish relationships between devices */
440 g_hash_table_foreach (masters, relate_masters, object);
441 g_hash_table_destroy (masters);
443 g_hash_table_foreach (slaves, relate_slaves, object);
444 g_hash_table_destroy (slaves);
446 /* Connect to hierarchy change events */
447 screen = gdk_display_get_default_screen (display);
448 XISetMask (mask, XI_HierarchyChanged);
449 XISetMask (mask, XI_DeviceChanged);
451 event_mask.deviceid = XIAllDevices;
452 event_mask.mask_len = sizeof (mask);
453 event_mask.mask = mask;
455 _gdk_x11_device_manager_xi2_select_events (GDK_DEVICE_MANAGER (object),
456 GDK_WINDOW_XID (gdk_screen_get_root_window (screen)),
461 gdk_x11_device_manager_xi2_dispose (GObject *object)
463 GdkX11DeviceManagerXI2 *device_manager;
465 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
467 g_list_free_full (device_manager->devices, g_object_unref);
468 device_manager->devices = NULL;
470 if (device_manager->id_table)
472 g_hash_table_destroy (device_manager->id_table);
473 device_manager->id_table = NULL;
476 G_OBJECT_CLASS (gdk_x11_device_manager_xi2_parent_class)->dispose (object);
480 gdk_x11_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
483 GdkX11DeviceManagerXI2 *device_manager_xi2;
484 GList *cur, *list = NULL;
486 device_manager_xi2 = GDK_X11_DEVICE_MANAGER_XI2 (device_manager);
488 for (cur = device_manager_xi2->devices; cur; cur = cur->next)
490 GdkDevice *dev = cur->data;
492 if (type == gdk_device_get_device_type (dev))
493 list = g_list_prepend (list, dev);
500 gdk_x11_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager)
502 GdkX11DeviceManagerXI2 *device_manager_xi2;
506 device_manager_xi2 = (GdkX11DeviceManagerXI2 *) device_manager;
507 display = gdk_device_manager_get_display (device_manager);
509 XIGetClientPointer (GDK_DISPLAY_XDISPLAY (display),
512 return g_hash_table_lookup (device_manager_xi2->id_table,
513 GINT_TO_POINTER (device_id));
517 gdk_x11_device_manager_xi2_set_property (GObject *object,
522 GdkX11DeviceManagerXI2 *device_manager;
524 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
529 device_manager->opcode = g_value_get_int (value);
532 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
538 gdk_x11_device_manager_xi2_get_property (GObject *object,
543 GdkX11DeviceManagerXI2 *device_manager;
545 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
550 g_value_set_int (value, device_manager->opcode);
553 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
559 gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
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;
567 handle_hierarchy_changed (GdkX11DeviceManagerXI2 *device_manager,
568 XIHierarchyEvent *ev)
576 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
577 xdisplay = GDK_DISPLAY_XDISPLAY (display);
579 for (i = 0; i < ev->num_info; i++)
581 if (ev->info[i].flags & XIDeviceEnabled)
583 info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
584 add_device (device_manager, &info[0], TRUE);
585 XIFreeDeviceInfo (info);
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)
592 GdkDevice *master, *slave;
594 slave = g_hash_table_lookup (device_manager->id_table,
595 GINT_TO_POINTER (ev->info[i].deviceid));
597 /* Remove old master info */
598 master = gdk_device_get_associated_device (slave);
602 _gdk_device_remove_slave (master, slave);
603 _gdk_device_set_associated_device (slave, NULL);
605 g_signal_emit_by_name (device_manager, "device-changed", master);
608 /* Add new master if it's an attachment event */
609 if (ev->info[i].flags & XISlaveAttached)
611 info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
613 master = g_hash_table_lookup (device_manager->id_table,
614 GINT_TO_POINTER (info->attachment));
616 _gdk_device_set_associated_device (slave, master);
617 _gdk_device_add_slave (master, slave);
619 g_signal_emit_by_name (device_manager, "device-changed", master);
622 g_signal_emit_by_name (device_manager, "device-changed", slave);
628 handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
629 XIDeviceChangedEvent *ev)
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));
638 _gdk_device_reset_axes (device);
639 translate_device_classes (display, device, ev->classes, ev->num_classes);
641 g_signal_emit_by_name (G_OBJECT (device), "changed");
644 static GdkCrossingMode
645 translate_crossing_mode (gint mode)
650 return GDK_CROSSING_NORMAL;
652 return GDK_CROSSING_GRAB;
654 return GDK_CROSSING_UNGRAB;
656 g_assert_not_reached ();
661 translate_notify_type (gint detail)
666 return GDK_NOTIFY_INFERIOR;
668 return GDK_NOTIFY_ANCESTOR;
670 return GDK_NOTIFY_VIRTUAL;
671 case NotifyNonlinear:
672 return GDK_NOTIFY_NONLINEAR;
673 case NotifyNonlinearVirtual:
674 return GDK_NOTIFY_NONLINEAR_VIRTUAL;
676 g_assert_not_reached ();
681 set_screen_from_root (GdkDisplay *display,
687 screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
691 gdk_event_set_screen (event, screen);
700 set_user_time (GdkEvent *event)
705 window = gdk_window_get_toplevel (event->any.window);
706 g_return_if_fail (GDK_IS_WINDOW (window));
708 time = gdk_event_get_time (event);
710 /* If an event doesn't have a valid timestamp, we shouldn't use it
711 * to update the latest user interaction time.
713 if (time != GDK_CURRENT_TIME)
714 gdk_x11_window_set_user_time (window, time);
718 generate_focus_event (GdkWindow *window,
720 GdkDevice *source_device,
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);
732 gdk_event_put (event);
733 gdk_event_free (event);
737 handle_focus_change (GdkWindow *window,
739 GdkDevice *source_device,
744 GdkToplevelX11 *toplevel;
747 toplevel = _gdk_x11_window_get_toplevel (window);
752 had_focus = HAS_FOCUS (toplevel);
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.
765 if (toplevel->has_pointer &&
766 mode != NotifyGrab &&
767 mode != NotifyUngrab)
768 toplevel->has_pointer_focus = (in) ? FALSE : TRUE;
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
780 if (mode != NotifyWhileGrabbed)
781 toplevel->has_focus = (in) ? TRUE : FALSE;
784 /* The X server sends NotifyPointer/NotifyGrab,
785 * but the pointer focus is ignored while a
788 if (mode != NotifyGrab &&
789 mode != NotifyUngrab)
790 toplevel->has_pointer_focus = (in) ? TRUE :FALSE;
793 case NotifyPointerRoot:
794 case NotifyDetailNone:
798 if (HAS_FOCUS (toplevel) != had_focus)
799 generate_focus_event (window, device, source_device, (in) ? TRUE : FALSE);
803 translate_axes (GdkDevice *device,
807 XIValuatorState *valuators)
813 g_object_get (device, "n-axes", &n_axes, NULL);
815 axes = g_new0 (gdouble, n_axes);
816 vals = valuators->values;
818 for (i = 0; i < valuators->mask_len * 8; i++)
823 if (!XIMaskIsSet (valuators->mask, i))
826 use = gdk_device_get_axis_use (device, i);
833 if (gdk_device_get_mode (device) == GDK_MODE_WINDOW)
834 _gdk_device_translate_window_coord (device, window, i, val, &axes[i]);
837 if (use == GDK_AXIS_X)
844 _gdk_device_translate_axis (device, i, val, &axes[i]);
853 is_parent_of (GdkWindow *parent,
864 w = gdk_window_get_parent (w);
871 get_event_window (GdkEventTranslator *translator,
875 GdkWindow *window = NULL;
877 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (translator));
884 case XI_ButtonRelease:
887 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
889 window = gdk_x11_window_lookup_for_display (display, xev->event);
891 /* Apply keyboard grabs to non-native windows */
892 if (ev->evtype == XI_KeyPress || ev->evtype == XI_KeyRelease)
894 GdkDeviceGrabInfo *info;
898 device = g_hash_table_lookup (GDK_X11_DEVICE_MANAGER_XI2 (translator)->id_table,
899 GUINT_TO_POINTER (((XIDeviceEvent *) ev)->deviceid));
901 serial = _gdk_display_get_next_serial (display);
902 info = _gdk_display_has_device_grab (display, device, serial);
905 (!is_parent_of (info->window, window) ||
906 !info->owner_events))
908 /* Report key event against grab window */
909 window = info->window;
919 XIEnterEvent *xev = (XIEnterEvent *) ev;
921 window = gdk_x11_window_lookup_for_display (display, xev->event);
930 gdk_x11_device_manager_xi2_translate_core_event (GdkEventTranslator *translator,
935 GdkEventTranslatorIface *parent_iface;
936 gboolean keyboard = FALSE;
939 if (xevent->type == KeyPress && xevent->xkey.keycode == 0)
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.
946 * This is just a bandaid fix to keep xim working with a single
947 * keyboard until XFilterEvent learns about XI2.
951 else if (xevent->xany.send_event)
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.)
960 switch (xevent->type)
983 parent_iface = g_type_interface_peek_parent (GDK_EVENT_TRANSLATOR_GET_IFACE (translator));
984 if (!parent_iface->translate_event (translator, display, event, xevent))
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
991 device = gdk_x11_device_manager_xi2_get_client_pointer ((GdkDeviceManager *)translator);
993 device = gdk_device_get_associated_device (device);
994 gdk_event_set_device (event, device);
1000 gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
1001 GdkDisplay *display,
1005 GdkX11DeviceManagerXI2 *device_manager;
1006 XGenericEventCookie *cookie;
1007 gboolean return_val = TRUE;
1012 dpy = GDK_DISPLAY_XDISPLAY (display);
1013 device_manager = (GdkX11DeviceManagerXI2 *) translator;
1014 cookie = &xevent->xcookie;
1016 if (xevent->type != GenericEvent)
1017 return gdk_x11_device_manager_xi2_translate_core_event (translator, display, event, xevent);
1019 if (!XGetEventData (dpy, cookie))
1022 if (cookie->type != GenericEvent ||
1023 cookie->extension != device_manager->opcode)
1025 XFreeEventData (dpy, cookie);
1029 ev = (XIEvent *) cookie->data;
1031 window = get_event_window (translator, ev);
1033 if (window && GDK_WINDOW_DESTROYED (window))
1035 XFreeEventData (dpy, cookie);
1039 if (ev->evtype == XI_Motion ||
1040 ev->evtype == XI_ButtonRelease)
1042 if (_gdk_x11_moveresize_handle_event (xevent))
1044 XFreeEventData (dpy, cookie);
1051 case XI_HierarchyChanged:
1052 handle_hierarchy_changed (device_manager,
1053 (XIHierarchyEvent *) ev);
1056 case XI_DeviceChanged:
1057 handle_device_changed (device_manager,
1058 (XIDeviceChangedEvent *) ev);
1064 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1065 GdkKeymap *keymap = gdk_keymap_get_for_display (display);
1066 GdkModifierType consumed, state;
1067 GdkDevice *device, *source_device;
1069 event->key.type = xev->evtype == XI_KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
1071 event->key.window = window;
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);
1077 event->key.hardware_keycode = xev->detail;
1078 event->key.is_modifier = _gdk_x11_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
1080 device = g_hash_table_lookup (device_manager->id_table,
1081 GUINT_TO_POINTER (xev->deviceid));
1082 gdk_event_set_device (event, device);
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);
1088 event->key.keyval = GDK_KEY_VoidSymbol;
1090 gdk_keymap_translate_keyboard_state (keymap,
1091 event->key.hardware_keycode,
1095 NULL, NULL, &consumed);
1097 state = event->key.state & ~consumed;
1098 _gdk_x11_keymap_add_virt_mods (keymap, &state);
1099 event->key.state |= state;
1101 _gdk_x11_event_translate_keyboard_string (&event->key);
1103 if (ev->evtype == XI_KeyPress)
1104 set_user_time (event);
1106 /* FIXME: emulate autorepeat on key
1107 * release? XI2 seems attached to Xkb.
1112 case XI_ButtonPress:
1113 case XI_ButtonRelease:
1115 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1116 GdkDevice *source_device;
1118 switch (xev->detail)
1124 /* Button presses of button 4-7 are scroll events */
1125 if (ev->evtype == XI_ButtonPress)
1127 event->scroll.type = GDK_SCROLL;
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;
1136 event->scroll.direction = GDK_SCROLL_RIGHT;
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;
1145 event->scroll.device = g_hash_table_lookup (device_manager->id_table,
1146 GUINT_TO_POINTER (xev->deviceid));
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);
1152 event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1155 /* Button presses of button 4-7 are scroll events, so ignore the release */
1156 else if (ev->evtype == XI_ButtonRelease)
1161 /* else (XI_ButtonRelease) fall thru */
1163 event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
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;
1172 event->button.device = g_hash_table_lookup (device_manager->id_table,
1173 GUINT_TO_POINTER (xev->deviceid));
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);
1179 event->button.axes = translate_axes (event->button.device,
1182 event->button.window,
1185 if (gdk_device_get_mode (event->button.device) == GDK_MODE_WINDOW)
1187 GdkDevice *device = event->button.device;
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);
1194 event->button.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1195 event->button.button = xev->detail;
1198 if (return_val == FALSE)
1201 if (!set_screen_from_root (display, event, xev->root))
1207 set_user_time (event);
1213 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1214 GdkDevice *source_device;
1216 event->motion.type = GDK_MOTION_NOTIFY;
1218 event->motion.window = window;
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;
1226 event->motion.device = g_hash_table_lookup (device_manager->id_table,
1227 GINT_TO_POINTER (xev->deviceid));
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);
1233 event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1235 /* There doesn't seem to be motion hints in XI */
1236 event->motion.is_hint = FALSE;
1238 event->motion.axes = translate_axes (event->motion.device,
1241 event->motion.window,
1244 if (gdk_device_get_mode (event->motion.device) == GDK_MODE_WINDOW)
1246 GdkDevice *device = event->motion.device;
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);
1257 XIEnterEvent *xev = (XIEnterEvent *) ev;
1258 GdkDevice *device, *source_device;
1260 event->crossing.type = (ev->evtype == XI_Enter) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
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;
1269 event->crossing.window = window;
1270 event->crossing.subwindow = gdk_x11_window_lookup_for_display (display, xev->child);
1272 device = g_hash_table_lookup (device_manager->id_table,
1273 GINT_TO_POINTER (xev->deviceid));
1274 gdk_event_set_device (event, device);
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);
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);
1288 XIEnterEvent *xev = (XIEnterEvent *) ev;
1289 GdkDevice *device, *source_device;
1291 device = g_hash_table_lookup (device_manager->id_table,
1292 GINT_TO_POINTER (xev->deviceid));
1294 source_device = g_hash_table_lookup (device_manager->id_table,
1295 GUINT_TO_POINTER (xev->sourceid));
1297 handle_focus_change (window, device, source_device,
1298 xev->detail, xev->mode,
1299 (ev->evtype == XI_FocusIn) ? TRUE : FALSE);
1308 event->any.send_event = cookie->send_event;
1312 if (event->any.window)
1313 g_object_ref (event->any.window);
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);
1322 /* Mark this event as having no resources to be freed */
1323 event->any.window = NULL;
1324 event->any.type = GDK_NOTHING;
1327 XFreeEventData (dpy, cookie);
1333 gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
1335 return (GDK_KEY_PRESS_MASK |
1336 GDK_KEY_RELEASE_MASK |
1337 GDK_BUTTON_PRESS_MASK |
1338 GDK_BUTTON_RELEASE_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);
1352 gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
1354 GdkEventMask evmask)
1356 GdkDeviceManager *device_manager;
1357 XIEventMask event_mask;
1359 device_manager = GDK_DEVICE_MANAGER (translator);
1361 event_mask.deviceid = XIAllMasterDevices;
1362 event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (evmask, &event_mask.mask_len);
1364 _gdk_x11_device_manager_xi2_select_events (device_manager, window, &event_mask);
1365 g_free (event_mask.mask);
1368 #else /* XINPUT_2 */
1371 gdk_x11_device_manager_xi2_class_init (GdkX11DeviceManagerXI2Class *klass)
1376 gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
1381 gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
1385 #endif /* XINPUT_2 */