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);
94 static GdkWindow * gdk_x11_device_manager_xi2_get_window (GdkEventTranslator *translator,
103 gdk_x11_device_manager_xi2_class_init (GdkX11DeviceManagerXI2Class *klass)
105 GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
106 GObjectClass *object_class = G_OBJECT_CLASS (klass);
108 object_class->constructed = gdk_x11_device_manager_xi2_constructed;
109 object_class->dispose = gdk_x11_device_manager_xi2_dispose;
110 object_class->set_property = gdk_x11_device_manager_xi2_set_property;
111 object_class->get_property = gdk_x11_device_manager_xi2_get_property;
113 device_manager_class->list_devices = gdk_x11_device_manager_xi2_list_devices;
114 device_manager_class->get_client_pointer = gdk_x11_device_manager_xi2_get_client_pointer;
116 g_object_class_install_property (object_class,
118 g_param_spec_int ("opcode",
120 P_("Opcode for XInput2 requests"),
122 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
126 gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
128 device_manager->id_table = g_hash_table_new_full (g_direct_hash,
131 (GDestroyNotify) g_object_unref);
135 _gdk_x11_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
137 XIEventMask *event_mask)
142 display = gdk_device_manager_get_display (device_manager);
143 xdisplay = GDK_DISPLAY_XDISPLAY (display);
145 XISelectEvents (xdisplay, xwindow, event_mask, 1);
149 translate_valuator_class (GdkDisplay *display,
151 XIValuatorClassInfo *info,
154 static gboolean initialized = FALSE;
155 static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
156 GdkAxisUse use = GDK_AXIS_IGNORE;
162 label_atoms [GDK_AXIS_X] = gdk_x11_get_xatom_by_name_for_display (display, "Abs X");
163 label_atoms [GDK_AXIS_Y] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Y");
164 label_atoms [GDK_AXIS_PRESSURE] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Pressure");
165 label_atoms [GDK_AXIS_XTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt X");
166 label_atoms [GDK_AXIS_YTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt Y");
167 label_atoms [GDK_AXIS_WHEEL] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Wheel");
171 for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
173 if (label_atoms[i] == info->label)
180 if (info->label != None)
181 label = gdk_x11_xatom_to_atom_for_display (display, info->label);
185 _gdk_device_add_axis (device,
194 translate_device_classes (GdkDisplay *display,
196 XIAnyClassInfo **classes,
199 gint i, n_valuator = 0;
201 g_object_freeze_notify (G_OBJECT (device));
203 for (i = 0; i < n_classes; i++)
205 XIAnyClassInfo *class_info = classes[i];
207 switch (class_info->type)
211 XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info;
214 _gdk_device_set_keys (device, key_info->num_keycodes);
216 for (i = 0; i < key_info->num_keycodes; i++)
217 gdk_device_set_key (device, i, key_info->keycodes[i], 0);
220 case XIValuatorClass:
221 translate_valuator_class (display, device,
222 (XIValuatorClassInfo *) class_info,
232 g_object_thaw_notify (G_OBJECT (device));
236 create_device (GdkDeviceManager *device_manager,
240 GdkInputSource input_source;
245 if (dev->use == XIMasterKeyboard || dev->use == XISlaveKeyboard)
246 input_source = GDK_SOURCE_KEYBOARD;
251 tmp_name = g_ascii_strdown (dev->name, -1);
253 if (strstr (tmp_name, "eraser"))
254 input_source = GDK_SOURCE_ERASER;
255 else if (strstr (tmp_name, "cursor"))
256 input_source = GDK_SOURCE_CURSOR;
257 else if (strstr (tmp_name, "wacom") ||
258 strstr (tmp_name, "pen"))
259 input_source = GDK_SOURCE_PEN;
261 input_source = GDK_SOURCE_MOUSE;
268 case XIMasterKeyboard:
269 case XIMasterPointer:
270 type = GDK_DEVICE_TYPE_MASTER;
271 mode = GDK_MODE_SCREEN;
273 case XISlaveKeyboard:
275 type = GDK_DEVICE_TYPE_SLAVE;
276 mode = GDK_MODE_DISABLED;
278 case XIFloatingSlave:
280 type = GDK_DEVICE_TYPE_FLOATING;
281 mode = GDK_MODE_DISABLED;
285 device = g_object_new (GDK_TYPE_X11_DEVICE_XI2,
288 "input-source", input_source,
290 "has-cursor", (dev->use == XIMasterPointer),
292 "device-manager", device_manager,
293 "device-id", dev->deviceid,
296 translate_device_classes (display, device, dev->classes, dev->num_classes);
302 add_device (GdkX11DeviceManagerXI2 *device_manager,
304 gboolean emit_signal)
309 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
310 device = create_device (GDK_DEVICE_MANAGER (device_manager), display, dev);
312 g_hash_table_replace (device_manager->id_table,
313 GINT_TO_POINTER (dev->deviceid),
314 g_object_ref (device));
316 device_manager->devices = g_list_append (device_manager->devices, device);
320 if (dev->use == XISlavePointer || dev->use == XISlaveKeyboard)
324 /* The device manager is already constructed, then
325 * keep the hierarchy coherent for the added device.
327 master = g_hash_table_lookup (device_manager->id_table,
328 GINT_TO_POINTER (dev->attachment));
330 _gdk_device_set_associated_device (device, master);
331 _gdk_device_add_slave (master, device);
334 g_signal_emit_by_name (device_manager, "device-added", device);
341 remove_device (GdkX11DeviceManagerXI2 *device_manager,
346 device = g_hash_table_lookup (device_manager->id_table,
347 GINT_TO_POINTER (device_id));
351 device_manager->devices = g_list_remove (device_manager->devices, device);
353 g_signal_emit_by_name (device_manager, "device-removed", device);
355 g_object_run_dispose (G_OBJECT (device));
357 g_hash_table_remove (device_manager->id_table,
358 GINT_TO_POINTER (device_id));
363 relate_masters (gpointer key,
367 GdkX11DeviceManagerXI2 *device_manager;
368 GdkDevice *device, *relative;
370 device_manager = user_data;
371 device = g_hash_table_lookup (device_manager->id_table, key);
372 relative = g_hash_table_lookup (device_manager->id_table, value);
374 _gdk_device_set_associated_device (device, relative);
375 _gdk_device_set_associated_device (relative, device);
379 relate_slaves (gpointer key,
383 GdkX11DeviceManagerXI2 *device_manager;
384 GdkDevice *slave, *master;
386 device_manager = user_data;
387 slave = g_hash_table_lookup (device_manager->id_table, key);
388 master = g_hash_table_lookup (device_manager->id_table, value);
390 _gdk_device_set_associated_device (slave, master);
391 _gdk_device_add_slave (master, slave);
395 gdk_x11_device_manager_xi2_constructed (GObject *object)
397 GdkX11DeviceManagerXI2 *device_manager;
400 GHashTable *masters, *slaves;
402 XIDeviceInfo *info, *dev;
404 XIEventMask event_mask;
405 unsigned char mask[2] = { 0 };
407 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
408 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
409 xdisplay = GDK_DISPLAY_XDISPLAY (display);
411 masters = g_hash_table_new (NULL, NULL);
412 slaves = g_hash_table_new (NULL, NULL);
414 info = XIQueryDevice (xdisplay, XIAllDevices, &ndevices);
416 /* Initialize devices list */
417 for (i = 0; i < ndevices; i++)
420 add_device (device_manager, dev, FALSE);
422 if (dev->use == XIMasterPointer ||
423 dev->use == XIMasterKeyboard)
425 g_hash_table_insert (masters,
426 GINT_TO_POINTER (dev->deviceid),
427 GINT_TO_POINTER (dev->attachment));
429 else if (dev->use == XISlavePointer ||
430 dev->use == XISlaveKeyboard)
432 g_hash_table_insert (slaves,
433 GINT_TO_POINTER (dev->deviceid),
434 GINT_TO_POINTER (dev->attachment));
438 XIFreeDeviceInfo (info);
440 /* Stablish relationships between devices */
441 g_hash_table_foreach (masters, relate_masters, object);
442 g_hash_table_destroy (masters);
444 g_hash_table_foreach (slaves, relate_slaves, object);
445 g_hash_table_destroy (slaves);
447 /* Connect to hierarchy change events */
448 screen = gdk_display_get_default_screen (display);
449 XISetMask (mask, XI_HierarchyChanged);
450 XISetMask (mask, XI_DeviceChanged);
452 event_mask.deviceid = XIAllDevices;
453 event_mask.mask_len = sizeof (mask);
454 event_mask.mask = mask;
456 _gdk_x11_device_manager_xi2_select_events (GDK_DEVICE_MANAGER (object),
457 GDK_WINDOW_XID (gdk_screen_get_root_window (screen)),
462 gdk_x11_device_manager_xi2_dispose (GObject *object)
464 GdkX11DeviceManagerXI2 *device_manager;
466 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
468 g_list_free_full (device_manager->devices, g_object_unref);
469 device_manager->devices = NULL;
471 if (device_manager->id_table)
473 g_hash_table_destroy (device_manager->id_table);
474 device_manager->id_table = NULL;
477 G_OBJECT_CLASS (gdk_x11_device_manager_xi2_parent_class)->dispose (object);
481 gdk_x11_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
484 GdkX11DeviceManagerXI2 *device_manager_xi2;
485 GList *cur, *list = NULL;
487 device_manager_xi2 = GDK_X11_DEVICE_MANAGER_XI2 (device_manager);
489 for (cur = device_manager_xi2->devices; cur; cur = cur->next)
491 GdkDevice *dev = cur->data;
493 if (type == gdk_device_get_device_type (dev))
494 list = g_list_prepend (list, dev);
501 gdk_x11_device_manager_xi2_get_client_pointer (GdkDeviceManager *device_manager)
503 GdkX11DeviceManagerXI2 *device_manager_xi2;
507 device_manager_xi2 = (GdkX11DeviceManagerXI2 *) device_manager;
508 display = gdk_device_manager_get_display (device_manager);
510 XIGetClientPointer (GDK_DISPLAY_XDISPLAY (display),
513 return g_hash_table_lookup (device_manager_xi2->id_table,
514 GINT_TO_POINTER (device_id));
518 gdk_x11_device_manager_xi2_set_property (GObject *object,
523 GdkX11DeviceManagerXI2 *device_manager;
525 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
530 device_manager->opcode = g_value_get_int (value);
533 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
539 gdk_x11_device_manager_xi2_get_property (GObject *object,
544 GdkX11DeviceManagerXI2 *device_manager;
546 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
551 g_value_set_int (value, device_manager->opcode);
554 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
560 gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
562 iface->translate_event = gdk_x11_device_manager_xi2_translate_event;
563 iface->get_handled_events = gdk_x11_device_manager_xi2_get_handled_events;
564 iface->select_window_events = gdk_x11_device_manager_xi2_select_window_events;
565 iface->get_window = gdk_x11_device_manager_xi2_get_window;
569 handle_hierarchy_changed (GdkX11DeviceManagerXI2 *device_manager,
570 XIHierarchyEvent *ev)
578 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
579 xdisplay = GDK_DISPLAY_XDISPLAY (display);
581 for (i = 0; i < ev->num_info; i++)
583 if (ev->info[i].flags & XIDeviceEnabled)
585 info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
586 add_device (device_manager, &info[0], TRUE);
587 XIFreeDeviceInfo (info);
589 else if (ev->info[i].flags & XIDeviceDisabled)
590 remove_device (device_manager, ev->info[i].deviceid);
591 else if (ev->info[i].flags & XISlaveAttached ||
592 ev->info[i].flags & XISlaveDetached)
594 GdkDevice *master, *slave;
596 slave = g_hash_table_lookup (device_manager->id_table,
597 GINT_TO_POINTER (ev->info[i].deviceid));
599 /* Remove old master info */
600 master = gdk_device_get_associated_device (slave);
604 _gdk_device_remove_slave (master, slave);
605 _gdk_device_set_associated_device (slave, NULL);
607 g_signal_emit_by_name (device_manager, "device-changed", master);
610 /* Add new master if it's an attachment event */
611 if (ev->info[i].flags & XISlaveAttached)
613 info = XIQueryDevice (xdisplay, ev->info[i].deviceid, &ndevices);
615 master = g_hash_table_lookup (device_manager->id_table,
616 GINT_TO_POINTER (info->attachment));
618 _gdk_device_set_associated_device (slave, master);
619 _gdk_device_add_slave (master, slave);
621 g_signal_emit_by_name (device_manager, "device-changed", master);
624 g_signal_emit_by_name (device_manager, "device-changed", slave);
630 handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
631 XIDeviceChangedEvent *ev)
636 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
637 device = g_hash_table_lookup (device_manager->id_table,
638 GUINT_TO_POINTER (ev->deviceid));
640 _gdk_device_reset_axes (device);
641 translate_device_classes (display, device, ev->classes, ev->num_classes);
643 g_signal_emit_by_name (G_OBJECT (device), "changed");
646 static GdkCrossingMode
647 translate_crossing_mode (gint mode)
652 return GDK_CROSSING_NORMAL;
654 return GDK_CROSSING_GRAB;
656 return GDK_CROSSING_UNGRAB;
658 g_assert_not_reached ();
663 translate_notify_type (gint detail)
668 return GDK_NOTIFY_INFERIOR;
670 return GDK_NOTIFY_ANCESTOR;
672 return GDK_NOTIFY_VIRTUAL;
673 case NotifyNonlinear:
674 return GDK_NOTIFY_NONLINEAR;
675 case NotifyNonlinearVirtual:
676 return GDK_NOTIFY_NONLINEAR_VIRTUAL;
678 g_assert_not_reached ();
683 set_screen_from_root (GdkDisplay *display,
689 screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
693 gdk_event_set_screen (event, screen);
702 set_user_time (GdkEvent *event)
707 window = gdk_window_get_toplevel (event->any.window);
708 g_return_if_fail (GDK_IS_WINDOW (window));
710 time = gdk_event_get_time (event);
712 /* If an event doesn't have a valid timestamp, we shouldn't use it
713 * to update the latest user interaction time.
715 if (time != GDK_CURRENT_TIME)
716 gdk_x11_window_set_user_time (window, time);
720 generate_focus_event (GdkWindow *window,
722 GdkDevice *source_device,
727 event = gdk_event_new (GDK_FOCUS_CHANGE);
728 event->focus_change.window = g_object_ref (window);
729 event->focus_change.send_event = FALSE;
730 event->focus_change.in = in;
731 gdk_event_set_device (event, device);
732 gdk_event_set_source_device (event, source_device);
734 gdk_event_put (event);
735 gdk_event_free (event);
739 handle_focus_change (GdkWindow *window,
741 GdkDevice *source_device,
746 GdkToplevelX11 *toplevel;
749 toplevel = _gdk_x11_window_get_toplevel (window);
754 had_focus = HAS_FOCUS (toplevel);
760 /* When the focus moves from an ancestor of the window to
761 * the window or a descendent of the window, *and* the
762 * pointer is inside the window, then we were previously
763 * receiving keystroke events in the has_pointer_focus
764 * case and are now receiving them in the
765 * has_focus_window case.
767 if (toplevel->has_pointer &&
768 mode != NotifyGrab &&
769 mode != NotifyUngrab)
770 toplevel->has_pointer_focus = (in) ? FALSE : TRUE;
773 case NotifyNonlinear:
774 case NotifyNonlinearVirtual:
775 if (mode != NotifyGrab &&
776 mode != NotifyUngrab)
777 toplevel->has_focus_window = (in) ? TRUE : FALSE;
778 /* We pretend that the focus moves to the grab
779 * window, so we pay attention to NotifyGrab
780 * NotifyUngrab, and ignore NotifyWhileGrabbed
782 if (mode != NotifyWhileGrabbed)
783 toplevel->has_focus = (in) ? TRUE : FALSE;
786 /* The X server sends NotifyPointer/NotifyGrab,
787 * but the pointer focus is ignored while a
790 if (mode != NotifyGrab &&
791 mode != NotifyUngrab)
792 toplevel->has_pointer_focus = (in) ? TRUE :FALSE;
795 case NotifyPointerRoot:
796 case NotifyDetailNone:
800 if (HAS_FOCUS (toplevel) != had_focus)
801 generate_focus_event (window, device, source_device, (in) ? TRUE : FALSE);
805 translate_axes (GdkDevice *device,
809 XIValuatorState *valuators)
815 g_object_get (device, "n-axes", &n_axes, NULL);
817 axes = g_new0 (gdouble, n_axes);
818 vals = valuators->values;
820 for (i = 0; i < valuators->mask_len * 8; i++)
825 if (!XIMaskIsSet (valuators->mask, i))
828 use = gdk_device_get_axis_use (device, i);
835 if (gdk_device_get_mode (device) == GDK_MODE_WINDOW)
836 _gdk_device_translate_window_coord (device, window, i, val, &axes[i]);
839 if (use == GDK_AXIS_X)
846 _gdk_device_translate_axis (device, i, val, &axes[i]);
855 is_parent_of (GdkWindow *parent,
866 w = gdk_window_get_parent (w);
873 get_event_window (GdkEventTranslator *translator,
877 GdkWindow *window = NULL;
879 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (translator));
886 case XI_ButtonRelease:
889 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
891 window = gdk_x11_window_lookup_for_display (display, xev->event);
893 /* Apply keyboard grabs to non-native windows */
894 if (ev->evtype == XI_KeyPress || ev->evtype == XI_KeyRelease)
896 GdkDeviceGrabInfo *info;
900 device = g_hash_table_lookup (GDK_X11_DEVICE_MANAGER_XI2 (translator)->id_table,
901 GUINT_TO_POINTER (((XIDeviceEvent *) ev)->deviceid));
903 serial = _gdk_display_get_next_serial (display);
904 info = _gdk_display_has_device_grab (display, device, serial);
907 (!is_parent_of (info->window, window) ||
908 !info->owner_events))
910 /* Report key event against grab window */
911 window = info->window;
921 XIEnterEvent *xev = (XIEnterEvent *) ev;
923 window = gdk_x11_window_lookup_for_display (display, xev->event);
932 gdk_x11_device_manager_xi2_translate_core_event (GdkEventTranslator *translator,
937 GdkEventTranslatorIface *parent_iface;
938 gboolean keyboard = FALSE;
941 if ((xevent->type == KeyPress || xevent->type == KeyRelease) &&
942 (xevent->xkey.keycode == 0 || xevent->xkey.serial == 0))
944 /* The X input methods (when triggered via XFilterEvent)
945 * generate a core key press event with keycode 0 to signal the
946 * end of a key sequence. We use the core translate_event
947 * implementation to translate this event.
949 * Other less educated IM modules like to filter every keypress,
950 * only to have these replaced by their own homegrown events,
951 * these events oddly have serial=0, so we try to catch these.
953 * This is just a bandaid fix to keep xim working with a single
954 * keyboard until XFilterEvent learns about XI2.
958 else if (xevent->xany.send_event)
960 /* If another process sends us core events, process them; we
961 * assume that it won't send us redundant core and XI2 events.
962 * (At the moment, it's not possible to send XI2 events anyway.
963 * In the future, an app that was trying to decide whether to
964 * send core or XI2 events could look at the event mask on the
965 * window to see which kind we are listening to.)
967 switch (xevent->type)
990 parent_iface = g_type_interface_peek_parent (GDK_EVENT_TRANSLATOR_GET_IFACE (translator));
991 if (!parent_iface->translate_event (translator, display, event, xevent))
994 /* The core device manager sets a core device on the event.
995 * We need to override that with an XI2 device, since we are
998 device = gdk_x11_device_manager_xi2_get_client_pointer ((GdkDeviceManager *)translator);
1000 device = gdk_device_get_associated_device (device);
1001 gdk_event_set_device (event, device);
1007 gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
1008 GdkDisplay *display,
1012 GdkX11DeviceManagerXI2 *device_manager;
1013 XGenericEventCookie *cookie;
1014 gboolean return_val = TRUE;
1018 device_manager = (GdkX11DeviceManagerXI2 *) translator;
1019 cookie = &xevent->xcookie;
1021 if (xevent->type != GenericEvent)
1022 return gdk_x11_device_manager_xi2_translate_core_event (translator, display, event, xevent);
1023 else if (cookie->extension != device_manager->opcode)
1026 ev = (XIEvent *) cookie->data;
1028 window = get_event_window (translator, ev);
1030 if (window && GDK_WINDOW_DESTROYED (window))
1033 if (ev->evtype == XI_Motion ||
1034 ev->evtype == XI_ButtonRelease)
1036 if (_gdk_x11_moveresize_handle_event (xevent))
1042 case XI_HierarchyChanged:
1043 handle_hierarchy_changed (device_manager,
1044 (XIHierarchyEvent *) ev);
1047 case XI_DeviceChanged:
1048 handle_device_changed (device_manager,
1049 (XIDeviceChangedEvent *) ev);
1055 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1056 GdkKeymap *keymap = gdk_keymap_get_for_display (display);
1057 GdkModifierType consumed, state;
1058 GdkDevice *device, *source_device;
1060 event->key.type = xev->evtype == XI_KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
1062 event->key.window = window;
1064 event->key.time = xev->time;
1065 event->key.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1066 event->key.group = _gdk_x11_get_group_for_state (display, event->key.state);
1068 event->key.hardware_keycode = xev->detail;
1069 event->key.is_modifier = _gdk_x11_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
1071 device = g_hash_table_lookup (device_manager->id_table,
1072 GUINT_TO_POINTER (xev->deviceid));
1073 gdk_event_set_device (event, device);
1075 source_device = g_hash_table_lookup (device_manager->id_table,
1076 GUINT_TO_POINTER (xev->sourceid));
1077 gdk_event_set_source_device (event, source_device);
1079 event->key.keyval = GDK_KEY_VoidSymbol;
1081 gdk_keymap_translate_keyboard_state (keymap,
1082 event->key.hardware_keycode,
1086 NULL, NULL, &consumed);
1088 state = event->key.state & ~consumed;
1089 _gdk_x11_keymap_add_virt_mods (keymap, &state);
1090 event->key.state |= state;
1092 _gdk_x11_event_translate_keyboard_string (&event->key);
1094 if (ev->evtype == XI_KeyPress)
1095 set_user_time (event);
1097 /* FIXME: emulate autorepeat on key
1098 * release? XI2 seems attached to Xkb.
1103 case XI_ButtonPress:
1104 case XI_ButtonRelease:
1106 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1107 GdkDevice *source_device;
1109 switch (xev->detail)
1115 /* Button presses of button 4-7 are scroll events */
1116 if (ev->evtype == XI_ButtonPress)
1118 event->scroll.type = GDK_SCROLL;
1120 if (xev->detail == 4)
1121 event->scroll.direction = GDK_SCROLL_UP;
1122 else if (xev->detail == 5)
1123 event->scroll.direction = GDK_SCROLL_DOWN;
1124 else if (xev->detail == 6)
1125 event->scroll.direction = GDK_SCROLL_LEFT;
1127 event->scroll.direction = GDK_SCROLL_RIGHT;
1129 event->scroll.window = window;
1130 event->scroll.time = xev->time;
1131 event->scroll.x = (gdouble) xev->event_x;
1132 event->scroll.y = (gdouble) xev->event_y;
1133 event->scroll.x_root = (gdouble) xev->root_x;
1134 event->scroll.y_root = (gdouble) xev->root_y;
1136 event->scroll.device = g_hash_table_lookup (device_manager->id_table,
1137 GUINT_TO_POINTER (xev->deviceid));
1139 source_device = g_hash_table_lookup (device_manager->id_table,
1140 GUINT_TO_POINTER (xev->sourceid));
1141 gdk_event_set_source_device (event, source_device);
1143 event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1146 /* Button presses of button 4-7 are scroll events, so ignore the release */
1147 else if (ev->evtype == XI_ButtonRelease)
1152 /* else (XI_ButtonRelease) fall thru */
1154 event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
1156 event->button.window = window;
1157 event->button.time = xev->time;
1158 event->button.x = (gdouble) xev->event_x;
1159 event->button.y = (gdouble) xev->event_y;
1160 event->button.x_root = (gdouble) xev->root_x;
1161 event->button.y_root = (gdouble) xev->root_y;
1163 event->button.device = g_hash_table_lookup (device_manager->id_table,
1164 GUINT_TO_POINTER (xev->deviceid));
1166 source_device = g_hash_table_lookup (device_manager->id_table,
1167 GUINT_TO_POINTER (xev->sourceid));
1168 gdk_event_set_source_device (event, source_device);
1170 event->button.axes = translate_axes (event->button.device,
1173 event->button.window,
1176 if (gdk_device_get_mode (event->button.device) == GDK_MODE_WINDOW)
1178 GdkDevice *device = event->button.device;
1180 /* Update event coordinates from axes */
1181 gdk_device_get_axis (device, event->button.axes, GDK_AXIS_X, &event->button.x);
1182 gdk_device_get_axis (device, event->button.axes, GDK_AXIS_Y, &event->button.y);
1185 event->button.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1186 event->button.button = xev->detail;
1189 if (return_val == FALSE)
1192 if (!set_screen_from_root (display, event, xev->root))
1198 if (ev->evtype == XI_ButtonPress)
1199 set_user_time (event);
1205 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1206 GdkDevice *source_device;
1208 event->motion.type = GDK_MOTION_NOTIFY;
1210 event->motion.window = window;
1212 event->motion.time = xev->time;
1213 event->motion.x = (gdouble) xev->event_x;
1214 event->motion.y = (gdouble) xev->event_y;
1215 event->motion.x_root = (gdouble) xev->root_x;
1216 event->motion.y_root = (gdouble) xev->root_y;
1218 event->motion.device = g_hash_table_lookup (device_manager->id_table,
1219 GINT_TO_POINTER (xev->deviceid));
1221 source_device = g_hash_table_lookup (device_manager->id_table,
1222 GUINT_TO_POINTER (xev->sourceid));
1223 gdk_event_set_source_device (event, source_device);
1225 event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1227 /* There doesn't seem to be motion hints in XI */
1228 event->motion.is_hint = FALSE;
1230 event->motion.axes = translate_axes (event->motion.device,
1233 event->motion.window,
1236 if (gdk_device_get_mode (event->motion.device) == GDK_MODE_WINDOW)
1238 GdkDevice *device = event->motion.device;
1240 /* Update event coordinates from axes */
1241 gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_X, &event->motion.x);
1242 gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_Y, &event->motion.y);
1249 XIEnterEvent *xev = (XIEnterEvent *) ev;
1250 GdkDevice *device, *source_device;
1252 event->crossing.type = (ev->evtype == XI_Enter) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
1254 event->crossing.x = (gdouble) xev->event_x;
1255 event->crossing.y = (gdouble) xev->event_y;
1256 event->crossing.x_root = (gdouble) xev->root_x;
1257 event->crossing.y_root = (gdouble) xev->root_y;
1258 event->crossing.time = xev->time;
1259 event->crossing.focus = xev->focus;
1261 event->crossing.window = window;
1262 event->crossing.subwindow = gdk_x11_window_lookup_for_display (display, xev->child);
1264 device = g_hash_table_lookup (device_manager->id_table,
1265 GINT_TO_POINTER (xev->deviceid));
1266 gdk_event_set_device (event, device);
1268 source_device = g_hash_table_lookup (device_manager->id_table,
1269 GUINT_TO_POINTER (xev->sourceid));
1270 gdk_event_set_source_device (event, source_device);
1272 event->crossing.mode = translate_crossing_mode (xev->mode);
1273 event->crossing.detail = translate_notify_type (xev->detail);
1274 event->crossing.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1280 XIEnterEvent *xev = (XIEnterEvent *) ev;
1281 GdkDevice *device, *source_device;
1283 device = g_hash_table_lookup (device_manager->id_table,
1284 GINT_TO_POINTER (xev->deviceid));
1286 source_device = g_hash_table_lookup (device_manager->id_table,
1287 GUINT_TO_POINTER (xev->sourceid));
1289 handle_focus_change (window, device, source_device,
1290 xev->detail, xev->mode,
1291 (ev->evtype == XI_FocusIn) ? TRUE : FALSE);
1300 event->any.send_event = cookie->send_event;
1304 if (event->any.window)
1305 g_object_ref (event->any.window);
1307 if (((event->any.type == GDK_ENTER_NOTIFY) ||
1308 (event->any.type == GDK_LEAVE_NOTIFY)) &&
1309 (event->crossing.subwindow != NULL))
1310 g_object_ref (event->crossing.subwindow);
1314 /* Mark this event as having no resources to be freed */
1315 event->any.window = NULL;
1316 event->any.type = GDK_NOTHING;
1323 gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
1325 return (GDK_KEY_PRESS_MASK |
1326 GDK_KEY_RELEASE_MASK |
1327 GDK_BUTTON_PRESS_MASK |
1328 GDK_BUTTON_RELEASE_MASK |
1330 GDK_ENTER_NOTIFY_MASK |
1331 GDK_LEAVE_NOTIFY_MASK |
1332 GDK_POINTER_MOTION_MASK |
1333 GDK_POINTER_MOTION_HINT_MASK |
1334 GDK_BUTTON1_MOTION_MASK |
1335 GDK_BUTTON2_MOTION_MASK |
1336 GDK_BUTTON3_MOTION_MASK |
1337 GDK_BUTTON_MOTION_MASK |
1338 GDK_FOCUS_CHANGE_MASK);
1342 gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
1344 GdkEventMask evmask)
1346 GdkDeviceManager *device_manager;
1347 XIEventMask event_mask;
1349 device_manager = GDK_DEVICE_MANAGER (translator);
1351 event_mask.deviceid = XIAllMasterDevices;
1352 event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (evmask, &event_mask.mask_len);
1354 _gdk_x11_device_manager_xi2_select_events (device_manager, window, &event_mask);
1355 g_free (event_mask.mask);
1359 gdk_x11_device_manager_xi2_get_window (GdkEventTranslator *translator,
1362 GdkX11DeviceManagerXI2 *device_manager;
1365 device_manager = (GdkX11DeviceManagerXI2 *) translator;
1367 if (xevent->type != GenericEvent ||
1368 xevent->xcookie.extension != device_manager->opcode)
1371 ev = (XIEvent *) xevent->xcookie.data;
1373 return get_event_window (translator, ev);
1376 #else /* XINPUT_2 */
1379 gdk_x11_device_manager_xi2_class_init (GdkX11DeviceManagerXI2Class *klass)
1384 gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
1389 gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
1393 #endif /* XINPUT_2 */