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.h"
26 #include "gdkdeviceprivate.h"
27 #include "gdkdisplayprivate.h"
28 #include "gdkeventtranslator.h"
29 #include "gdkprivate-x11.h"
31 #include "gdkkeysyms.h"
34 #include <X11/Xutil.h>
35 #include <X11/extensions/XInput2.h>
39 struct _GdkX11DeviceManagerXI2
41 GdkDeviceManager parent_object;
50 struct _GdkX11DeviceManagerXI2Class
52 GdkDeviceManagerClass parent_class;
55 #define HAS_FOCUS(toplevel) ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
58 static void gdk_x11_device_manager_xi2_constructed (GObject *object);
59 static void gdk_x11_device_manager_xi2_dispose (GObject *object);
60 static void gdk_x11_device_manager_xi2_set_property (GObject *object,
64 static void gdk_x11_device_manager_xi2_get_property (GObject *object,
69 static GList * gdk_x11_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
71 static GdkDevice * gdk_x11_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager);
73 static void gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
75 static gboolean gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
79 static GdkEventMask gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator);
80 static void gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
82 GdkEventMask event_mask);
85 G_DEFINE_TYPE_WITH_CODE (GdkX11DeviceManagerXI2, gdk_x11_device_manager_xi2, GDK_TYPE_X11_DEVICE_MANAGER_CORE,
86 G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
87 gdk_x11_device_manager_xi2_event_translator_init))
96 gdk_x11_device_manager_xi2_class_init (GdkX11DeviceManagerXI2Class *klass)
98 GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
99 GObjectClass *object_class = G_OBJECT_CLASS (klass);
101 object_class->constructed = gdk_x11_device_manager_xi2_constructed;
102 object_class->dispose = gdk_x11_device_manager_xi2_dispose;
103 object_class->set_property = gdk_x11_device_manager_xi2_set_property;
104 object_class->get_property = gdk_x11_device_manager_xi2_get_property;
106 device_manager_class->list_devices = gdk_x11_device_manager_xi2_list_devices;
107 device_manager_class->get_client_pointer = gdk_x11_device_manager_xi2_get_client_pointer;
109 g_object_class_install_property (object_class,
111 g_param_spec_int ("opcode",
113 P_("Opcode for XInput2 requests"),
115 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
119 gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
121 device_manager->id_table = g_hash_table_new_full (g_direct_hash,
124 (GDestroyNotify) g_object_unref);
128 _gdk_x11_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
130 XIEventMask *event_mask)
135 display = gdk_device_manager_get_display (device_manager);
136 xdisplay = GDK_DISPLAY_XDISPLAY (display);
138 XISelectEvents (xdisplay, xwindow, event_mask, 1);
142 translate_valuator_class (GdkDisplay *display,
144 XIValuatorClassInfo *info,
147 static gboolean initialized = FALSE;
148 static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
149 GdkAxisUse use = GDK_AXIS_IGNORE;
155 label_atoms [GDK_AXIS_X] = gdk_x11_get_xatom_by_name_for_display (display, "Abs X");
156 label_atoms [GDK_AXIS_Y] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Y");
157 label_atoms [GDK_AXIS_PRESSURE] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Pressure");
158 label_atoms [GDK_AXIS_XTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt X");
159 label_atoms [GDK_AXIS_YTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt Y");
160 label_atoms [GDK_AXIS_WHEEL] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Wheel");
164 for (i = GDK_AXIS_IGNORE; i <= GDK_AXIS_LAST; i++)
166 if (label_atoms[i] == info->label)
173 if (info->label != None)
174 label = gdk_x11_xatom_to_atom_for_display (display, info->label);
178 _gdk_device_add_axis (device,
187 translate_device_classes (GdkDisplay *display,
189 XIAnyClassInfo **classes,
192 gint i, n_valuator = 0;
194 g_object_freeze_notify (G_OBJECT (device));
196 for (i = 0; i < n_classes; i++)
198 XIAnyClassInfo *class_info = classes[i];
200 switch (class_info->type)
204 XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info;
207 _gdk_device_set_keys (device, key_info->num_keycodes);
209 for (i = 0; i < key_info->num_keycodes; i++)
210 gdk_device_set_key (device, i, key_info->keycodes[i], 0);
213 case XIValuatorClass:
214 translate_valuator_class (display, device,
215 (XIValuatorClassInfo *) class_info,
225 g_object_thaw_notify (G_OBJECT (device));
229 create_device (GdkDeviceManager *device_manager,
233 GdkInputSource input_source;
238 if (dev->use == XIMasterKeyboard || dev->use == XISlaveKeyboard)
239 input_source = GDK_SOURCE_KEYBOARD;
244 tmp_name = g_ascii_strdown (dev->name, -1);
246 if (strstr (tmp_name, "eraser"))
247 input_source = GDK_SOURCE_ERASER;
248 else if (strstr (tmp_name, "cursor"))
249 input_source = GDK_SOURCE_CURSOR;
250 else if (strstr (tmp_name, "wacom") ||
251 strstr (tmp_name, "pen"))
252 input_source = GDK_SOURCE_PEN;
254 input_source = GDK_SOURCE_MOUSE;
261 case XIMasterKeyboard:
262 case XIMasterPointer:
263 type = GDK_DEVICE_TYPE_MASTER;
264 mode = GDK_MODE_SCREEN;
266 case XISlaveKeyboard:
268 type = GDK_DEVICE_TYPE_SLAVE;
269 mode = GDK_MODE_DISABLED;
271 case XIFloatingSlave:
273 type = GDK_DEVICE_TYPE_FLOATING;
274 mode = GDK_MODE_DISABLED;
278 device = g_object_new (GDK_TYPE_X11_DEVICE_XI2,
281 "input-source", input_source,
283 "has-cursor", (dev->use == XIMasterPointer),
285 "device-manager", device_manager,
286 "device-id", dev->deviceid,
289 translate_device_classes (display, device, dev->classes, dev->num_classes);
295 add_device (GdkX11DeviceManagerXI2 *device_manager,
297 gboolean emit_signal)
302 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
303 device = create_device (GDK_DEVICE_MANAGER (device_manager), display, dev);
305 g_hash_table_replace (device_manager->id_table,
306 GINT_TO_POINTER (dev->deviceid),
307 g_object_ref (device));
309 device_manager->devices = g_list_append (device_manager->devices, device);
313 if (dev->use == XISlavePointer || dev->use == XISlaveKeyboard)
317 /* The device manager is already constructed, then
318 * keep the hierarchy coherent for the added device.
320 master = g_hash_table_lookup (device_manager->id_table,
321 GINT_TO_POINTER (dev->attachment));
323 _gdk_device_set_associated_device (device, master);
324 _gdk_device_add_slave (master, device);
327 g_signal_emit_by_name (device_manager, "device-added", device);
334 remove_device (GdkX11DeviceManagerXI2 *device_manager,
339 device = g_hash_table_lookup (device_manager->id_table,
340 GINT_TO_POINTER (device_id));
344 device_manager->devices = g_list_remove (device_manager->devices, device);
346 g_signal_emit_by_name (device_manager, "device-removed", device);
348 g_object_run_dispose (G_OBJECT (device));
350 g_hash_table_remove (device_manager->id_table,
351 GINT_TO_POINTER (device_id));
356 relate_masters (gpointer key,
360 GdkX11DeviceManagerXI2 *device_manager;
361 GdkDevice *device, *relative;
363 device_manager = user_data;
364 device = g_hash_table_lookup (device_manager->id_table, key);
365 relative = g_hash_table_lookup (device_manager->id_table, value);
367 _gdk_device_set_associated_device (device, relative);
368 _gdk_device_set_associated_device (relative, device);
372 relate_slaves (gpointer key,
376 GdkX11DeviceManagerXI2 *device_manager;
377 GdkDevice *slave, *master;
379 device_manager = user_data;
380 slave = g_hash_table_lookup (device_manager->id_table, key);
381 master = g_hash_table_lookup (device_manager->id_table, value);
383 _gdk_device_set_associated_device (slave, master);
384 _gdk_device_add_slave (master, slave);
388 gdk_x11_device_manager_xi2_constructed (GObject *object)
390 GdkX11DeviceManagerXI2 *device_manager;
393 GHashTable *masters, *slaves;
395 XIDeviceInfo *info, *dev;
397 XIEventMask event_mask;
398 unsigned char mask[2] = { 0 };
400 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
401 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
402 xdisplay = GDK_DISPLAY_XDISPLAY (display);
404 masters = g_hash_table_new (NULL, NULL);
405 slaves = g_hash_table_new (NULL, NULL);
407 info = XIQueryDevice (xdisplay, XIAllDevices, &ndevices);
409 /* Initialize devices list */
410 for (i = 0; i < ndevices; i++)
413 add_device (device_manager, dev, FALSE);
415 if (dev->use == XIMasterPointer ||
416 dev->use == XIMasterKeyboard)
418 g_hash_table_insert (masters,
419 GINT_TO_POINTER (dev->deviceid),
420 GINT_TO_POINTER (dev->attachment));
422 else if (dev->use == XISlavePointer ||
423 dev->use == XISlaveKeyboard)
425 g_hash_table_insert (slaves,
426 GINT_TO_POINTER (dev->deviceid),
427 GINT_TO_POINTER (dev->attachment));
431 XIFreeDeviceInfo (info);
433 /* Stablish relationships between devices */
434 g_hash_table_foreach (masters, relate_masters, object);
435 g_hash_table_destroy (masters);
437 g_hash_table_foreach (slaves, relate_slaves, object);
438 g_hash_table_destroy (slaves);
440 /* Connect to hierarchy change events */
441 screen = gdk_display_get_default_screen (display);
442 XISetMask (mask, XI_HierarchyChanged);
443 XISetMask (mask, XI_DeviceChanged);
445 event_mask.deviceid = XIAllDevices;
446 event_mask.mask_len = sizeof (mask);
447 event_mask.mask = mask;
449 _gdk_x11_device_manager_xi2_select_events (GDK_DEVICE_MANAGER (object),
450 GDK_WINDOW_XID (gdk_screen_get_root_window (screen)),
455 gdk_x11_device_manager_xi2_dispose (GObject *object)
457 GdkX11DeviceManagerXI2 *device_manager;
459 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
461 g_list_free_full (device_manager->devices, g_object_unref);
462 device_manager->devices = NULL;
464 if (device_manager->id_table)
466 g_hash_table_destroy (device_manager->id_table);
467 device_manager->id_table = NULL;
470 G_OBJECT_CLASS (gdk_x11_device_manager_xi2_parent_class)->dispose (object);
474 gdk_x11_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
477 GdkX11DeviceManagerXI2 *device_manager_xi2;
478 GList *cur, *list = NULL;
480 device_manager_xi2 = GDK_X11_DEVICE_MANAGER_XI2 (device_manager);
482 for (cur = device_manager_xi2->devices; cur; cur = cur->next)
484 GdkDevice *dev = cur->data;
486 if (type == gdk_device_get_device_type (dev))
487 list = g_list_prepend (list, dev);
494 gdk_x11_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager)
496 GdkX11DeviceManagerXI2 *device_manager_xi2;
500 device_manager_xi2 = (GdkX11DeviceManagerXI2 *) device_manager;
501 display = gdk_device_manager_get_display (device_manager);
503 XIGetClientPointer (GDK_DISPLAY_XDISPLAY (display),
506 return g_hash_table_lookup (device_manager_xi2->id_table,
507 GINT_TO_POINTER (device_id));
511 gdk_x11_device_manager_xi2_set_property (GObject *object,
516 GdkX11DeviceManagerXI2 *device_manager;
518 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
523 device_manager->opcode = g_value_get_int (value);
526 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
532 gdk_x11_device_manager_xi2_get_property (GObject *object,
537 GdkX11DeviceManagerXI2 *device_manager;
539 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
544 g_value_set_int (value, device_manager->opcode);
547 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
553 gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
555 iface->translate_event = gdk_x11_device_manager_xi2_translate_event;
556 iface->get_handled_events = gdk_x11_device_manager_xi2_get_handled_events;
557 iface->select_window_events = gdk_x11_device_manager_xi2_select_window_events;
561 handle_hierarchy_changed (GdkX11DeviceManagerXI2 *device_manager,
562 XIHierarchyEvent *ev)
570 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
571 xdisplay = GDK_DISPLAY_XDISPLAY (display);
573 for (i = 0; i < ev->num_info; i++)
575 if (ev->info[i].flags & XIDeviceEnabled)
577 info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
578 add_device (device_manager, &info[0], TRUE);
579 XIFreeDeviceInfo (info);
581 else if (ev->info[i].flags & XIDeviceDisabled)
582 remove_device (device_manager, ev->info[i].deviceid);
583 else if (ev->info[i].flags & XISlaveAttached ||
584 ev->info[i].flags & XISlaveDetached)
586 GdkDevice *master, *slave;
588 slave = g_hash_table_lookup (device_manager->id_table,
589 GINT_TO_POINTER (ev->info[i].deviceid));
591 /* Remove old master info */
592 master = gdk_device_get_associated_device (slave);
596 _gdk_device_remove_slave (master, slave);
597 _gdk_device_set_associated_device (slave, NULL);
599 g_signal_emit_by_name (device_manager, "device-changed", master);
602 /* Add new master if it's an attachment event */
603 if (ev->info[i].flags & XISlaveAttached)
605 info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
607 master = g_hash_table_lookup (device_manager->id_table,
608 GINT_TO_POINTER (info->attachment));
610 _gdk_device_set_associated_device (slave, master);
611 _gdk_device_add_slave (master, slave);
613 g_signal_emit_by_name (device_manager, "device-changed", master);
616 g_signal_emit_by_name (device_manager, "device-changed", slave);
622 handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
623 XIDeviceChangedEvent *ev)
628 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
629 device = g_hash_table_lookup (device_manager->id_table,
630 GUINT_TO_POINTER (ev->deviceid));
632 _gdk_device_reset_axes (device);
633 translate_device_classes (display, device, ev->classes, ev->num_classes);
635 g_signal_emit_by_name (G_OBJECT (device), "changed");
638 static GdkCrossingMode
639 translate_crossing_mode (gint mode)
644 return GDK_CROSSING_NORMAL;
646 return GDK_CROSSING_GRAB;
648 return GDK_CROSSING_UNGRAB;
650 g_assert_not_reached ();
655 translate_notify_type (gint detail)
660 return GDK_NOTIFY_INFERIOR;
662 return GDK_NOTIFY_ANCESTOR;
664 return GDK_NOTIFY_VIRTUAL;
665 case NotifyNonlinear:
666 return GDK_NOTIFY_NONLINEAR;
667 case NotifyNonlinearVirtual:
668 return GDK_NOTIFY_NONLINEAR_VIRTUAL;
670 g_assert_not_reached ();
675 set_screen_from_root (GdkDisplay *display,
681 screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
685 gdk_event_set_screen (event, screen);
694 set_user_time (GdkEvent *event)
699 window = gdk_window_get_toplevel (event->any.window);
700 g_return_if_fail (GDK_IS_WINDOW (window));
702 time = gdk_event_get_time (event);
704 /* If an event doesn't have a valid timestamp, we shouldn't use it
705 * to update the latest user interaction time.
707 if (time != GDK_CURRENT_TIME)
708 gdk_x11_window_set_user_time (window, time);
712 translate_keyboard_string (GdkEventKey *event)
717 /* Fill in event->string crudely, since various programs
720 event->string = NULL;
722 if (event->keyval != GDK_KEY_VoidSymbol)
723 c = gdk_keyval_to_unicode (event->keyval);
730 /* Apply the control key - Taken from Xlib
732 if (event->state & GDK_CONTROL_MASK)
734 if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
737 event->string = g_memdup ("\0\0", 2);
742 else if (c >= '3' && c <= '7') c -= ('3' - '\033');
743 else if (c == '8') c = '\177';
744 else if (c == '/') c = '_' & 0x1F;
747 len = g_unichar_to_utf8 (c, buf);
750 event->string = g_locale_from_utf8 (buf, len,
751 NULL, &bytes_written,
754 event->length = bytes_written;
756 else if (event->keyval == GDK_KEY_Escape)
759 event->string = g_strdup ("\033");
761 else if (event->keyval == GDK_KEY_Return ||
762 event->keyval == GDK_KEY_KP_Enter)
765 event->string = g_strdup ("\r");
771 event->string = g_strdup ("");
776 generate_focus_event (GdkWindow *window,
778 GdkDevice *source_device,
783 event = gdk_event_new (GDK_FOCUS_CHANGE);
784 event->focus_change.window = g_object_ref (window);
785 event->focus_change.send_event = FALSE;
786 event->focus_change.in = in;
787 gdk_event_set_device (event, device);
788 gdk_event_set_source_device (event, source_device);
790 gdk_event_put (event);
791 gdk_event_free (event);
795 handle_focus_change (GdkWindow *window,
797 GdkDevice *source_device,
802 GdkToplevelX11 *toplevel;
805 toplevel = _gdk_x11_window_get_toplevel (window);
810 had_focus = HAS_FOCUS (toplevel);
816 /* When the focus moves from an ancestor of the window to
817 * the window or a descendent of the window, *and* the
818 * pointer is inside the window, then we were previously
819 * receiving keystroke events in the has_pointer_focus
820 * case and are now receiving them in the
821 * has_focus_window case.
823 if (toplevel->has_pointer &&
824 mode != NotifyGrab &&
825 mode != NotifyUngrab)
826 toplevel->has_pointer_focus = (in) ? FALSE : TRUE;
829 case NotifyNonlinear:
830 case NotifyNonlinearVirtual:
831 if (mode != NotifyGrab &&
832 mode != NotifyUngrab)
833 toplevel->has_focus_window = (in) ? TRUE : FALSE;
834 /* We pretend that the focus moves to the grab
835 * window, so we pay attention to NotifyGrab
836 * NotifyUngrab, and ignore NotifyWhileGrabbed
838 if (mode != NotifyWhileGrabbed)
839 toplevel->has_focus = (in) ? TRUE : FALSE;
842 /* The X server sends NotifyPointer/NotifyGrab,
843 * but the pointer focus is ignored while a
846 if (mode != NotifyGrab &&
847 mode != NotifyUngrab)
848 toplevel->has_pointer_focus = (in) ? TRUE :FALSE;
851 case NotifyPointerRoot:
852 case NotifyDetailNone:
856 if (HAS_FOCUS (toplevel) != had_focus)
857 generate_focus_event (window, device, source_device, (in) ? TRUE : FALSE);
861 translate_axes (GdkDevice *device,
865 XIValuatorState *valuators)
871 g_object_get (device, "n-axes", &n_axes, NULL);
873 axes = g_new0 (gdouble, n_axes);
874 vals = valuators->values;
876 for (i = 0; i < valuators->mask_len * 8; i++)
881 if (!XIMaskIsSet (valuators->mask, i))
884 use = _gdk_device_get_axis_use (device, i);
891 if (gdk_device_get_mode (device) == GDK_MODE_WINDOW)
892 _gdk_device_translate_window_coord (device, window, i, val, &axes[i]);
895 if (use == GDK_AXIS_X)
902 _gdk_device_translate_axis (device, i, val, &axes[i]);
911 is_parent_of (GdkWindow *parent,
922 w = gdk_window_get_parent (w);
929 get_event_window (GdkEventTranslator *translator,
933 GdkWindow *window = NULL;
935 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (translator));
942 case XI_ButtonRelease:
945 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
947 window = gdk_x11_window_lookup_for_display (display, xev->event);
949 /* Apply keyboard grabs to non-native windows */
950 if (ev->evtype == XI_KeyPress || ev->evtype == XI_KeyRelease)
952 GdkDeviceGrabInfo *info;
956 device = g_hash_table_lookup (GDK_X11_DEVICE_MANAGER_XI2 (translator)->id_table,
957 GUINT_TO_POINTER (((XIDeviceEvent *) ev)->deviceid));
959 serial = _gdk_display_get_next_serial (display);
960 info = _gdk_display_has_device_grab (display, device, serial);
963 (!is_parent_of (info->window, window) ||
964 !info->owner_events))
966 /* Report key event against grab window */
967 window = info->window;
977 XIEnterEvent *xev = (XIEnterEvent *) ev;
979 window = gdk_x11_window_lookup_for_display (display, xev->event);
988 gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
993 GdkX11DeviceManagerXI2 *device_manager;
994 GdkEventTranslatorIface *parent_iface;
995 XGenericEventCookie *cookie;
996 gboolean return_val = TRUE;
1001 dpy = GDK_DISPLAY_XDISPLAY (display);
1002 device_manager = (GdkX11DeviceManagerXI2 *) translator;
1003 cookie = &xevent->xcookie;
1005 parent_iface = g_type_interface_peek_parent (GDK_EVENT_TRANSLATOR_GET_IFACE (translator));
1007 /* The X input methods (when triggered via XFilterEvent) generate
1008 * a core key press event with keycode 0 to signal the end of a
1009 * key sequence. We use the core translate_event implementation
1010 * to translate this event.
1012 * This is just a bandaid fix to keep xim working with a single
1013 * keyboard until XFilterEvent learns about XI2.
1015 if (xevent->type == KeyPress && xevent->xkey.keycode == 0 &&
1016 parent_iface->translate_event (translator, display, event, xevent))
1020 /* The core device manager sets a core device on the event.
1021 * We need to override that with an XI2 device, since we are
1024 device = gdk_x11_device_manager_xi2_get_client_pointer ((GdkDeviceManager *)device_manager);
1025 gdk_event_set_device (event, gdk_device_get_associated_device (device));
1030 if (!XGetEventData (dpy, cookie))
1033 if (cookie->type != GenericEvent ||
1034 cookie->extension != device_manager->opcode)
1036 XFreeEventData (dpy, cookie);
1040 ev = (XIEvent *) cookie->data;
1042 window = get_event_window (translator, ev);
1044 if (window && GDK_WINDOW_DESTROYED (window))
1046 XFreeEventData (dpy, cookie);
1050 if (ev->evtype == XI_Motion ||
1051 ev->evtype == XI_ButtonRelease)
1053 if (_gdk_x11_moveresize_handle_event (xevent))
1055 XFreeEventData (dpy, cookie);
1062 case XI_HierarchyChanged:
1063 handle_hierarchy_changed (device_manager,
1064 (XIHierarchyEvent *) ev);
1067 case XI_DeviceChanged:
1068 handle_device_changed (device_manager,
1069 (XIDeviceChangedEvent *) ev);
1075 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1076 GdkKeymap *keymap = gdk_keymap_get_for_display (display);
1077 GdkModifierType consumed, state;
1078 GdkDevice *device, *source_device;
1080 event->key.type = xev->evtype == XI_KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
1082 event->key.window = window;
1084 event->key.time = xev->time;
1085 event->key.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons);
1086 event->key.group = _gdk_x11_get_group_for_state (display, event->key.state);
1088 event->key.hardware_keycode = xev->detail;
1089 event->key.is_modifier = _gdk_x11_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
1091 device = g_hash_table_lookup (device_manager->id_table,
1092 GUINT_TO_POINTER (xev->deviceid));
1093 gdk_event_set_device (event, device);
1095 source_device = g_hash_table_lookup (device_manager->id_table,
1096 GUINT_TO_POINTER (xev->sourceid));
1097 gdk_event_set_source_device (event, source_device);
1099 event->key.keyval = GDK_KEY_VoidSymbol;
1101 gdk_keymap_translate_keyboard_state (keymap,
1102 event->key.hardware_keycode,
1106 NULL, NULL, &consumed);
1108 state = event->key.state & ~consumed;
1109 _gdk_x11_keymap_add_virt_mods (keymap, &state);
1110 event->key.state |= state;
1112 translate_keyboard_string ((GdkEventKey *) event);
1114 if (ev->evtype == XI_KeyPress)
1115 set_user_time (event);
1117 /* FIXME: emulate autorepeat on key
1118 * release? XI2 seems attached to Xkb.
1123 case XI_ButtonPress:
1124 case XI_ButtonRelease:
1126 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1127 GdkDevice *source_device;
1129 switch (xev->detail)
1135 event->scroll.type = GDK_SCROLL;
1137 if (xev->detail == 4)
1138 event->scroll.direction = GDK_SCROLL_UP;
1139 else if (xev->detail == 5)
1140 event->scroll.direction = GDK_SCROLL_DOWN;
1141 else if (xev->detail == 6)
1142 event->scroll.direction = GDK_SCROLL_LEFT;
1144 event->scroll.direction = GDK_SCROLL_RIGHT;
1146 event->scroll.window = window;
1147 event->scroll.time = xev->time;
1148 event->scroll.x = (gdouble) xev->event_x;
1149 event->scroll.y = (gdouble) xev->event_y;
1150 event->scroll.x_root = (gdouble) xev->root_x;
1151 event->scroll.y_root = (gdouble) xev->root_y;
1153 event->scroll.device = g_hash_table_lookup (device_manager->id_table,
1154 GUINT_TO_POINTER (xev->deviceid));
1156 source_device = g_hash_table_lookup (device_manager->id_table,
1157 GUINT_TO_POINTER (xev->sourceid));
1158 gdk_event_set_source_device (event, source_device);
1160 event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons);
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);
1195 event->button.button = xev->detail;
1198 if (!set_screen_from_root (display, event, xev->root))
1204 set_user_time (event);
1210 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1211 GdkDevice *source_device;
1213 event->motion.type = GDK_MOTION_NOTIFY;
1215 event->motion.window = window;
1217 event->motion.time = xev->time;
1218 event->motion.x = (gdouble) xev->event_x;
1219 event->motion.y = (gdouble) xev->event_y;
1220 event->motion.x_root = (gdouble) xev->root_x;
1221 event->motion.y_root = (gdouble) xev->root_y;
1223 event->motion.device = g_hash_table_lookup (device_manager->id_table,
1224 GINT_TO_POINTER (xev->deviceid));
1226 source_device = g_hash_table_lookup (device_manager->id_table,
1227 GUINT_TO_POINTER (xev->sourceid));
1228 gdk_event_set_source_device (event, source_device);
1230 event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons);
1232 /* There doesn't seem to be motion hints in XI */
1233 event->motion.is_hint = FALSE;
1235 event->motion.axes = translate_axes (event->motion.device,
1238 event->motion.window,
1241 if (gdk_device_get_mode (event->motion.device) == GDK_MODE_WINDOW)
1243 GdkDevice *device = event->motion.device;
1245 /* Update event coordinates from axes */
1246 gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_X, &event->motion.x);
1247 gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_Y, &event->motion.y);
1254 XIEnterEvent *xev = (XIEnterEvent *) ev;
1255 GdkDevice *device, *source_device;
1257 event->crossing.type = (ev->evtype == XI_Enter) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
1259 event->crossing.x = (gdouble) xev->event_x;
1260 event->crossing.y = (gdouble) xev->event_y;
1261 event->crossing.x_root = (gdouble) xev->root_x;
1262 event->crossing.y_root = (gdouble) xev->root_y;
1263 event->crossing.time = xev->time;
1264 event->crossing.focus = xev->focus;
1266 event->crossing.window = window;
1267 event->crossing.subwindow = gdk_x11_window_lookup_for_display (display, xev->child);
1269 device = g_hash_table_lookup (device_manager->id_table,
1270 GINT_TO_POINTER (xev->deviceid));
1271 gdk_event_set_device (event, device);
1273 source_device = g_hash_table_lookup (device_manager->id_table,
1274 GUINT_TO_POINTER (xev->sourceid));
1275 gdk_event_set_source_device (event, source_device);
1277 event->crossing.mode = translate_crossing_mode (xev->mode);
1278 event->crossing.detail = translate_notify_type (xev->detail);
1279 event->crossing.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons);
1285 XIEnterEvent *xev = (XIEnterEvent *) ev;
1286 GdkDevice *device, *source_device;
1288 device = g_hash_table_lookup (device_manager->id_table,
1289 GINT_TO_POINTER (xev->deviceid));
1291 source_device = g_hash_table_lookup (device_manager->id_table,
1292 GUINT_TO_POINTER (xev->sourceid));
1294 handle_focus_change (window, device, source_device,
1295 xev->detail, xev->mode,
1296 (ev->evtype == XI_FocusIn) ? TRUE : FALSE);
1305 event->any.send_event = cookie->send_event;
1309 if (event->any.window)
1310 g_object_ref (event->any.window);
1312 if (((event->any.type == GDK_ENTER_NOTIFY) ||
1313 (event->any.type == GDK_LEAVE_NOTIFY)) &&
1314 (event->crossing.subwindow != NULL))
1315 g_object_ref (event->crossing.subwindow);
1319 /* Mark this event as having no resources to be freed */
1320 event->any.window = NULL;
1321 event->any.type = GDK_NOTHING;
1324 XFreeEventData (dpy, cookie);
1330 gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
1332 return (GDK_KEY_PRESS_MASK |
1333 GDK_KEY_RELEASE_MASK |
1334 GDK_BUTTON_PRESS_MASK |
1335 GDK_BUTTON_RELEASE_MASK |
1337 GDK_ENTER_NOTIFY_MASK |
1338 GDK_LEAVE_NOTIFY_MASK |
1339 GDK_POINTER_MOTION_MASK |
1340 GDK_POINTER_MOTION_HINT_MASK |
1341 GDK_BUTTON1_MOTION_MASK |
1342 GDK_BUTTON2_MOTION_MASK |
1343 GDK_BUTTON3_MOTION_MASK |
1344 GDK_BUTTON_MOTION_MASK |
1345 GDK_FOCUS_CHANGE_MASK);
1349 gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
1351 GdkEventMask evmask)
1353 GdkDeviceManager *device_manager;
1354 XIEventMask event_mask;
1356 device_manager = GDK_DEVICE_MANAGER (translator);
1358 event_mask.deviceid = XIAllMasterDevices;
1359 event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (evmask, &event_mask.mask_len);
1361 _gdk_x11_device_manager_xi2_select_events (device_manager, window, &event_mask);
1362 g_free (event_mask.mask);