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, see <http://www.gnu.org/licenses/>.
20 #include "gdkx11devicemanager-xi2.h"
21 #include "gdkx11device-xi2.h"
23 #include "gdkdevicemanagerprivate-core.h"
24 #include "gdkdeviceprivate.h"
25 #include "gdkdisplayprivate.h"
26 #include "gdkeventtranslator.h"
27 #include "gdkprivate-x11.h"
29 #include "gdkkeysyms.h"
30 #include "gdkinternals.h"
33 #include <X11/Xutil.h>
34 #include <X11/extensions/XInput2.h>
38 struct _GdkX11DeviceManagerXI2
40 GdkX11DeviceManagerCore parent_object;
51 struct _GdkX11DeviceManagerXI2Class
53 GdkDeviceManagerClass parent_class;
56 static void gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
58 G_DEFINE_TYPE_WITH_CODE (GdkX11DeviceManagerXI2, gdk_x11_device_manager_xi2, GDK_TYPE_X11_DEVICE_MANAGER_CORE,
59 G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
60 gdk_x11_device_manager_xi2_event_translator_init))
63 #define HAS_FOCUS(toplevel) ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
66 static void gdk_x11_device_manager_xi2_constructed (GObject *object);
67 static void gdk_x11_device_manager_xi2_dispose (GObject *object);
68 static void gdk_x11_device_manager_xi2_set_property (GObject *object,
72 static void gdk_x11_device_manager_xi2_get_property (GObject *object,
77 static GList * gdk_x11_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
79 static GdkDevice * gdk_x11_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager);
81 static gboolean gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
85 static GdkEventMask gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator);
86 static void gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
88 GdkEventMask event_mask);
89 static GdkWindow * gdk_x11_device_manager_xi2_get_window (GdkEventTranslator *translator,
100 gdk_x11_device_manager_xi2_class_init (GdkX11DeviceManagerXI2Class *klass)
102 GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
103 GObjectClass *object_class = G_OBJECT_CLASS (klass);
105 object_class->constructed = gdk_x11_device_manager_xi2_constructed;
106 object_class->dispose = gdk_x11_device_manager_xi2_dispose;
107 object_class->set_property = gdk_x11_device_manager_xi2_set_property;
108 object_class->get_property = gdk_x11_device_manager_xi2_get_property;
110 device_manager_class->list_devices = gdk_x11_device_manager_xi2_list_devices;
111 device_manager_class->get_client_pointer = gdk_x11_device_manager_xi2_get_client_pointer;
113 g_object_class_install_property (object_class,
115 g_param_spec_int ("opcode",
117 P_("Opcode for XInput2 requests"),
119 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
120 g_object_class_install_property (object_class,
122 g_param_spec_int ("major",
124 P_("Major version number"),
126 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
127 g_object_class_install_property (object_class,
129 g_param_spec_int ("minor",
131 P_("Minor version number"),
133 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
137 gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
139 device_manager->id_table = g_hash_table_new_full (g_direct_hash,
142 (GDestroyNotify) g_object_unref);
146 _gdk_x11_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
148 XIEventMask *event_mask)
153 display = gdk_device_manager_get_display (device_manager);
154 xdisplay = GDK_DISPLAY_XDISPLAY (display);
156 XISelectEvents (xdisplay, xwindow, event_mask, 1);
160 translate_valuator_class (GdkDisplay *display,
167 static gboolean initialized = FALSE;
168 static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
169 GdkAxisUse use = GDK_AXIS_IGNORE;
175 label_atoms [GDK_AXIS_X] = gdk_x11_get_xatom_by_name_for_display (display, "Abs X");
176 label_atoms [GDK_AXIS_Y] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Y");
177 label_atoms [GDK_AXIS_PRESSURE] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Pressure");
178 label_atoms [GDK_AXIS_XTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt X");
179 label_atoms [GDK_AXIS_YTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt Y");
180 label_atoms [GDK_AXIS_WHEEL] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Wheel");
184 for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
186 if (label_atoms[i] == valuator_label)
193 if (valuator_label != None)
194 label = gdk_x11_xatom_to_atom_for_display (display, valuator_label);
198 _gdk_device_add_axis (device, label, use, min, max, resolution);
202 translate_device_classes (GdkDisplay *display,
204 XIAnyClassInfo **classes,
209 g_object_freeze_notify (G_OBJECT (device));
211 for (i = 0; i < n_classes; i++)
213 XIAnyClassInfo *class_info = classes[i];
215 switch (class_info->type)
219 XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info;
222 _gdk_device_set_keys (device, key_info->num_keycodes);
224 for (i = 0; i < key_info->num_keycodes; i++)
225 gdk_device_set_key (device, i, key_info->keycodes[i], 0);
228 case XIValuatorClass:
230 XIValuatorClassInfo *valuator_info = (XIValuatorClassInfo *) class_info;
231 translate_valuator_class (display, device,
232 valuator_info->label,
235 valuator_info->resolution);
241 XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info;
242 GdkScrollDirection direction;
244 if (scroll_info->scroll_type == XIScrollTypeVertical)
245 direction = GDK_SCROLL_DOWN;
247 direction = GDK_SCROLL_RIGHT;
250 g_message ("\n\tscroll valuator %d: %s, increment %f",
252 scroll_info->scroll_type == XIScrollTypeVertical
255 scroll_info->increment));
257 _gdk_x11_device_xi2_add_scroll_valuator (GDK_X11_DEVICE_XI2 (device),
260 scroll_info->increment);
262 #endif /* XINPUT_2_2 */
269 g_object_thaw_notify (G_OBJECT (device));
273 is_touch_device (XIAnyClassInfo **classes,
275 GdkInputSource *device_type,
281 for (i = 0; i < n_classes; i++)
283 XITouchClassInfo *class = (XITouchClassInfo *) classes[i];
285 if (class->type != XITouchClass)
288 if (class->num_touches > 0)
290 if (class->mode == XIDirectTouch)
291 *device_type = GDK_SOURCE_TOUCHSCREEN;
292 else if (class->mode == XIDependentTouch)
293 *device_type = GDK_SOURCE_TOUCHPAD;
297 *num_touches = class->num_touches;
308 create_device (GdkDeviceManager *device_manager,
312 GdkInputSource input_source;
313 GdkInputSource touch_source;
317 gint num_touches = 0;
319 if (dev->use == XIMasterKeyboard || dev->use == XISlaveKeyboard)
320 input_source = GDK_SOURCE_KEYBOARD;
321 else if (dev->use == XISlavePointer &&
322 is_touch_device (dev->classes, dev->num_classes, &touch_source, &num_touches))
323 input_source = touch_source;
328 tmp_name = g_ascii_strdown (dev->name, -1);
330 if (strstr (tmp_name, "eraser"))
331 input_source = GDK_SOURCE_ERASER;
332 else if (strstr (tmp_name, "cursor"))
333 input_source = GDK_SOURCE_CURSOR;
334 else if (strstr (tmp_name, "wacom") ||
335 strstr (tmp_name, "pen"))
336 input_source = GDK_SOURCE_PEN;
338 input_source = GDK_SOURCE_MOUSE;
345 case XIMasterKeyboard:
346 case XIMasterPointer:
347 type = GDK_DEVICE_TYPE_MASTER;
348 mode = GDK_MODE_SCREEN;
350 case XISlaveKeyboard:
352 type = GDK_DEVICE_TYPE_SLAVE;
353 mode = GDK_MODE_DISABLED;
355 case XIFloatingSlave:
357 type = GDK_DEVICE_TYPE_FLOATING;
358 mode = GDK_MODE_DISABLED;
364 const gchar *type_names[] = { "master", "slave", "floating" };
365 const gchar *source_names[] = { "mouse", "pen", "eraser", "cursor", "keyboard", "direct touch", "indirect touch" };
366 const gchar *mode_names[] = { "disabled", "screen", "window" };
367 g_message ("input device:\n\tname: %s\n\ttype: %s\n\tsource: %s\n\tmode: %s\n\thas cursor: %d\n\ttouches: %d",
370 source_names[input_source],
372 dev->use == XIMasterPointer,
376 device = g_object_new (GDK_TYPE_X11_DEVICE_XI2,
379 "input-source", input_source,
381 "has-cursor", (dev->use == XIMasterPointer),
383 "device-manager", device_manager,
384 "device-id", dev->deviceid,
387 translate_device_classes (display, device, dev->classes, dev->num_classes);
393 add_device (GdkX11DeviceManagerXI2 *device_manager,
395 gboolean emit_signal)
400 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
401 device = create_device (GDK_DEVICE_MANAGER (device_manager), display, dev);
403 g_hash_table_replace (device_manager->id_table,
404 GINT_TO_POINTER (dev->deviceid),
405 g_object_ref (device));
407 device_manager->devices = g_list_append (device_manager->devices, device);
411 if (dev->use == XISlavePointer || dev->use == XISlaveKeyboard)
415 /* The device manager is already constructed, then
416 * keep the hierarchy coherent for the added device.
418 master = g_hash_table_lookup (device_manager->id_table,
419 GINT_TO_POINTER (dev->attachment));
421 _gdk_device_set_associated_device (device, master);
422 _gdk_device_add_slave (master, device);
425 g_signal_emit_by_name (device_manager, "device-added", device);
432 remove_device (GdkX11DeviceManagerXI2 *device_manager,
437 device = g_hash_table_lookup (device_manager->id_table,
438 GINT_TO_POINTER (device_id));
442 device_manager->devices = g_list_remove (device_manager->devices, device);
444 g_signal_emit_by_name (device_manager, "device-removed", device);
446 g_object_run_dispose (G_OBJECT (device));
448 g_hash_table_remove (device_manager->id_table,
449 GINT_TO_POINTER (device_id));
454 relate_masters (gpointer key,
458 GdkX11DeviceManagerXI2 *device_manager;
459 GdkDevice *device, *relative;
461 device_manager = user_data;
462 device = g_hash_table_lookup (device_manager->id_table, key);
463 relative = g_hash_table_lookup (device_manager->id_table, value);
465 _gdk_device_set_associated_device (device, relative);
466 _gdk_device_set_associated_device (relative, device);
470 relate_slaves (gpointer key,
474 GdkX11DeviceManagerXI2 *device_manager;
475 GdkDevice *slave, *master;
477 device_manager = user_data;
478 slave = g_hash_table_lookup (device_manager->id_table, key);
479 master = g_hash_table_lookup (device_manager->id_table, value);
481 _gdk_device_set_associated_device (slave, master);
482 _gdk_device_add_slave (master, slave);
486 gdk_x11_device_manager_xi2_constructed (GObject *object)
488 GdkX11DeviceManagerXI2 *device_manager;
491 GHashTable *masters, *slaves;
493 XIDeviceInfo *info, *dev;
495 XIEventMask event_mask;
496 unsigned char mask[2] = { 0 };
498 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
499 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
500 xdisplay = GDK_DISPLAY_XDISPLAY (display);
502 g_assert (device_manager->major == 2);
504 masters = g_hash_table_new (NULL, NULL);
505 slaves = g_hash_table_new (NULL, NULL);
507 info = XIQueryDevice (xdisplay, XIAllDevices, &ndevices);
509 /* Initialize devices list */
510 for (i = 0; i < ndevices; i++)
517 add_device (device_manager, dev, FALSE);
519 if (dev->use == XIMasterPointer ||
520 dev->use == XIMasterKeyboard)
522 g_hash_table_insert (masters,
523 GINT_TO_POINTER (dev->deviceid),
524 GINT_TO_POINTER (dev->attachment));
526 else if (dev->use == XISlavePointer ||
527 dev->use == XISlaveKeyboard)
529 g_hash_table_insert (slaves,
530 GINT_TO_POINTER (dev->deviceid),
531 GINT_TO_POINTER (dev->attachment));
535 XIFreeDeviceInfo (info);
537 /* Stablish relationships between devices */
538 g_hash_table_foreach (masters, relate_masters, object);
539 g_hash_table_destroy (masters);
541 g_hash_table_foreach (slaves, relate_slaves, object);
542 g_hash_table_destroy (slaves);
544 /* Connect to hierarchy change events */
545 screen = gdk_display_get_default_screen (display);
546 XISetMask (mask, XI_HierarchyChanged);
547 XISetMask (mask, XI_DeviceChanged);
549 event_mask.deviceid = XIAllDevices;
550 event_mask.mask_len = sizeof (mask);
551 event_mask.mask = mask;
553 _gdk_x11_device_manager_xi2_select_events (GDK_DEVICE_MANAGER (object),
554 GDK_WINDOW_XID (gdk_screen_get_root_window (screen)),
559 gdk_x11_device_manager_xi2_dispose (GObject *object)
561 GdkX11DeviceManagerXI2 *device_manager;
563 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
565 g_list_free_full (device_manager->devices, g_object_unref);
566 device_manager->devices = NULL;
568 if (device_manager->id_table)
570 g_hash_table_destroy (device_manager->id_table);
571 device_manager->id_table = NULL;
574 G_OBJECT_CLASS (gdk_x11_device_manager_xi2_parent_class)->dispose (object);
578 gdk_x11_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
581 GdkX11DeviceManagerXI2 *device_manager_xi2;
582 GList *cur, *list = NULL;
584 device_manager_xi2 = GDK_X11_DEVICE_MANAGER_XI2 (device_manager);
586 for (cur = device_manager_xi2->devices; cur; cur = cur->next)
588 GdkDevice *dev = cur->data;
590 if (type == gdk_device_get_device_type (dev))
591 list = g_list_prepend (list, dev);
598 gdk_x11_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager)
600 GdkX11DeviceManagerXI2 *device_manager_xi2;
604 device_manager_xi2 = (GdkX11DeviceManagerXI2 *) device_manager;
605 display = gdk_device_manager_get_display (device_manager);
607 XIGetClientPointer (GDK_DISPLAY_XDISPLAY (display),
610 return g_hash_table_lookup (device_manager_xi2->id_table,
611 GINT_TO_POINTER (device_id));
615 gdk_x11_device_manager_xi2_set_property (GObject *object,
620 GdkX11DeviceManagerXI2 *device_manager;
622 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
627 device_manager->opcode = g_value_get_int (value);
630 device_manager->major = g_value_get_int (value);
633 device_manager->minor = g_value_get_int (value);
636 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
642 gdk_x11_device_manager_xi2_get_property (GObject *object,
647 GdkX11DeviceManagerXI2 *device_manager;
649 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
654 g_value_set_int (value, device_manager->opcode);
657 g_value_set_int (value, device_manager->major);
660 g_value_set_int (value, device_manager->minor);
663 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
669 gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
671 iface->translate_event = gdk_x11_device_manager_xi2_translate_event;
672 iface->get_handled_events = gdk_x11_device_manager_xi2_get_handled_events;
673 iface->select_window_events = gdk_x11_device_manager_xi2_select_window_events;
674 iface->get_window = gdk_x11_device_manager_xi2_get_window;
678 handle_hierarchy_changed (GdkX11DeviceManagerXI2 *device_manager,
679 XIHierarchyEvent *ev)
687 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
688 xdisplay = GDK_DISPLAY_XDISPLAY (display);
690 for (i = 0; i < ev->num_info; i++)
692 if (ev->info[i].flags & XIDeviceEnabled)
694 gdk_x11_display_error_trap_push (display);
695 info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
696 gdk_x11_display_error_trap_pop_ignored (display);
699 add_device (device_manager, &info[0], TRUE);
700 XIFreeDeviceInfo (info);
703 else if (ev->info[i].flags & XIDeviceDisabled)
704 remove_device (device_manager, ev->info[i].deviceid);
705 else if (ev->info[i].flags & XISlaveAttached ||
706 ev->info[i].flags & XISlaveDetached)
708 GdkDevice *master, *slave;
710 slave = g_hash_table_lookup (device_manager->id_table,
711 GINT_TO_POINTER (ev->info[i].deviceid));
716 /* Remove old master info */
717 master = gdk_device_get_associated_device (slave);
721 _gdk_device_remove_slave (master, slave);
722 _gdk_device_set_associated_device (slave, NULL);
724 g_signal_emit_by_name (device_manager, "device-changed", master);
727 /* Add new master if it's an attachment event */
728 if (ev->info[i].flags & XISlaveAttached)
730 gdk_x11_display_error_trap_push (display);
731 info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
732 gdk_x11_display_error_trap_pop_ignored (display);
735 master = g_hash_table_lookup (device_manager->id_table,
736 GINT_TO_POINTER (info->attachment));
737 XIFreeDeviceInfo (info);
742 _gdk_device_set_associated_device (slave, master);
743 _gdk_device_add_slave (master, slave);
745 g_signal_emit_by_name (device_manager, "device-changed", master);
749 g_signal_emit_by_name (device_manager, "device-changed", slave);
755 handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
756 XIDeviceChangedEvent *ev)
759 GdkDevice *device, *source_device;
761 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
762 device = g_hash_table_lookup (device_manager->id_table,
763 GUINT_TO_POINTER (ev->deviceid));
764 source_device = g_hash_table_lookup (device_manager->id_table,
765 GUINT_TO_POINTER (ev->sourceid));
769 _gdk_device_reset_axes (device);
770 translate_device_classes (display, device, ev->classes, ev->num_classes);
772 g_signal_emit_by_name (G_OBJECT (device), "changed");
776 _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
779 static GdkCrossingMode
780 translate_crossing_mode (gint mode)
785 return GDK_CROSSING_NORMAL;
787 return GDK_CROSSING_GRAB;
789 return GDK_CROSSING_UNGRAB;
791 g_assert_not_reached ();
796 translate_notify_type (gint detail)
801 return GDK_NOTIFY_INFERIOR;
803 return GDK_NOTIFY_ANCESTOR;
805 return GDK_NOTIFY_VIRTUAL;
806 case NotifyNonlinear:
807 return GDK_NOTIFY_NONLINEAR;
808 case NotifyNonlinearVirtual:
809 return GDK_NOTIFY_NONLINEAR_VIRTUAL;
811 g_assert_not_reached ();
816 set_screen_from_root (GdkDisplay *display,
822 screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
826 gdk_event_set_screen (event, screen);
835 set_user_time (GdkEvent *event)
840 window = gdk_window_get_toplevel (event->any.window);
841 g_return_if_fail (GDK_IS_WINDOW (window));
843 time = gdk_event_get_time (event);
845 /* If an event doesn't have a valid timestamp, we shouldn't use it
846 * to update the latest user interaction time.
848 if (time != GDK_CURRENT_TIME)
849 gdk_x11_window_set_user_time (window, time);
853 translate_axes (GdkDevice *device,
857 XIValuatorState *valuators)
863 g_object_get (device, "n-axes", &n_axes, NULL);
865 axes = g_new0 (gdouble, n_axes);
866 vals = valuators->values;
868 for (i = 0; i < valuators->mask_len * 8; i++)
873 if (!XIMaskIsSet (valuators->mask, i))
876 use = gdk_device_get_axis_use (device, i);
883 if (gdk_device_get_mode (device) == GDK_MODE_WINDOW)
884 _gdk_device_translate_window_coord (device, window, i, val, &axes[i]);
887 if (use == GDK_AXIS_X)
894 _gdk_device_translate_axis (device, i, val, &axes[i]);
903 is_parent_of (GdkWindow *parent,
914 w = gdk_window_get_parent (w);
921 get_event_window (GdkEventTranslator *translator,
923 GdkWindow **window_p)
926 GdkWindow *window = NULL;
927 gboolean should_have_window = TRUE;
929 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (translator));
936 case XI_ButtonRelease:
942 #endif /* XINPUT_2_2 */
944 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
946 window = gdk_x11_window_lookup_for_display (display, xev->event);
948 /* Apply keyboard grabs to non-native windows */
949 if (ev->evtype == XI_KeyPress || ev->evtype == XI_KeyRelease)
951 GdkDeviceGrabInfo *info;
955 device = g_hash_table_lookup (GDK_X11_DEVICE_MANAGER_XI2 (translator)->id_table,
956 GUINT_TO_POINTER (((XIDeviceEvent *) ev)->deviceid));
958 serial = _gdk_display_get_next_serial (display);
959 info = _gdk_display_has_device_grab (display, device, serial);
962 (!is_parent_of (info->window, window) ||
963 !info->owner_events))
965 /* Report key event against grab window */
966 window = info->window;
976 XIEnterEvent *xev = (XIEnterEvent *) ev;
978 window = gdk_x11_window_lookup_for_display (display, xev->event);
982 should_have_window = FALSE;
988 if (should_have_window && !window)
995 gdk_x11_device_manager_xi2_translate_core_event (GdkEventTranslator *translator,
1000 GdkEventTranslatorIface *parent_iface;
1001 gboolean keyboard = FALSE;
1004 if ((xevent->type == KeyPress || xevent->type == KeyRelease) &&
1005 (xevent->xkey.keycode == 0 || xevent->xkey.serial == 0))
1007 /* The X input methods (when triggered via XFilterEvent)
1008 * generate a core key press event with keycode 0 to signal the
1009 * end of a key sequence. We use the core translate_event
1010 * implementation to translate this event.
1012 * Other less educated IM modules like to filter every keypress,
1013 * only to have these replaced by their own homegrown events,
1014 * these events oddly have serial=0, so we try to catch these.
1016 * This is just a bandaid fix to keep xim working with a single
1017 * keyboard until XFilterEvent learns about XI2.
1021 else if (xevent->xany.send_event)
1023 /* If another process sends us core events, process them; we
1024 * assume that it won't send us redundant core and XI2 events.
1025 * (At the moment, it's not possible to send XI2 events anyway.
1026 * In the future, an app that was trying to decide whether to
1027 * send core or XI2 events could look at the event mask on the
1028 * window to see which kind we are listening to.)
1030 switch (xevent->type)
1053 parent_iface = g_type_interface_peek_parent (GDK_EVENT_TRANSLATOR_GET_IFACE (translator));
1054 if (!parent_iface->translate_event (translator, display, event, xevent))
1057 /* The core device manager sets a core device on the event.
1058 * We need to override that with an XI2 device, since we are
1061 device = gdk_x11_device_manager_xi2_get_client_pointer ((GdkDeviceManager *)translator);
1063 device = gdk_device_get_associated_device (device);
1064 gdk_event_set_device (event, device);
1070 scroll_valuators_changed (GdkX11DeviceXI2 *device,
1071 XIValuatorState *valuators,
1075 gboolean has_scroll_valuators = FALSE;
1076 GdkScrollDirection direction;
1077 guint n_axes, i, n_val;
1080 n_axes = gdk_device_get_n_axes (GDK_DEVICE (device));
1081 vals = valuators->values;
1085 for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
1089 if (!XIMaskIsSet (valuators->mask, i))
1092 if (_gdk_x11_device_xi2_get_scroll_delta (device, i, vals[n_val],
1093 &direction, &delta))
1095 has_scroll_valuators = TRUE;
1097 if (direction == GDK_SCROLL_UP ||
1098 direction == GDK_SCROLL_DOWN)
1107 return has_scroll_valuators;
1111 gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
1112 GdkDisplay *display,
1116 GdkX11DeviceManagerXI2 *device_manager;
1117 XGenericEventCookie *cookie;
1118 gboolean return_val = TRUE;
1122 device_manager = (GdkX11DeviceManagerXI2 *) translator;
1123 cookie = &xevent->xcookie;
1125 if (xevent->type != GenericEvent)
1126 return gdk_x11_device_manager_xi2_translate_core_event (translator, display, event, xevent);
1127 else if (cookie->extension != device_manager->opcode)
1130 ev = (XIEvent *) cookie->data;
1135 if (!get_event_window (translator, ev, &window))
1138 if (window && GDK_WINDOW_DESTROYED (window))
1141 if (ev->evtype == XI_Motion ||
1142 ev->evtype == XI_ButtonRelease)
1144 if (_gdk_x11_moveresize_handle_event (xevent))
1150 case XI_HierarchyChanged:
1151 handle_hierarchy_changed (device_manager,
1152 (XIHierarchyEvent *) ev);
1155 case XI_DeviceChanged:
1156 handle_device_changed (device_manager,
1157 (XIDeviceChangedEvent *) ev);
1163 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1164 GdkKeymap *keymap = gdk_keymap_get_for_display (display);
1165 GdkModifierType consumed, state;
1166 GdkDevice *device, *source_device;
1168 event->key.type = xev->evtype == XI_KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
1170 event->key.window = window;
1172 event->key.time = xev->time;
1173 event->key.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1174 event->key.group = xev->group.effective;
1176 event->key.hardware_keycode = xev->detail;
1177 event->key.is_modifier = gdk_x11_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
1179 device = g_hash_table_lookup (device_manager->id_table,
1180 GUINT_TO_POINTER (xev->deviceid));
1181 gdk_event_set_device (event, device);
1183 source_device = g_hash_table_lookup (device_manager->id_table,
1184 GUINT_TO_POINTER (xev->sourceid));
1185 gdk_event_set_source_device (event, source_device);
1187 event->key.keyval = GDK_KEY_VoidSymbol;
1189 gdk_keymap_translate_keyboard_state (keymap,
1190 event->key.hardware_keycode,
1194 NULL, NULL, &consumed);
1196 state = event->key.state & ~consumed;
1197 _gdk_x11_keymap_add_virt_mods (keymap, &state);
1198 event->key.state |= state;
1200 _gdk_x11_event_translate_keyboard_string (&event->key);
1202 if (ev->evtype == XI_KeyPress)
1203 set_user_time (event);
1205 /* FIXME: emulate autorepeat on key
1206 * release? XI2 seems attached to Xkb.
1211 case XI_ButtonPress:
1212 case XI_ButtonRelease:
1214 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1215 GdkDevice *source_device;
1217 if (ev->evtype == XI_ButtonRelease &&
1218 (xev->detail >= 4 && xev->detail <= 7))
1220 else if (ev->evtype == XI_ButtonPress &&
1221 (xev->detail >= 4 && xev->detail <= 7))
1223 /* Button presses of button 4-7 are scroll events */
1224 event->scroll.type = GDK_SCROLL;
1226 if (xev->detail == 4)
1227 event->scroll.direction = GDK_SCROLL_UP;
1228 else if (xev->detail == 5)
1229 event->scroll.direction = GDK_SCROLL_DOWN;
1230 else if (xev->detail == 6)
1231 event->scroll.direction = GDK_SCROLL_LEFT;
1233 event->scroll.direction = GDK_SCROLL_RIGHT;
1235 event->scroll.window = window;
1236 event->scroll.time = xev->time;
1237 event->scroll.x = (gdouble) xev->event_x;
1238 event->scroll.y = (gdouble) xev->event_y;
1239 event->scroll.x_root = (gdouble) xev->root_x;
1240 event->scroll.y_root = (gdouble) xev->root_y;
1241 event->scroll.delta_x = 0;
1242 event->scroll.delta_y = 0;
1244 event->scroll.device = g_hash_table_lookup (device_manager->id_table,
1245 GUINT_TO_POINTER (xev->deviceid));
1247 source_device = g_hash_table_lookup (device_manager->id_table,
1248 GUINT_TO_POINTER (xev->sourceid));
1249 gdk_event_set_source_device (event, source_device);
1251 event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1254 if (xev->flags & XIPointerEmulated)
1255 _gdk_event_set_pointer_emulated (event, TRUE);
1260 event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
1262 event->button.window = window;
1263 event->button.time = xev->time;
1264 event->button.x = (gdouble) xev->event_x;
1265 event->button.y = (gdouble) xev->event_y;
1266 event->button.x_root = (gdouble) xev->root_x;
1267 event->button.y_root = (gdouble) xev->root_y;
1269 event->button.device = g_hash_table_lookup (device_manager->id_table,
1270 GUINT_TO_POINTER (xev->deviceid));
1272 source_device = g_hash_table_lookup (device_manager->id_table,
1273 GUINT_TO_POINTER (xev->sourceid));
1274 gdk_event_set_source_device (event, source_device);
1276 event->button.axes = translate_axes (event->button.device,
1279 event->button.window,
1282 if (gdk_device_get_mode (event->button.device) == GDK_MODE_WINDOW)
1284 GdkDevice *device = event->button.device;
1286 /* Update event coordinates from axes */
1287 gdk_device_get_axis (device, event->button.axes, GDK_AXIS_X, &event->button.x);
1288 gdk_device_get_axis (device, event->button.axes, GDK_AXIS_Y, &event->button.y);
1291 event->button.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1293 event->button.button = xev->detail;
1297 if (xev->flags & XIPointerEmulated)
1298 _gdk_event_set_pointer_emulated (event, TRUE);
1301 if (return_val == FALSE)
1304 if (!set_screen_from_root (display, event, xev->root))
1310 if (ev->evtype == XI_ButtonPress)
1311 set_user_time (event);
1318 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1319 GdkDevice *source_device, *device;
1320 gdouble delta_x, delta_y;
1322 source_device = g_hash_table_lookup (device_manager->id_table,
1323 GUINT_TO_POINTER (xev->sourceid));
1324 device = g_hash_table_lookup (device_manager->id_table,
1325 GUINT_TO_POINTER (xev->deviceid));
1327 /* When scrolling, X might send events twice here; once with both the
1328 * device and the source device set to the physical device, and once
1329 * with the device set to the master device.
1330 * Since we are only interested in the latter, and
1331 * scroll_valuators_changed() updates the valuator cache for the
1332 * source device, we need to explicitly ignore the first event in
1333 * order to get the correct delta for the second.
1335 if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_SLAVE &&
1336 scroll_valuators_changed (GDK_X11_DEVICE_XI2 (source_device),
1337 &xev->valuators, &delta_x, &delta_y))
1339 event->scroll.type = GDK_SCROLL;
1340 event->scroll.direction = GDK_SCROLL_SMOOTH;
1343 g_message ("smooth scroll: %s\n\tdevice: %u\n\tsource device: %u\n\twindow %ld\n\tdeltas: %f %f",
1345 (xev->flags & XIPointerEmulated) ? "emulated" : "",
1349 xev->deviceid, xev->sourceid,
1350 xev->event, delta_x, delta_y));
1353 event->scroll.window = window;
1354 event->scroll.time = xev->time;
1355 event->scroll.x = (gdouble) xev->event_x;
1356 event->scroll.y = (gdouble) xev->event_y;
1357 event->scroll.x_root = (gdouble) xev->root_x;
1358 event->scroll.y_root = (gdouble) xev->root_y;
1359 event->scroll.delta_x = delta_x;
1360 event->scroll.delta_y = delta_y;
1362 event->scroll.device = device;
1363 gdk_event_set_source_device (event, source_device);
1365 event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1369 event->motion.type = GDK_MOTION_NOTIFY;
1370 event->motion.window = window;
1371 event->motion.time = xev->time;
1372 event->motion.x = (gdouble) xev->event_x;
1373 event->motion.y = (gdouble) xev->event_y;
1374 event->motion.x_root = (gdouble) xev->root_x;
1375 event->motion.y_root = (gdouble) xev->root_y;
1377 event->motion.device = device;
1378 gdk_event_set_source_device (event, source_device);
1380 event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1383 if (xev->flags & XIPointerEmulated)
1384 _gdk_event_set_pointer_emulated (event, TRUE);
1387 /* There doesn't seem to be motion hints in XI */
1388 event->motion.is_hint = FALSE;
1390 event->motion.axes = translate_axes (event->motion.device,
1393 event->motion.window,
1396 if (gdk_device_get_mode (event->motion.device) == GDK_MODE_WINDOW)
1398 GdkDevice *device = event->motion.device;
1400 /* Update event coordinates from axes */
1401 gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_X, &event->motion.x);
1402 gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_Y, &event->motion.y);
1411 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1412 GdkDevice *source_device;
1415 g_message ("touch %s:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %d",
1416 ev->evtype == XI_TouchBegin ? "begin" : "end",
1419 xev->flags & XITouchEmulatingPointer));
1421 if (ev->evtype == XI_TouchBegin)
1422 event->touch.type = GDK_TOUCH_BEGIN;
1423 else if (ev->evtype == XI_TouchEnd)
1424 event->touch.type = GDK_TOUCH_END;
1426 event->touch.window = window;
1427 event->touch.time = xev->time;
1428 event->touch.x = (gdouble) xev->event_x;
1429 event->touch.y = (gdouble) xev->event_y;
1430 event->touch.x_root = (gdouble) xev->root_x;
1431 event->touch.y_root = (gdouble) xev->root_y;
1433 event->touch.device = g_hash_table_lookup (device_manager->id_table,
1434 GUINT_TO_POINTER (xev->deviceid));
1436 source_device = g_hash_table_lookup (device_manager->id_table,
1437 GUINT_TO_POINTER (xev->sourceid));
1438 gdk_event_set_source_device (event, source_device);
1440 event->touch.axes = translate_axes (event->touch.device,
1443 event->touch.window,
1446 if (gdk_device_get_mode (event->touch.device) == GDK_MODE_WINDOW)
1448 GdkDevice *device = event->touch.device;
1450 /* Update event coordinates from axes */
1451 gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_X, &event->touch.x);
1452 gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_Y, &event->touch.y);
1455 event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1457 if (ev->evtype == XI_TouchBegin)
1458 event->touch.state |= GDK_BUTTON1_MASK;
1460 event->touch.sequence = GUINT_TO_POINTER (xev->detail);
1462 if (xev->flags & XITouchEmulatingPointer)
1464 event->touch.emulating_pointer = TRUE;
1465 _gdk_event_set_pointer_emulated (event, TRUE);
1468 if (return_val == FALSE)
1471 if (!set_screen_from_root (display, event, xev->root))
1477 if (ev->evtype == XI_TouchBegin)
1478 set_user_time (event);
1482 case XI_TouchUpdate:
1484 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1485 GdkDevice *source_device;
1488 g_message ("touch update:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %d",
1491 xev->flags & XITouchEmulatingPointer));
1493 event->touch.window = window;
1494 event->touch.sequence = GUINT_TO_POINTER (xev->detail);
1495 event->touch.type = GDK_TOUCH_UPDATE;
1496 event->touch.time = xev->time;
1497 event->touch.x = (gdouble) xev->event_x;
1498 event->touch.y = (gdouble) xev->event_y;
1499 event->touch.x_root = (gdouble) xev->root_x;
1500 event->touch.y_root = (gdouble) xev->root_y;
1502 event->touch.device = g_hash_table_lookup (device_manager->id_table,
1503 GINT_TO_POINTER (xev->deviceid));
1505 source_device = g_hash_table_lookup (device_manager->id_table,
1506 GUINT_TO_POINTER (xev->sourceid));
1507 gdk_event_set_source_device (event, source_device);
1509 event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1511 event->touch.state |= GDK_BUTTON1_MASK;
1513 if (xev->flags & XITouchEmulatingPointer)
1515 event->touch.emulating_pointer = TRUE;
1516 _gdk_event_set_pointer_emulated (event, TRUE);
1519 event->touch.axes = translate_axes (event->touch.device,
1522 event->touch.window,
1525 if (gdk_device_get_mode (event->touch.device) == GDK_MODE_WINDOW)
1527 GdkDevice *device = event->touch.device;
1529 /* Update event coordinates from axes */
1530 gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_X, &event->touch.x);
1531 gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_Y, &event->touch.y);
1535 #endif /* XINPUT_2_2 */
1540 XIEnterEvent *xev = (XIEnterEvent *) ev;
1541 GdkDevice *device, *source_device;
1543 event->crossing.type = (ev->evtype == XI_Enter) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
1545 event->crossing.x = (gdouble) xev->event_x;
1546 event->crossing.y = (gdouble) xev->event_y;
1547 event->crossing.x_root = (gdouble) xev->root_x;
1548 event->crossing.y_root = (gdouble) xev->root_y;
1549 event->crossing.time = xev->time;
1550 event->crossing.focus = xev->focus;
1552 event->crossing.window = window;
1553 event->crossing.subwindow = gdk_x11_window_lookup_for_display (display, xev->child);
1555 device = g_hash_table_lookup (device_manager->id_table,
1556 GINT_TO_POINTER (xev->deviceid));
1557 gdk_event_set_device (event, device);
1559 source_device = g_hash_table_lookup (device_manager->id_table,
1560 GUINT_TO_POINTER (xev->sourceid));
1561 gdk_event_set_source_device (event, source_device);
1562 _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
1564 event->crossing.mode = translate_crossing_mode (xev->mode);
1565 event->crossing.detail = translate_notify_type (xev->detail);
1566 event->crossing.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1574 XIEnterEvent *xev = (XIEnterEvent *) ev;
1575 GdkDevice *device, *source_device;
1577 device = g_hash_table_lookup (device_manager->id_table,
1578 GINT_TO_POINTER (xev->deviceid));
1580 source_device = g_hash_table_lookup (device_manager->id_table,
1581 GUINT_TO_POINTER (xev->sourceid));
1583 _gdk_device_manager_core_handle_focus (window,
1587 (ev->evtype == XI_FocusIn) ? TRUE : FALSE,
1600 event->any.send_event = cookie->send_event;
1604 if (event->any.window)
1605 g_object_ref (event->any.window);
1607 if (((event->any.type == GDK_ENTER_NOTIFY) ||
1608 (event->any.type == GDK_LEAVE_NOTIFY)) &&
1609 (event->crossing.subwindow != NULL))
1610 g_object_ref (event->crossing.subwindow);
1614 /* Mark this event as having no resources to be freed */
1615 event->any.window = NULL;
1616 event->any.type = GDK_NOTHING;
1623 gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
1625 return (GDK_KEY_PRESS_MASK |
1626 GDK_KEY_RELEASE_MASK |
1627 GDK_BUTTON_PRESS_MASK |
1628 GDK_BUTTON_RELEASE_MASK |
1630 GDK_ENTER_NOTIFY_MASK |
1631 GDK_LEAVE_NOTIFY_MASK |
1632 GDK_POINTER_MOTION_MASK |
1633 GDK_POINTER_MOTION_HINT_MASK |
1634 GDK_BUTTON1_MOTION_MASK |
1635 GDK_BUTTON2_MOTION_MASK |
1636 GDK_BUTTON3_MOTION_MASK |
1637 GDK_BUTTON_MOTION_MASK |
1638 GDK_FOCUS_CHANGE_MASK |
1643 gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
1645 GdkEventMask evmask)
1647 GdkDeviceManager *device_manager;
1648 XIEventMask event_mask;
1650 device_manager = GDK_DEVICE_MANAGER (translator);
1652 event_mask.deviceid = XIAllMasterDevices;
1653 event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (GDK_X11_DEVICE_MANAGER_XI2 (device_manager),
1655 &event_mask.mask_len);
1657 _gdk_x11_device_manager_xi2_select_events (device_manager, window, &event_mask);
1658 g_free (event_mask.mask);
1662 gdk_x11_device_manager_xi2_get_window (GdkEventTranslator *translator,
1665 GdkX11DeviceManagerXI2 *device_manager;
1667 GdkWindow *window = NULL;
1669 device_manager = (GdkX11DeviceManagerXI2 *) translator;
1671 if (xevent->type != GenericEvent ||
1672 xevent->xcookie.extension != device_manager->opcode)
1675 ev = (XIEvent *) xevent->xcookie.data;
1677 get_event_window (translator, ev, &window);
1682 _gdk_x11_device_manager_xi2_lookup (GdkX11DeviceManagerXI2 *device_manager_xi2,
1685 return g_hash_table_lookup (device_manager_xi2->id_table,
1686 GINT_TO_POINTER (device_id));