1/* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include "gdkx11devicemanager-xi2.h"
21
22#include "gdkdevice-xi2-private.h"
23#include "gdkdeviceprivate.h"
24#include "gdkdevicetoolprivate.h"
25#include "gdkdisplayprivate.h"
26#include "gdkeventsprivate.h"
27#include "gdkeventtranslator.h"
28#include "gdkkeys-x11.h"
29#include "gdkprivate-x11.h"
30#include "gdkdisplay-x11.h"
31#include "gdkintl.h"
32#include "gdkkeysyms.h"
33#include "gdkseatdefaultprivate.h"
34
35#include <X11/Xlib.h>
36#include <X11/Xutil.h>
37#include <X11/extensions/XInput2.h>
38#include <X11/Xatom.h>
39
40#include <string.h>
41
42#ifdef G_ENABLE_DEBUG
43static const char notify_modes[][19] = {
44 "NotifyNormal",
45 "NotifyGrab",
46 "NotifyUngrab",
47 "NotifyWhileGrabbed"
48};
49
50static const char notify_details[][23] = {
51 "NotifyAncestor",
52 "NotifyVirtual",
53 "NotifyInferior",
54 "NotifyNonlinear",
55 "NotifyNonlinearVirtual",
56 "NotifyPointer",
57 "NotifyPointerRoot",
58 "NotifyDetailNone"
59};
60#endif
61
62#define HAS_FOCUS(toplevel) \
63 ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
64
65static const char *wacom_type_atoms[] = {
66 "STYLUS",
67 "CURSOR",
68 "ERASER",
69 "PAD",
70 "TOUCH"
71};
72#define N_WACOM_TYPE_ATOMS G_N_ELEMENTS (wacom_type_atoms)
73
74enum {
75 WACOM_TYPE_STYLUS,
76 WACOM_TYPE_CURSOR,
77 WACOM_TYPE_ERASER,
78 WACOM_TYPE_PAD,
79 WACOM_TYPE_TOUCH,
80};
81
82struct _GdkX11DeviceManagerXI2
83{
84 GObject parent_object;
85
86 GdkDisplay *display;
87 GHashTable *id_table;
88
89 GList *devices;
90
91 int opcode;
92 int major;
93 int minor;
94};
95
96struct _GdkX11DeviceManagerXI2Class
97{
98 GObjectClass parent_class;
99};
100
101static void gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
102
103G_DEFINE_TYPE_WITH_CODE (GdkX11DeviceManagerXI2, gdk_x11_device_manager_xi2, G_TYPE_OBJECT,
104 G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
105 gdk_x11_device_manager_xi2_event_translator_init))
106
107static void gdk_x11_device_manager_xi2_constructed (GObject *object);
108static void gdk_x11_device_manager_xi2_dispose (GObject *object);
109static void gdk_x11_device_manager_xi2_set_property (GObject *object,
110 guint prop_id,
111 const GValue *value,
112 GParamSpec *pspec);
113static void gdk_x11_device_manager_xi2_get_property (GObject *object,
114 guint prop_id,
115 GValue *value,
116 GParamSpec *pspec);
117
118static GdkEvent * gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
119 GdkDisplay *display,
120 const XEvent *xevent);
121static GdkEventMask gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator);
122static void gdk_x11_device_manager_xi2_select_surface_events (GdkEventTranslator *translator,
123 Window window,
124 GdkEventMask event_mask);
125static GdkSurface * gdk_x11_device_manager_xi2_get_surface (GdkEventTranslator *translator,
126 const XEvent *xevent);
127
128enum {
129 PROP_0,
130 PROP_DISPLAY,
131 PROP_OPCODE,
132 PROP_MAJOR,
133 PROP_MINOR
134};
135
136static void
137gdk_x11_device_manager_xi2_class_init (GdkX11DeviceManagerXI2Class *klass)
138{
139 GObjectClass *object_class = G_OBJECT_CLASS (klass);
140
141 object_class->constructed = gdk_x11_device_manager_xi2_constructed;
142 object_class->dispose = gdk_x11_device_manager_xi2_dispose;
143 object_class->set_property = gdk_x11_device_manager_xi2_set_property;
144 object_class->get_property = gdk_x11_device_manager_xi2_get_property;
145
146 g_object_class_install_property (oclass: object_class,
147 property_id: PROP_DISPLAY,
148 pspec: g_param_spec_object (name: "display",
149 nick: "Display",
150 blurb: "Display for the device manager",
151 GDK_TYPE_DISPLAY,
152 flags: G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
153 G_PARAM_STATIC_STRINGS));
154 g_object_class_install_property (oclass: object_class,
155 property_id: PROP_OPCODE,
156 pspec: g_param_spec_int (name: "opcode",
157 P_("Opcode"),
158 P_("Opcode for XInput2 requests"),
159 minimum: 0, G_MAXINT, default_value: 0,
160 flags: G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
161 G_PARAM_STATIC_STRINGS));
162 g_object_class_install_property (oclass: object_class,
163 property_id: PROP_MAJOR,
164 pspec: g_param_spec_int (name: "major",
165 P_("Major"),
166 P_("Major version number"),
167 minimum: 0, G_MAXINT, default_value: 0,
168 flags: G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
169 G_PARAM_STATIC_STRINGS));
170 g_object_class_install_property (oclass: object_class,
171 property_id: PROP_MINOR,
172 pspec: g_param_spec_int (name: "minor",
173 P_("Minor"),
174 P_("Minor version number"),
175 minimum: 0, G_MAXINT, default_value: 0,
176 flags: G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
177 G_PARAM_STATIC_STRINGS));
178}
179
180static void
181gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
182{
183 device_manager->id_table = g_hash_table_new_full (hash_func: g_direct_hash,
184 key_equal_func: g_direct_equal,
185 NULL,
186 value_destroy_func: (GDestroyNotify) g_object_unref);
187}
188
189static void
190_gdk_x11_device_manager_xi2_select_events (GdkX11DeviceManagerXI2 *device_manager,
191 Window xwindow,
192 XIEventMask *event_mask)
193{
194 GdkDisplay *display;
195 Display *xdisplay;
196
197 display = device_manager->display;
198 xdisplay = GDK_DISPLAY_XDISPLAY (display);
199
200 XISelectEvents (dpy: xdisplay, win: xwindow, masks: event_mask, num_masks: 1);
201}
202
203static void
204translate_valuator_class (GdkDisplay *display,
205 GdkDevice *device,
206 Atom valuator_label,
207 double min,
208 double max,
209 double resolution)
210{
211 static gboolean initialized = FALSE;
212 static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
213 GdkAxisUse use = GDK_AXIS_IGNORE;
214 int i;
215
216 if (!initialized)
217 {
218 label_atoms [GDK_AXIS_X] = gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Abs X");
219 label_atoms [GDK_AXIS_Y] = gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Abs Y");
220 label_atoms [GDK_AXIS_PRESSURE] = gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Abs Pressure");
221 label_atoms [GDK_AXIS_XTILT] = gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Abs Tilt X");
222 label_atoms [GDK_AXIS_YTILT] = gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Abs Tilt Y");
223 label_atoms [GDK_AXIS_WHEEL] = gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Abs Wheel");
224 initialized = TRUE;
225 }
226
227 for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++)
228 {
229 if (label_atoms[i] == valuator_label)
230 {
231 use = i;
232 break;
233 }
234 }
235
236 _gdk_device_add_axis (device, use, min_value: min, max_value: max, resolution);
237 GDK_DISPLAY_NOTE (display, INPUT,
238 {
239 const char *label;
240
241 if (valuator_label != None)
242 label = gdk_x11_get_xatom_name_for_display (display, valuator_label);
243 else
244 label = NULL;
245
246 g_message ("\n\taxis: %s %s", label, use == GDK_AXIS_IGNORE ? "(ignored)" : "(used)");
247 });
248}
249
250static void
251translate_device_classes (GdkDisplay *display,
252 GdkDevice *device,
253 XIAnyClassInfo **classes,
254 guint n_classes)
255{
256 int i;
257
258 g_object_freeze_notify (G_OBJECT (device));
259
260 for (i = 0; i < n_classes; i++)
261 {
262 XIAnyClassInfo *class_info = classes[i];
263
264 switch (class_info->type)
265 {
266 case XIKeyClass:
267 {
268 /* Not used */
269 }
270 break;
271 case XIValuatorClass:
272 {
273 XIValuatorClassInfo *valuator_info = (XIValuatorClassInfo *) class_info;
274 translate_valuator_class (display, device,
275 valuator_label: valuator_info->label,
276 min: valuator_info->min,
277 max: valuator_info->max,
278 resolution: valuator_info->resolution);
279 }
280 break;
281#ifdef XINPUT_2_2
282 case XIScrollClass:
283 {
284 XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info;
285 GdkScrollDirection direction;
286
287 if (scroll_info->scroll_type == XIScrollTypeVertical)
288 direction = GDK_SCROLL_DOWN;
289 else
290 direction = GDK_SCROLL_RIGHT;
291
292 GDK_DISPLAY_NOTE (display, INPUT,
293 g_message ("\n\tscroll valuator %d: %s, increment %f",
294 scroll_info->number,
295 scroll_info->scroll_type == XIScrollTypeVertical
296 ? "vertical"
297 : "horizontal",
298 scroll_info->increment));
299
300 _gdk_x11_device_xi2_add_scroll_valuator (GDK_X11_DEVICE_XI2 (device),
301 n_valuator: scroll_info->number,
302 direction,
303 increment: scroll_info->increment);
304 }
305 break;
306#endif /* XINPUT_2_2 */
307 default:
308 /* Ignore */
309 break;
310 }
311 }
312
313 g_object_thaw_notify (G_OBJECT (device));
314}
315
316static gboolean
317is_touch_device (XIAnyClassInfo **classes,
318 guint n_classes,
319 GdkInputSource *device_type,
320 int *num_touches)
321{
322#ifdef XINPUT_2_2
323 guint i;
324
325 for (i = 0; i < n_classes; i++)
326 {
327 XITouchClassInfo *class = (XITouchClassInfo *) classes[i];
328
329 if (class->type != XITouchClass)
330 continue;
331
332 if (class->num_touches > 0)
333 {
334 if (class->mode == XIDirectTouch)
335 *device_type = GDK_SOURCE_TOUCHSCREEN;
336 else if (class->mode == XIDependentTouch)
337 *device_type = GDK_SOURCE_TOUCHPAD;
338 else
339 continue;
340
341 *num_touches = class->num_touches;
342
343 return TRUE;
344 }
345 }
346#endif
347
348 return FALSE;
349}
350
351static gboolean
352has_abs_axes (GdkDisplay *display,
353 XIAnyClassInfo **classes,
354 guint n_classes)
355{
356 gboolean has_x = FALSE, has_y = FALSE;
357 Atom abs_x, abs_y;
358 guint i;
359
360 abs_x = gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Abs X");
361 abs_y = gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Abs Y");
362
363 for (i = 0; i < n_classes; i++)
364 {
365 XIValuatorClassInfo *class = (XIValuatorClassInfo *) classes[i];
366
367 if (class->type != XIValuatorClass)
368 continue;
369 if (class->mode != XIModeAbsolute)
370 continue;
371
372 if (class->label == abs_x)
373 has_x = TRUE;
374 else if (class->label == abs_y)
375 has_y = TRUE;
376
377 if (has_x && has_y)
378 break;
379 }
380
381 return (has_x && has_y);
382}
383
384static gboolean
385get_device_ids (GdkDisplay *display,
386 XIDeviceInfo *info,
387 char **vendor_id,
388 char **product_id)
389{
390 gulong nitems, bytes_after;
391 guint32 *data;
392 int rc, format;
393 Atom prop, type;
394
395 gdk_x11_display_error_trap_push (display);
396
397 prop = XInternAtom (GDK_DISPLAY_XDISPLAY (display), "Device Product ID", True);
398
399 if (prop == None)
400 {
401 gdk_x11_display_error_trap_pop_ignored (display);
402 return 0;
403 }
404
405 rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
406 deviceid: info->deviceid, property: prop,
407 offset: 0, length: 2, False, XA_INTEGER, type_return: &type, format_return: &format, num_items_return: &nitems, bytes_after_return: &bytes_after,
408 data: (guchar **) &data);
409 gdk_x11_display_error_trap_pop_ignored (display);
410
411 if (rc != Success || type != XA_INTEGER || format != 32 || nitems != 2)
412 return FALSE;
413
414 if (vendor_id)
415 *vendor_id = g_strdup_printf (format: "%.4x", data[0]);
416 if (product_id)
417 *product_id = g_strdup_printf (format: "%.4x", data[1]);
418
419 XFree (data);
420
421 return TRUE;
422}
423
424static gboolean
425has_bool_prop (GdkDisplay *display,
426 XIDeviceInfo *info,
427 const char *prop_name)
428{
429 gulong nitems, bytes_after;
430 guint32 *data;
431 int rc, format;
432 Atom type;
433
434 gdk_x11_display_error_trap_push (display);
435
436 rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
437 deviceid: info->deviceid,
438 property: gdk_x11_get_xatom_by_name_for_display (display, atom_name: prop_name),
439 offset: 0, length: 1, False, XA_INTEGER, type_return: &type, format_return: &format, num_items_return: &nitems, bytes_after_return: &bytes_after,
440 data: (guchar **) &data);
441 gdk_x11_display_error_trap_pop_ignored (display);
442
443 if (rc != Success || type != XA_INTEGER || format != 8 || nitems != 1)
444 return FALSE;
445
446 XFree (data);
447
448 return TRUE;
449}
450
451static gboolean
452is_touchpad_device (GdkDisplay *display,
453 XIDeviceInfo *info)
454{
455 /*
456 * Touchpads are heuristically recognized via XI properties that the various
457 * Xorg drivers expose:
458 * libinput: libinput Tapping Enabled
459 * synaptics: Synaptics Off
460 * cmt: Raw Touch Passthrough
461 */
462 return has_bool_prop (display, info, prop_name: "libinput Tapping Enabled") ||
463 has_bool_prop (display, info, prop_name: "Synaptics Off") ||
464 has_bool_prop (display, info, prop_name: "Raw Touch Passthrough");
465}
466
467static GdkDevice *
468create_device (GdkX11DeviceManagerXI2 *device_manager,
469 GdkDisplay *display,
470 XIDeviceInfo *dev)
471{
472 GdkInputSource input_source;
473 GdkInputSource touch_source;
474 GdkX11DeviceType type;
475 GdkDevice *device;
476 int num_touches = 0;
477 char *vendor_id = NULL, *product_id = NULL;
478
479 if (dev->use == XIMasterKeyboard || dev->use == XISlaveKeyboard)
480 input_source = GDK_SOURCE_KEYBOARD;
481 else if (is_touchpad_device (display, info: dev))
482 input_source = GDK_SOURCE_TOUCHPAD;
483 else if (dev->use == XISlavePointer &&
484 is_touch_device (classes: dev->classes, n_classes: dev->num_classes, device_type: &touch_source, num_touches: &num_touches))
485 input_source = touch_source;
486 else
487 {
488 char *tmp_name;
489
490 tmp_name = g_ascii_strdown (str: dev->name, len: -1);
491
492 if (strstr (haystack: tmp_name, needle: " pad"))
493 input_source = GDK_SOURCE_TABLET_PAD;
494 else if (strstr (haystack: tmp_name, needle: "wacom") ||
495 strstr (haystack: tmp_name, needle: "pen") ||
496 strstr (haystack: tmp_name, needle: "eraser"))
497 input_source = GDK_SOURCE_PEN;
498 else if (!strstr (haystack: tmp_name, needle: "mouse") &&
499 !strstr (haystack: tmp_name, needle: "pointer") &&
500 !strstr (haystack: tmp_name, needle: "qemu usb tablet") &&
501 !strstr (haystack: tmp_name, needle: "spice vdagent tablet") &&
502 !strstr (haystack: tmp_name, needle: "virtualbox usb tablet") &&
503 has_abs_axes (display, classes: dev->classes, n_classes: dev->num_classes))
504 input_source = GDK_SOURCE_TOUCHSCREEN;
505 else if (strstr (haystack: tmp_name, needle: "trackpoint") ||
506 strstr (haystack: tmp_name, needle: "dualpoint stick"))
507 input_source = GDK_SOURCE_TRACKPOINT;
508 else
509 input_source = GDK_SOURCE_MOUSE;
510
511 g_free (mem: tmp_name);
512 }
513
514 switch (dev->use)
515 {
516 case XIMasterKeyboard:
517 case XIMasterPointer:
518 type = GDK_X11_DEVICE_TYPE_LOGICAL;
519 break;
520 case XISlaveKeyboard:
521 case XISlavePointer:
522 type = GDK_X11_DEVICE_TYPE_PHYSICAL;
523 break;
524 case XIFloatingSlave:
525 default:
526 type = GDK_X11_DEVICE_TYPE_FLOATING;
527 break;
528 }
529
530 GDK_DISPLAY_NOTE (display, INPUT,
531 ({
532 const char *type_names[] = { "logical", "physical", "floating" };
533 const char *source_names[] = { "mouse", "pen", "eraser", "cursor", "keyboard", "direct touch", "indirect touch", "trackpoint", "pad" };
534 g_message ("input device:\n\tname: %s\n\ttype: %s\n\tsource: %s\n\thas cursor: %d\n\ttouches: %d",
535 dev->name,
536 type_names[type],
537 source_names[input_source],
538 dev->use == XIMasterPointer,
539 num_touches);
540 }));
541
542 if (dev->use != XIMasterKeyboard &&
543 dev->use != XIMasterPointer)
544 get_device_ids (display, info: dev, vendor_id: &vendor_id, product_id: &product_id);
545
546 device = g_object_new (GDK_TYPE_X11_DEVICE_XI2,
547 first_property_name: "name", dev->name,
548 "source", input_source,
549 "has-cursor", (dev->use == XIMasterPointer),
550 "display", display,
551 "device-id", dev->deviceid,
552 "vendor-id", vendor_id,
553 "product-id", product_id,
554 "num-touches", num_touches,
555 NULL);
556 gdk_x11_device_xi2_set_device_type (device: (GdkX11DeviceXI2 *) device, type);
557
558 translate_device_classes (display, device, classes: dev->classes, n_classes: dev->num_classes);
559 g_free (mem: vendor_id);
560 g_free (mem: product_id);
561
562 return device;
563}
564
565static void
566ensure_seat_for_device_pair (GdkX11DeviceManagerXI2 *device_manager,
567 GdkDevice *device1,
568 GdkDevice *device2)
569{
570 GdkDevice *pointer, *keyboard;
571 GdkDisplay *display;
572 GdkSeat *seat;
573
574 display = device_manager->display;
575 seat = gdk_device_get_seat (device: device1);
576
577 if (!seat)
578 {
579 if (gdk_device_get_source (device: device1) == GDK_SOURCE_KEYBOARD)
580 {
581 keyboard = device1;
582 pointer = device2;
583 }
584 else
585 {
586 pointer = device1;
587 keyboard = device2;
588 }
589
590 seat = gdk_seat_default_new_for_logical_pair (pointer, keyboard);
591 gdk_display_add_seat (display, seat);
592 g_object_unref (object: seat);
593 }
594}
595
596static GdkDevice *
597add_device (GdkX11DeviceManagerXI2 *device_manager,
598 XIDeviceInfo *dev,
599 gboolean emit_signal)
600{
601 GdkDisplay *display;
602 GdkDevice *device;
603
604 display = device_manager->display;
605 device = create_device (device_manager, display, dev);
606
607 g_hash_table_replace (hash_table: device_manager->id_table,
608 GINT_TO_POINTER (dev->deviceid),
609 g_object_ref (device));
610
611 device_manager->devices = g_list_append (list: device_manager->devices, data: device);
612
613 if (emit_signal)
614 {
615 if (dev->use == XISlavePointer || dev->use == XISlaveKeyboard)
616 {
617 GdkDevice *logical;
618 GdkSeat *seat;
619
620 /* The device manager is already constructed, then
621 * keep the hierarchy coherent for the added device.
622 */
623 logical = g_hash_table_lookup (hash_table: device_manager->id_table,
624 GINT_TO_POINTER (dev->attachment));
625
626 _gdk_device_set_associated_device (device, relative: logical);
627 _gdk_device_add_physical_device (device: logical, physical: device);
628
629 seat = gdk_device_get_seat (device: logical);
630 gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), device);
631 }
632 else if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard)
633 {
634 GdkDevice *relative;
635
636 relative = g_hash_table_lookup (hash_table: device_manager->id_table,
637 GINT_TO_POINTER (dev->attachment));
638
639 if (relative)
640 {
641 _gdk_device_set_associated_device (device, relative);
642 _gdk_device_set_associated_device (device: relative, relative: device);
643 ensure_seat_for_device_pair (device_manager, device1: device, device2: relative);
644 }
645 }
646 }
647
648 return device;
649}
650
651static void
652detach_from_seat (GdkDevice *device)
653{
654 GdkSeat *seat = gdk_device_get_seat (device);
655 GdkX11DeviceXI2 *device_xi2 = (GdkX11DeviceXI2 *) device;
656
657 if (!seat)
658 return;
659
660 if (gdk_x11_device_xi2_get_device_type (device: device_xi2) == GDK_X11_DEVICE_TYPE_LOGICAL)
661 gdk_display_remove_seat (display: gdk_device_get_display (device), seat);
662 else if (gdk_x11_device_xi2_get_device_type (device: device_xi2) == GDK_X11_DEVICE_TYPE_PHYSICAL)
663 gdk_seat_default_remove_physical_device (GDK_SEAT_DEFAULT (seat), device);
664}
665
666static void
667remove_device (GdkX11DeviceManagerXI2 *device_manager,
668 int device_id)
669{
670 GdkDevice *device;
671
672 device = g_hash_table_lookup (hash_table: device_manager->id_table,
673 GINT_TO_POINTER (device_id));
674
675 if (device)
676 {
677 detach_from_seat (device);
678
679 g_hash_table_remove (hash_table: device_manager->id_table,
680 GINT_TO_POINTER (device_id));
681
682 device_manager->devices = g_list_remove (list: device_manager->devices, data: device);
683 g_object_run_dispose (G_OBJECT (device));
684 g_object_unref (object: device);
685 }
686}
687
688static void
689relate_logical_devices (gpointer key,
690 gpointer value,
691 gpointer user_data)
692{
693 GdkX11DeviceManagerXI2 *device_manager;
694 GdkDevice *device, *relative;
695
696 device_manager = user_data;
697 device = g_hash_table_lookup (hash_table: device_manager->id_table, key);
698 relative = g_hash_table_lookup (hash_table: device_manager->id_table, key: value);
699
700 _gdk_device_set_associated_device (device, relative);
701 _gdk_device_set_associated_device (device: relative, relative: device);
702 ensure_seat_for_device_pair (device_manager, device1: device, device2: relative);
703}
704
705static void
706relate_physical_devices (gpointer key,
707 gpointer value,
708 gpointer user_data)
709{
710 GdkX11DeviceManagerXI2 *device_manager;
711 GdkDevice *physical, *logical;
712 GdkSeat *seat;
713
714 device_manager = user_data;
715 physical = g_hash_table_lookup (hash_table: device_manager->id_table, key);
716 logical = g_hash_table_lookup (hash_table: device_manager->id_table, key: value);
717
718 _gdk_device_set_associated_device (device: physical, relative: logical);
719 _gdk_device_add_physical_device (device: logical, physical);
720
721 seat = gdk_device_get_seat (device: logical);
722 gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), device: physical);
723}
724
725static void
726gdk_x11_device_manager_xi2_constructed (GObject *object)
727{
728 GdkX11DeviceManagerXI2 *device_manager;
729 GdkDisplay *display;
730 GHashTable *logical_devices, *physical_devices;
731 Display *xdisplay;
732 XIDeviceInfo *info, *dev;
733 int ndevices, i;
734 XIEventMask event_mask;
735 unsigned char mask[2] = { 0 };
736
737 G_OBJECT_CLASS (gdk_x11_device_manager_xi2_parent_class)->constructed (object);
738
739 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
740 display = device_manager->display;
741 xdisplay = GDK_DISPLAY_XDISPLAY (display);
742
743 g_assert (device_manager->major == 2);
744
745 logical_devices = g_hash_table_new (NULL, NULL);
746 physical_devices = g_hash_table_new (NULL, NULL);
747
748 info = XIQueryDevice (dpy: xdisplay, XIAllDevices, ndevices_return: &ndevices);
749
750 /* Initialize devices list */
751 for (i = 0; i < ndevices; i++)
752 {
753 dev = &info[i];
754
755 if (!dev->enabled)
756 continue;
757
758 add_device (device_manager, dev, FALSE);
759
760 if (dev->use == XIMasterPointer ||
761 dev->use == XIMasterKeyboard)
762 {
763 g_hash_table_insert (hash_table: logical_devices,
764 GINT_TO_POINTER (dev->deviceid),
765 GINT_TO_POINTER (dev->attachment));
766 }
767 else if (dev->use == XISlavePointer ||
768 dev->use == XISlaveKeyboard)
769 {
770 g_hash_table_insert (hash_table: physical_devices,
771 GINT_TO_POINTER (dev->deviceid),
772 GINT_TO_POINTER (dev->attachment));
773 }
774 }
775
776 XIFreeDeviceInfo (info);
777
778 /* Stablish relationships between devices */
779 g_hash_table_foreach (hash_table: logical_devices, func: relate_logical_devices, user_data: object);
780 g_hash_table_destroy (hash_table: logical_devices);
781
782 g_hash_table_foreach (hash_table: physical_devices, func: relate_physical_devices, user_data: object);
783 g_hash_table_destroy (hash_table: physical_devices);
784
785 /* Connect to hierarchy change events */
786 XISetMask (mask, XI_HierarchyChanged);
787 XISetMask (mask, XI_DeviceChanged);
788 XISetMask (mask, XI_PropertyEvent);
789
790 event_mask.deviceid = XIAllDevices;
791 event_mask.mask_len = sizeof (mask);
792 event_mask.mask = mask;
793
794 _gdk_x11_device_manager_xi2_select_events (device_manager,
795 GDK_DISPLAY_XROOTWIN (display),
796 event_mask: &event_mask);
797}
798
799static void
800gdk_x11_device_manager_xi2_dispose (GObject *object)
801{
802 GdkX11DeviceManagerXI2 *device_manager;
803
804 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
805
806 g_list_free_full (list: device_manager->devices, free_func: g_object_unref);
807 device_manager->devices = NULL;
808
809 if (device_manager->id_table)
810 {
811 g_hash_table_destroy (hash_table: device_manager->id_table);
812 device_manager->id_table = NULL;
813 }
814
815 G_OBJECT_CLASS (gdk_x11_device_manager_xi2_parent_class)->dispose (object);
816}
817
818static void
819gdk_x11_device_manager_xi2_set_property (GObject *object,
820 guint prop_id,
821 const GValue *value,
822 GParamSpec *pspec)
823{
824 GdkX11DeviceManagerXI2 *device_manager;
825
826 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
827
828 switch (prop_id)
829 {
830 case PROP_DISPLAY:
831 device_manager->display = g_value_get_object (value);
832 break;
833 case PROP_OPCODE:
834 device_manager->opcode = g_value_get_int (value);
835 break;
836 case PROP_MAJOR:
837 device_manager->major = g_value_get_int (value);
838 break;
839 case PROP_MINOR:
840 device_manager->minor = g_value_get_int (value);
841 break;
842 default:
843 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
844 break;
845 }
846}
847
848static void
849gdk_x11_device_manager_xi2_get_property (GObject *object,
850 guint prop_id,
851 GValue *value,
852 GParamSpec *pspec)
853{
854 GdkX11DeviceManagerXI2 *device_manager;
855
856 device_manager = GDK_X11_DEVICE_MANAGER_XI2 (object);
857
858 switch (prop_id)
859 {
860 case PROP_DISPLAY:
861 g_value_set_object (value, v_object: device_manager->display);
862 break;
863 case PROP_OPCODE:
864 g_value_set_int (value, v_int: device_manager->opcode);
865 break;
866 case PROP_MAJOR:
867 g_value_set_int (value, v_int: device_manager->major);
868 break;
869 case PROP_MINOR:
870 g_value_set_int (value, v_int: device_manager->minor);
871 break;
872 default:
873 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
874 break;
875 }
876}
877
878static void
879gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
880{
881 iface->translate_event = gdk_x11_device_manager_xi2_translate_event;
882 iface->get_handled_events = gdk_x11_device_manager_xi2_get_handled_events;
883 iface->select_surface_events = gdk_x11_device_manager_xi2_select_surface_events;
884 iface->get_surface = gdk_x11_device_manager_xi2_get_surface;
885}
886
887static void
888handle_hierarchy_changed (GdkX11DeviceManagerXI2 *device_manager,
889 XIHierarchyEvent *ev)
890{
891 GdkDisplay *display;
892 Display *xdisplay;
893 XIDeviceInfo *info;
894 int ndevices;
895 int i;
896
897 display = device_manager->display;
898 xdisplay = GDK_DISPLAY_XDISPLAY (display);
899
900 for (i = 0; i < ev->num_info; i++)
901 {
902 if (ev->info[i].flags & XIDeviceEnabled)
903 {
904 gdk_x11_display_error_trap_push (display);
905 info = XIQueryDevice (dpy: xdisplay, deviceid: ev->info[i].deviceid, ndevices_return: &ndevices);
906 gdk_x11_display_error_trap_pop_ignored (display);
907 if (info)
908 {
909 add_device (device_manager, dev: &info[0], TRUE);
910 XIFreeDeviceInfo (info);
911 }
912 }
913 else if (ev->info[i].flags & XIDeviceDisabled)
914 remove_device (device_manager, device_id: ev->info[i].deviceid);
915 else if (ev->info[i].flags & XISlaveAttached ||
916 ev->info[i].flags & XISlaveDetached)
917 {
918 GdkDevice *logical = NULL, *physical;
919 GdkSeat *seat;
920
921 physical = g_hash_table_lookup (hash_table: device_manager->id_table,
922 GINT_TO_POINTER (ev->info[i].deviceid));
923
924 if (!physical)
925 continue;
926
927 seat = gdk_device_get_seat (device: physical);
928 gdk_seat_default_remove_physical_device (GDK_SEAT_DEFAULT (seat), device: physical);
929
930 /* Add new logical device if it's an attachment event */
931 if (ev->info[i].flags & XISlaveAttached)
932 {
933 gdk_x11_display_error_trap_push (display);
934 info = XIQueryDevice (dpy: xdisplay, deviceid: ev->info[i].deviceid, ndevices_return: &ndevices);
935 gdk_x11_display_error_trap_pop_ignored (display);
936 if (info)
937 {
938 logical = g_hash_table_lookup (hash_table: device_manager->id_table,
939 GINT_TO_POINTER (info->attachment));
940 XIFreeDeviceInfo (info);
941 }
942
943 if (logical != NULL)
944 {
945 _gdk_device_set_associated_device (device: physical, relative: logical);
946 _gdk_device_add_physical_device (device: logical, physical);
947
948 seat = gdk_device_get_seat (device: logical);
949 gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), device: physical);
950 }
951 }
952 }
953 }
954}
955
956static void
957handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
958 XIDeviceChangedEvent *ev)
959{
960 GdkDisplay *display;
961 GdkDevice *device, *source_device;
962
963 display = device_manager->display;
964 device = g_hash_table_lookup (hash_table: device_manager->id_table,
965 GUINT_TO_POINTER (ev->deviceid));
966 source_device = g_hash_table_lookup (hash_table: device_manager->id_table,
967 GUINT_TO_POINTER (ev->sourceid));
968
969 if (device)
970 {
971 _gdk_device_reset_axes (device);
972 _gdk_device_xi2_unset_scroll_valuators (device: (GdkX11DeviceXI2 *) device);
973 gdk_x11_device_xi2_store_axes (GDK_X11_DEVICE_XI2 (device), NULL, n_axes: 0);
974 translate_device_classes (display, device, classes: ev->classes, n_classes: ev->num_classes);
975
976 g_signal_emit_by_name (G_OBJECT (device), detailed_signal: "changed");
977 }
978
979 if (source_device)
980 _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
981}
982
983static gboolean
984device_get_tool_serial_and_id (GdkDevice *device,
985 guint *serial_id,
986 guint *id)
987{
988 GdkDisplay *display;
989 gulong nitems, bytes_after;
990 guint32 *data;
991 int rc, format;
992 Atom type;
993
994 display = gdk_device_get_display (device);
995
996 gdk_x11_display_error_trap_push (display);
997
998 rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
999 deviceid: gdk_x11_device_get_id (device),
1000 property: gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Wacom Serial IDs"),
1001 offset: 0, length: 5, False, XA_INTEGER, type_return: &type, format_return: &format, num_items_return: &nitems, bytes_after_return: &bytes_after,
1002 data: (guchar **) &data);
1003 gdk_x11_display_error_trap_pop_ignored (display);
1004
1005 if (rc != Success)
1006 return FALSE;
1007
1008 if (type == XA_INTEGER && format == 32)
1009 {
1010 if (nitems >= 4)
1011 *serial_id = data[3];
1012 if (nitems >= 5)
1013 *id = data[4];
1014 }
1015
1016 XFree (data);
1017
1018 return TRUE;
1019}
1020
1021static GdkDeviceToolType
1022device_get_tool_type (GdkDevice *device)
1023{
1024 GdkDisplay *display;
1025 gulong nitems, bytes_after;
1026 guint32 *data;
1027 int rc, format;
1028 Atom type;
1029 Atom device_type;
1030 Atom types[N_WACOM_TYPE_ATOMS];
1031 GdkDeviceToolType tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1032
1033 display = gdk_device_get_display (device);
1034 gdk_x11_display_error_trap_push (display);
1035
1036 rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
1037 deviceid: gdk_x11_device_get_id (device),
1038 property: gdk_x11_get_xatom_by_name_for_display (display, atom_name: "Wacom Tool Type"),
1039 offset: 0, length: 1, False, XA_ATOM, type_return: &type, format_return: &format, num_items_return: &nitems, bytes_after_return: &bytes_after,
1040 data: (guchar **) &data);
1041 gdk_x11_display_error_trap_pop_ignored (display);
1042
1043 if (rc != Success)
1044 return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1045
1046 if (type != XA_ATOM || format != 32 || nitems != 1)
1047 {
1048 XFree (data);
1049 return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1050 }
1051
1052 device_type = *data;
1053 XFree (data);
1054
1055 if (device_type == 0)
1056 return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1057
1058 gdk_x11_display_error_trap_push (display);
1059 rc = XInternAtoms (GDK_DISPLAY_XDISPLAY (display),
1060 (char **) wacom_type_atoms,
1061 N_WACOM_TYPE_ATOMS,
1062 False,
1063 types);
1064 gdk_x11_display_error_trap_pop_ignored (display);
1065
1066 if (rc == 0)
1067 return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1068
1069 if (device_type == types[WACOM_TYPE_STYLUS])
1070 tool_type = GDK_DEVICE_TOOL_TYPE_PEN;
1071 else if (device_type == types[WACOM_TYPE_CURSOR])
1072 tool_type = GDK_DEVICE_TOOL_TYPE_MOUSE;
1073 else if (device_type == types[WACOM_TYPE_ERASER])
1074 tool_type = GDK_DEVICE_TOOL_TYPE_ERASER;
1075 else if (device_type == types[WACOM_TYPE_TOUCH])
1076 tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
1077
1078 return tool_type;
1079}
1080
1081static void
1082handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
1083 XIPropertyEvent *ev)
1084{
1085 GdkDevice *device;
1086
1087 device = g_hash_table_lookup (hash_table: device_manager->id_table,
1088 GUINT_TO_POINTER (ev->deviceid));
1089
1090 if (device != NULL &&
1091 ev->property == gdk_x11_get_xatom_by_name_for_display (display: gdk_device_get_display (device), atom_name: "Wacom Serial IDs"))
1092 {
1093 GdkDeviceTool *tool = NULL;
1094 guint serial_id = 0, tool_id = 0;
1095 GdkSeat *seat;
1096
1097 if (ev->what != XIPropertyDeleted &&
1098 device_get_tool_serial_and_id (device, serial_id: &serial_id, id: &tool_id))
1099 {
1100 GdkDeviceToolType tool_type;
1101
1102 seat = gdk_device_get_seat (device);
1103 tool_type = device_get_tool_type (device);
1104
1105 if (tool_type != GDK_DEVICE_TOOL_TYPE_UNKNOWN)
1106 {
1107 tool = gdk_seat_get_tool (seat, serial: serial_id, hw_id: tool_id, type: tool_type);
1108
1109 if (!tool && serial_id > 0)
1110 {
1111 tool = gdk_device_tool_new (serial: serial_id, hw_id: tool_id, type: tool_type, tool_axes: 0);
1112 gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
1113 }
1114 }
1115 }
1116
1117 gdk_device_update_tool (device, tool);
1118 }
1119}
1120
1121static GdkCrossingMode
1122translate_crossing_mode (int mode)
1123{
1124 switch (mode)
1125 {
1126 case XINotifyNormal:
1127 return GDK_CROSSING_NORMAL;
1128 case XINotifyGrab:
1129 case XINotifyPassiveGrab:
1130 return GDK_CROSSING_GRAB;
1131 case XINotifyUngrab:
1132 case XINotifyPassiveUngrab:
1133 return GDK_CROSSING_UNGRAB;
1134 case XINotifyWhileGrabbed:
1135 /* Fall through, unexpected in pointer crossing events */
1136 default:
1137 g_assert_not_reached ();
1138 return GDK_CROSSING_NORMAL;
1139 }
1140}
1141
1142static GdkNotifyType
1143translate_notify_type (int detail)
1144{
1145 switch (detail)
1146 {
1147 case NotifyInferior:
1148 return GDK_NOTIFY_INFERIOR;
1149 case NotifyAncestor:
1150 return GDK_NOTIFY_ANCESTOR;
1151 case NotifyVirtual:
1152 return GDK_NOTIFY_VIRTUAL;
1153 case NotifyNonlinear:
1154 return GDK_NOTIFY_NONLINEAR;
1155 case NotifyNonlinearVirtual:
1156 return GDK_NOTIFY_NONLINEAR_VIRTUAL;
1157 default:
1158 g_assert_not_reached ();
1159 return GDK_NOTIFY_UNKNOWN;
1160 }
1161}
1162
1163static void
1164set_user_time (GdkEvent *event)
1165{
1166 GdkSurface *surface;
1167 guint32 time;
1168
1169 surface = gdk_event_get_surface (event);
1170 g_return_if_fail (GDK_IS_SURFACE (surface));
1171
1172 time = gdk_event_get_time (event);
1173
1174 /* If an event doesn't have a valid timestamp, we shouldn't use it
1175 * to update the latest user interaction time.
1176 */
1177 if (time != GDK_CURRENT_TIME)
1178 gdk_x11_surface_set_user_time (surface, timestamp: time);
1179}
1180
1181static double *
1182translate_axes (GdkDevice *device,
1183 double x,
1184 double y,
1185 GdkSurface *surface,
1186 XIValuatorState *valuators)
1187{
1188 guint n_axes, i;
1189 double *axes;
1190 double *vals;
1191
1192 n_axes = gdk_device_get_n_axes (device);
1193 axes = g_new0 (double, GDK_AXIS_LAST);
1194 vals = valuators->values;
1195
1196 for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
1197 {
1198 GdkAxisUse use;
1199 double val;
1200
1201 if (!XIMaskIsSet (valuators->mask, i))
1202 continue;
1203
1204 use = gdk_device_get_axis_use (device, index_: i);
1205 val = *vals++;
1206
1207 switch ((guint) use)
1208 {
1209 case GDK_AXIS_X:
1210 case GDK_AXIS_Y:
1211 {
1212 if (use == GDK_AXIS_X)
1213 axes[use] = x;
1214 else
1215 axes[use] = y;
1216 }
1217 break;
1218 default:
1219 _gdk_device_translate_axis (device, index: i, value: val, axis_value: &axes[use]);
1220 break;
1221 }
1222 }
1223
1224 gdk_x11_device_xi2_store_axes (GDK_X11_DEVICE_XI2 (device), axes, n_axes);
1225
1226 return axes;
1227}
1228
1229static gboolean
1230get_event_surface (GdkEventTranslator *translator,
1231 XIEvent *ev,
1232 GdkSurface **surface_p)
1233{
1234 GdkDisplay *display;
1235 GdkSurface *surface = NULL;
1236 gboolean should_have_window = TRUE;
1237
1238 display = GDK_X11_DEVICE_MANAGER_XI2 (translator)->display;
1239
1240 switch (ev->evtype)
1241 {
1242 case XI_KeyPress:
1243 case XI_KeyRelease:
1244 case XI_ButtonPress:
1245 case XI_ButtonRelease:
1246 case XI_Motion:
1247#ifdef XINPUT_2_2
1248 case XI_TouchUpdate:
1249 case XI_TouchBegin:
1250 case XI_TouchEnd:
1251#endif /* XINPUT_2_2 */
1252 {
1253 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1254
1255 surface = gdk_x11_surface_lookup_for_display (display, window: xev->event);
1256
1257 /* Apply keyboard grabs to non-native windows */
1258 if (ev->evtype == XI_KeyPress || ev->evtype == XI_KeyRelease)
1259 {
1260 GdkDeviceGrabInfo *info;
1261 GdkDevice *device;
1262 gulong serial;
1263
1264 device = g_hash_table_lookup (GDK_X11_DEVICE_MANAGER_XI2 (translator)->id_table,
1265 GUINT_TO_POINTER (((XIDeviceEvent *) ev)->deviceid));
1266
1267 serial = _gdk_display_get_next_serial (display);
1268 info = _gdk_display_has_device_grab (display, device, serial);
1269
1270 if (info && !info->owner_events)
1271 {
1272 /* Report key event against grab surface */
1273 surface = info->surface;
1274 }
1275 }
1276 }
1277 break;
1278#ifdef XINPUT_2_4
1279 case XI_GesturePinchBegin:
1280 case XI_GesturePinchUpdate:
1281 case XI_GesturePinchEnd:
1282 {
1283 XIGesturePinchEvent *xev = (XIGesturePinchEvent *) ev;
1284
1285 surface = gdk_x11_surface_lookup_for_display (display, xev->event);
1286 }
1287 break;
1288 case XI_GestureSwipeBegin:
1289 case XI_GestureSwipeUpdate:
1290 case XI_GestureSwipeEnd:
1291 {
1292 XIGestureSwipeEvent *xev = (XIGestureSwipeEvent *) ev;
1293
1294 surface = gdk_x11_surface_lookup_for_display (display, xev->event);
1295 }
1296 break;
1297#endif /* XINPUT_2_4 */
1298 case XI_Enter:
1299 case XI_Leave:
1300 case XI_FocusIn:
1301 case XI_FocusOut:
1302 {
1303 XIEnterEvent *xev = (XIEnterEvent *) ev;
1304
1305 surface = gdk_x11_surface_lookup_for_display (display, window: xev->event);
1306 }
1307 break;
1308 default:
1309 should_have_window = FALSE;
1310 break;
1311 }
1312
1313 *surface_p = surface;
1314
1315 if (should_have_window && !surface)
1316 return FALSE;
1317
1318 return TRUE;
1319}
1320
1321static gboolean
1322scroll_valuators_changed (GdkX11DeviceXI2 *device,
1323 XIValuatorState *valuators,
1324 double *dx,
1325 double *dy)
1326{
1327 gboolean has_scroll_valuators = FALSE;
1328 GdkScrollDirection direction;
1329 guint n_axes, i, n_val;
1330 double *vals;
1331
1332 n_axes = gdk_device_get_n_axes (GDK_DEVICE (device));
1333 vals = valuators->values;
1334 *dx = *dy = 0;
1335 n_val = 0;
1336
1337 for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
1338 {
1339 double delta;
1340
1341 if (!XIMaskIsSet (valuators->mask, i))
1342 continue;
1343
1344 if (_gdk_x11_device_xi2_get_scroll_delta (device, n_valuator: i, valuator_value: vals[n_val],
1345 direction_ret: &direction, delta_ret: &delta))
1346 {
1347 has_scroll_valuators = TRUE;
1348
1349 if (direction == GDK_SCROLL_UP ||
1350 direction == GDK_SCROLL_DOWN)
1351 *dy = delta;
1352 else
1353 *dx = delta;
1354 }
1355
1356 n_val++;
1357 }
1358
1359 return has_scroll_valuators;
1360}
1361
1362/* We only care about focus events that indicate that _this_
1363 * surface (not an ancestor or child) got or lost the focus
1364 */
1365static void
1366_gdk_device_manager_xi2_handle_focus (GdkSurface *surface,
1367 Window original,
1368 GdkDevice *device,
1369 GdkDevice *source_device,
1370 gboolean focus_in,
1371 int detail,
1372 int mode)
1373{
1374 GdkToplevelX11 *toplevel;
1375 GdkX11Screen *x11_screen;
1376 gboolean had_focus;
1377
1378 g_return_if_fail (GDK_IS_SURFACE (surface));
1379 g_return_if_fail (GDK_IS_DEVICE (device));
1380 g_return_if_fail (source_device == NULL || GDK_IS_DEVICE (source_device));
1381
1382 GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS,
1383 g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
1384 GDK_SURFACE_XID (surface),
1385 notify_details[detail],
1386 notify_modes[mode]));
1387
1388 toplevel = _gdk_x11_surface_get_toplevel (window: surface);
1389
1390 if (!toplevel)
1391 return;
1392
1393 if (toplevel->focus_window == original)
1394 return;
1395
1396 had_focus = HAS_FOCUS (toplevel);
1397 x11_screen = GDK_X11_SCREEN (GDK_SURFACE_SCREEN (surface));
1398
1399 switch (detail)
1400 {
1401 case NotifyAncestor:
1402 case NotifyVirtual:
1403 /* When the focus moves from an ancestor of the window to
1404 * the window or a descendent of the window, *and* the
1405 * pointer is inside the window, then we were previously
1406 * receiving keystroke events in the has_pointer_focus
1407 * case and are now receiving them in the
1408 * has_focus_window case.
1409 */
1410 if (toplevel->has_pointer &&
1411 !x11_screen->wmspec_check_window &&
1412 mode != NotifyGrab &&
1413 mode != XINotifyPassiveGrab &&
1414 mode != XINotifyPassiveUngrab &&
1415 mode != NotifyUngrab)
1416 toplevel->has_pointer_focus = (focus_in) ? FALSE : TRUE;
1417 G_GNUC_FALLTHROUGH;
1418
1419 case NotifyNonlinear:
1420 case NotifyNonlinearVirtual:
1421 if (mode != NotifyGrab &&
1422 mode != XINotifyPassiveGrab &&
1423 mode != XINotifyPassiveUngrab &&
1424 mode != NotifyUngrab)
1425 toplevel->has_focus_window = (focus_in) ? TRUE : FALSE;
1426 /* We pretend that the focus moves to the grab
1427 * window, so we pay attention to NotifyGrab
1428 * NotifyUngrab, and ignore NotifyWhileGrabbed
1429 */
1430 if (mode != NotifyWhileGrabbed)
1431 toplevel->has_focus = (focus_in) ? TRUE : FALSE;
1432 break;
1433 case NotifyPointer:
1434 /* The X server sends NotifyPointer/NotifyGrab,
1435 * but the pointer focus is ignored while a
1436 * grab is in effect
1437 */
1438 if (!x11_screen->wmspec_check_window &&
1439 mode != NotifyGrab &&
1440 mode != XINotifyPassiveGrab &&
1441 mode != XINotifyPassiveUngrab &&
1442 mode != NotifyUngrab)
1443 toplevel->has_pointer_focus = (focus_in) ? TRUE : FALSE;
1444 break;
1445 case NotifyInferior:
1446 case NotifyPointerRoot:
1447 case NotifyDetailNone:
1448 default:
1449 break;
1450 }
1451
1452 if (HAS_FOCUS (toplevel) != had_focus)
1453 {
1454 GdkEvent *event;
1455
1456 event = gdk_focus_event_new (surface, device, focus_in);
1457 gdk_display_put_event (display: gdk_surface_get_display (surface), event);
1458 gdk_event_unref (event);
1459 }
1460}
1461
1462static GdkEvent *
1463gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
1464 GdkDisplay *display,
1465 const XEvent *xevent)
1466{
1467 GdkX11DeviceManagerXI2 *device_manager;
1468 const XGenericEventCookie *cookie;
1469 GdkDevice *device, *source_device;
1470 GdkSurface *surface;
1471 GdkX11Surface *impl;
1472 int scale;
1473 XIEvent *ev;
1474 GdkEvent *event;
1475
1476 event = NULL;
1477
1478 device_manager = (GdkX11DeviceManagerXI2 *) translator;
1479 cookie = &xevent->xcookie;
1480
1481 if (xevent->type != GenericEvent ||
1482 cookie->extension != device_manager->opcode)
1483 return event;
1484
1485 ev = (XIEvent *) cookie->data;
1486
1487 if (!ev)
1488 return NULL;
1489
1490 if (!get_event_surface (translator, ev, surface_p: &surface))
1491 return NULL;
1492
1493 if (surface && GDK_SURFACE_DESTROYED (surface))
1494 return NULL;
1495
1496 scale = 1;
1497 if (surface)
1498 {
1499 impl = GDK_X11_SURFACE (surface);
1500 scale = impl->surface_scale;
1501 }
1502
1503 if (ev->evtype == XI_Motion ||
1504 ev->evtype == XI_ButtonRelease)
1505 {
1506 if (_gdk_x11_moveresize_handle_event (event: xevent))
1507 return NULL;
1508 }
1509
1510 switch (ev->evtype)
1511 {
1512 case XI_HierarchyChanged:
1513 handle_hierarchy_changed (device_manager,
1514 ev: (XIHierarchyEvent *) ev);
1515 break;
1516 case XI_DeviceChanged:
1517 handle_device_changed (device_manager,
1518 ev: (XIDeviceChangedEvent *) ev);
1519 break;
1520 case XI_PropertyEvent:
1521 handle_property_change (device_manager,
1522 ev: (XIPropertyEvent *) ev);
1523 break;
1524 case XI_KeyPress:
1525 case XI_KeyRelease:
1526 {
1527 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1528 GdkKeymap *keymap = gdk_display_get_keymap (display);
1529 GdkModifierType consumed, state, orig_state;
1530 int layout, level;
1531 guint keyval;
1532 GdkTranslatedKey translated;
1533 GdkTranslatedKey no_lock;
1534
1535 GDK_DISPLAY_NOTE (display, EVENTS,
1536 g_message ("key %s:\twindow %ld\n"
1537 "\tdevice:%u\n"
1538 "\tsource device:%u\n"
1539 "\tkey number: %u\n",
1540 (ev->evtype == XI_KeyPress) ? "press" : "release",
1541 xev->event,
1542 xev->deviceid,
1543 xev->sourceid,
1544 xev->detail));
1545
1546 state = _gdk_x11_device_xi2_translate_state (mods_state: &xev->mods, buttons_state: &xev->buttons, group_state: &xev->group);
1547
1548 device = g_hash_table_lookup (hash_table: device_manager->id_table,
1549 GUINT_TO_POINTER (xev->deviceid));
1550
1551 source_device = g_hash_table_lookup (hash_table: device_manager->id_table,
1552 GUINT_TO_POINTER (xev->sourceid));
1553
1554 keyval = GDK_KEY_VoidSymbol;
1555
1556 gdk_keymap_translate_keyboard_state (keymap,
1557 hardware_keycode: xev->detail,
1558 state,
1559 group: xev->group.effective,
1560 keyval: &keyval,
1561 effective_group: &layout, level: &level, consumed_modifiers: &consumed);
1562 orig_state = state;
1563 state &= ~consumed;
1564 _gdk_x11_keymap_add_virt_mods (keymap, modifiers: &state);
1565 state |= orig_state;
1566
1567 translated.keyval = keyval;
1568 translated.consumed = consumed;
1569 translated.layout = layout;
1570 translated.level = level;
1571
1572 if (orig_state & GDK_LOCK_MASK)
1573 {
1574 orig_state &= ~GDK_LOCK_MASK;
1575
1576 gdk_keymap_translate_keyboard_state (keymap,
1577 hardware_keycode: xev->detail,
1578 state: orig_state,
1579 group: xev->group.effective,
1580 keyval: &keyval,
1581 effective_group: &layout, level: &level, consumed_modifiers: &consumed);
1582
1583 no_lock.keyval = keyval;
1584 no_lock.consumed = consumed;
1585 no_lock.layout = layout;
1586 no_lock.level = level;
1587 }
1588 else
1589 {
1590 no_lock = translated;
1591 }
1592 event = gdk_key_event_new (type: xev->evtype == XI_KeyPress
1593 ? GDK_KEY_PRESS
1594 : GDK_KEY_RELEASE,
1595 surface,
1596 device,
1597 time: xev->time,
1598 keycode: xev->detail,
1599 modifiers: state,
1600 is_modifier: gdk_x11_keymap_key_is_modifier (keymap, keycode: xev->detail),
1601 translated: &translated,
1602 no_lock: &no_lock);
1603
1604 if (ev->evtype == XI_KeyPress)
1605 set_user_time (event);
1606
1607 /* FIXME: emulate autorepeat on key
1608 * release? XI2 seems attached to Xkb.
1609 */
1610 }
1611
1612 break;
1613 case XI_ButtonPress:
1614 case XI_ButtonRelease:
1615 {
1616 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1617
1618 GDK_DISPLAY_NOTE (display, EVENTS,
1619 g_message ("button %s:\twindow %ld\n"
1620 "\tdevice:%u\n"
1621 "\tsource device:%u\n"
1622 "\tbutton number: %u\n"
1623 "\tx,y: %.2f %.2f",
1624 (ev->evtype == XI_ButtonPress) ? "press" : "release",
1625 xev->event,
1626 xev->deviceid,
1627 xev->sourceid,
1628 xev->detail,
1629 xev->event_x, xev->event_y));
1630
1631#ifdef XINPUT_2_2
1632 if (xev->flags & XIPointerEmulated)
1633 return FALSE;
1634#endif
1635
1636 if (ev->evtype == XI_ButtonRelease &&
1637 (xev->detail >= 4 && xev->detail <= 7))
1638 return FALSE;
1639 else if (ev->evtype == XI_ButtonPress &&
1640 (xev->detail >= 4 && xev->detail <= 7))
1641 {
1642 GdkScrollDirection direction;
1643
1644 /* Button presses of button 4-7 are scroll events */
1645
1646 if (xev->detail == 4)
1647 direction = GDK_SCROLL_UP;
1648 else if (xev->detail == 5)
1649 direction = GDK_SCROLL_DOWN;
1650 else if (xev->detail == 6)
1651 direction = GDK_SCROLL_LEFT;
1652 else
1653 direction = GDK_SCROLL_RIGHT;
1654
1655 device = g_hash_table_lookup (hash_table: device_manager->id_table,
1656 GUINT_TO_POINTER (xev->deviceid));
1657
1658 source_device = g_hash_table_lookup (hash_table: device_manager->id_table,
1659 GUINT_TO_POINTER (xev->sourceid));
1660
1661 event = gdk_scroll_event_new_discrete (surface,
1662 device: source_device,
1663 NULL,
1664 time: xev->time,
1665 state: _gdk_x11_device_xi2_translate_state (mods_state: &xev->mods, buttons_state: &xev->buttons, group_state: &xev->group),
1666 direction,
1667 FALSE);
1668
1669 }
1670 else
1671 {
1672 double x, y;
1673 double *axes;
1674
1675 device = g_hash_table_lookup (hash_table: device_manager->id_table,
1676 GUINT_TO_POINTER (xev->deviceid));
1677
1678 source_device = g_hash_table_lookup (hash_table: device_manager->id_table,
1679 GUINT_TO_POINTER (xev->sourceid));
1680
1681 axes = translate_axes (device,
1682 x: (double) xev->event_x / scale,
1683 y: (double) xev->event_y / scale,
1684 surface,
1685 valuators: &xev->valuators);
1686
1687 x = (double) xev->event_x / scale;
1688 y = (double) xev->event_y / scale;
1689
1690 event = gdk_button_event_new (type: ev->evtype == XI_ButtonPress
1691 ? GDK_BUTTON_PRESS
1692 : GDK_BUTTON_RELEASE,
1693 surface,
1694 device,
1695 tool: source_device->last_tool,
1696 time: xev->time,
1697 state: _gdk_x11_device_xi2_translate_state (mods_state: &xev->mods, buttons_state: &xev->buttons, group_state: &xev->group),
1698 button: xev->detail,
1699 x, y,
1700 axes);
1701 }
1702
1703 if (ev->evtype == XI_ButtonPress)
1704 set_user_time (event);
1705
1706 break;
1707 }
1708
1709 case XI_Motion:
1710 {
1711 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1712 double delta_x, delta_y;
1713
1714 double x, y;
1715 double *axes;
1716
1717#ifdef XINPUT_2_2
1718 if (xev->flags & XIPointerEmulated)
1719 return FALSE;
1720#endif
1721
1722 source_device = g_hash_table_lookup (hash_table: device_manager->id_table,
1723 GUINT_TO_POINTER (xev->sourceid));
1724 device = g_hash_table_lookup (hash_table: device_manager->id_table,
1725 GUINT_TO_POINTER (xev->deviceid));
1726
1727 /* When scrolling, X might send events twice here; once with both the
1728 * device and the source device set to the physical device, and once
1729 * with the device set to the logical device.
1730 *
1731 * Since we are only interested in the latter, and
1732 * scroll_valuators_changed() updates the valuator cache for the
1733 * source device, we need to explicitly ignore the first event in
1734 * order to get the correct delta for the second.
1735 */
1736 if (gdk_x11_device_xi2_get_device_type (device: (GdkX11DeviceXI2 *) device) != GDK_X11_DEVICE_TYPE_PHYSICAL &&
1737 scroll_valuators_changed (GDK_X11_DEVICE_XI2 (source_device),
1738 valuators: &xev->valuators, dx: &delta_x, dy: &delta_y))
1739 {
1740 GdkModifierType state;
1741
1742 GDK_DISPLAY_NOTE (display, EVENTS,
1743 g_message ("smooth scroll: \n\tdevice: %u\n\tsource device: %u\n\twindow %ld\n\tdeltas: %f %f",
1744 xev->deviceid, xev->sourceid,
1745 xev->event, delta_x, delta_y));
1746
1747 state = _gdk_x11_device_xi2_translate_state (mods_state: &xev->mods, buttons_state: &xev->buttons, group_state: &xev->group);
1748
1749 if (gdk_device_get_source (device: source_device) != GDK_SOURCE_TOUCHPAD &&
1750 ((delta_x == 0.0 && ABS (delta_y) == 1.0) ||
1751 (ABS (delta_x) == 1.0 && delta_y == 0.0)))
1752 {
1753 GdkScrollDirection direction;
1754
1755 if (delta_x > 0)
1756 direction = GDK_SCROLL_RIGHT;
1757 else if (delta_x < 0)
1758 direction = GDK_SCROLL_LEFT;
1759 else if (delta_y > 0)
1760 direction = GDK_SCROLL_DOWN;
1761 else
1762 direction = GDK_SCROLL_UP;
1763
1764 event = gdk_scroll_event_new_discrete (surface,
1765 device,
1766 NULL,
1767 time: xev->time,
1768 state,
1769 direction,
1770 FALSE);
1771 }
1772 else
1773 {
1774 event = gdk_scroll_event_new (surface,
1775 device,
1776 NULL,
1777 time: xev->time,
1778 state,
1779 delta_x,
1780 delta_y,
1781 is_stop: delta_x == 0.0 && delta_y == 0.0);
1782 }
1783 break;
1784 }
1785
1786 axes = translate_axes (device,
1787 x: (double) xev->event_x / scale,
1788 y: (double) xev->event_y / scale,
1789 surface,
1790 valuators: &xev->valuators);
1791
1792 x = (double) xev->event_x / scale;
1793 y = (double) xev->event_y / scale;
1794
1795 event = gdk_motion_event_new (surface,
1796 device,
1797 tool: source_device->last_tool,
1798 time: xev->time,
1799 state: _gdk_x11_device_xi2_translate_state (mods_state: &xev->mods, buttons_state: &xev->buttons, group_state: &xev->group),
1800 x, y,
1801 axes);
1802
1803 }
1804 break;
1805
1806#ifdef XINPUT_2_2
1807 case XI_TouchBegin:
1808 case XI_TouchEnd:
1809 {
1810 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1811 GdkModifierType state;
1812
1813 double x, y;
1814 double *axes;
1815
1816 GDK_DISPLAY_NOTE (display, EVENTS,
1817 g_message ("touch %s:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %s",
1818 ev->evtype == XI_TouchBegin ? "begin" : "end",
1819 xev->event,
1820 xev->detail,
1821 xev->flags & XITouchEmulatingPointer ? "true" : "false"));
1822
1823 device = g_hash_table_lookup (hash_table: device_manager->id_table,
1824 GUINT_TO_POINTER (xev->deviceid));
1825
1826 source_device = g_hash_table_lookup (hash_table: device_manager->id_table,
1827 GUINT_TO_POINTER (xev->sourceid));
1828
1829 state = _gdk_x11_device_xi2_translate_state (mods_state: &xev->mods, buttons_state: &xev->buttons, group_state: &xev->group);
1830 if (ev->evtype == XI_TouchBegin)
1831 state |= GDK_BUTTON1_MASK;
1832
1833 axes = translate_axes (device,
1834 x: (double) xev->event_x / scale,
1835 y: (double) xev->event_y / scale,
1836 surface,
1837 valuators: &xev->valuators);
1838
1839 x = (double) xev->event_x / scale;
1840 y = (double) xev->event_y / scale;
1841
1842 event = gdk_touch_event_new (type: ev->evtype == XI_TouchBegin
1843 ? GDK_TOUCH_BEGIN
1844 : GDK_TOUCH_END,
1845 GUINT_TO_POINTER (xev->detail),
1846 surface,
1847 device,
1848 time: xev->time,
1849 state,
1850 x, y,
1851 axes,
1852 emulating: xev->flags & XITouchEmulatingPointer);
1853
1854 if (ev->evtype == XI_TouchBegin)
1855 set_user_time (event);
1856 }
1857 break;
1858
1859 case XI_TouchUpdate:
1860 {
1861 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1862 GdkModifierType state;
1863
1864 double x, y;
1865 double *axes;
1866
1867 GDK_DISPLAY_NOTE (display, EVENTS,
1868 g_message ("touch update:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %s",
1869 xev->event,
1870 xev->detail,
1871 xev->flags & XITouchEmulatingPointer ? "true" : "false"));
1872
1873 device = g_hash_table_lookup (hash_table: device_manager->id_table,
1874 GINT_TO_POINTER (xev->deviceid));
1875
1876 source_device = g_hash_table_lookup (hash_table: device_manager->id_table,
1877 GUINT_TO_POINTER (xev->sourceid));
1878
1879 state = _gdk_x11_device_xi2_translate_state (mods_state: &xev->mods, buttons_state: &xev->buttons, group_state: &xev->group);
1880 state |= GDK_BUTTON1_MASK;
1881
1882 axes = translate_axes (device,
1883 x: (double) xev->event_x / scale,
1884 y: (double) xev->event_y / scale,
1885 surface,
1886 valuators: &xev->valuators);
1887
1888 x = (double) xev->event_x / scale;
1889 y = (double) xev->event_y / scale;
1890
1891 event = gdk_touch_event_new (type: GDK_TOUCH_UPDATE,
1892 GUINT_TO_POINTER (xev->detail),
1893 surface,
1894 device,
1895 time: xev->time,
1896 state,
1897 x, y,
1898 axes,
1899 emulating: xev->flags & XITouchEmulatingPointer);
1900 }
1901 break;
1902#endif /* XINPUT_2_2 */
1903
1904#ifdef XINPUT_2_4
1905 case XI_GesturePinchBegin:
1906 case XI_GesturePinchUpdate:
1907 case XI_GesturePinchEnd:
1908 {
1909 XIGesturePinchEvent *xev = (XIGesturePinchEvent *) ev;
1910 GdkModifierType state;
1911 GdkTouchpadGesturePhase phase;
1912 double x, y;
1913
1914#ifdef G_ENABLE_DEBUG
1915 const char *event_name = "";
1916 switch (xev->evtype)
1917 {
1918 case XI_GesturePinchBegin:
1919 event_name = "begin";
1920 break;
1921 case XI_GesturePinchUpdate:
1922 event_name = "update";
1923 break;
1924 case XI_GesturePinchEnd:
1925 event_name = "end";
1926 break;
1927 default:
1928 break;
1929 }
1930#endif
1931
1932 GDK_NOTE (EVENTS,
1933 g_message ("pinch gesture %s:\twindow %ld\n\tfinger_count: %u%s",
1934 event_name,
1935 xev->event,
1936 xev->detail,
1937 xev->flags & XIGesturePinchEventCancelled ? "\n\tcancelled" : ""));
1938
1939 device = g_hash_table_lookup (device_manager->id_table,
1940 GINT_TO_POINTER (xev->deviceid));
1941
1942 state = _gdk_x11_device_xi2_translate_state (&xev->mods, NULL, &xev->group);
1943 phase = _gdk_x11_device_xi2_gesture_type_to_phase (xev->evtype, xev->flags);
1944
1945 x = (double) xev->event_x / scale;
1946 y = (double) xev->event_y / scale;
1947
1948 event = gdk_touchpad_event_new_pinch (surface,
1949 NULL, /* FIXME make up sequences */
1950 device,
1951 xev->time,
1952 state,
1953 phase,
1954 x, y,
1955 xev->detail,
1956 xev->delta_x,
1957 xev->delta_y,
1958 xev->scale,
1959 xev->delta_angle * G_PI / 180);
1960
1961 if (ev->evtype == XI_GesturePinchBegin)
1962 set_user_time (event);
1963 }
1964 break;
1965
1966 case XI_GestureSwipeBegin:
1967 case XI_GestureSwipeUpdate:
1968 case XI_GestureSwipeEnd:
1969 {
1970 XIGestureSwipeEvent *xev = (XIGestureSwipeEvent *) ev;
1971 GdkModifierType state;
1972 GdkTouchpadGesturePhase phase;
1973 double x, y;
1974
1975#ifdef G_ENABLE_DEBUG
1976 const char *event_name = "";
1977 switch (xev->evtype)
1978 {
1979 case XI_GestureSwipeBegin:
1980 event_name = "begin";
1981 break;
1982 case XI_GestureSwipeUpdate:
1983 event_name = "update";
1984 break;
1985 case XI_GestureSwipeEnd:
1986 event_name = "end";
1987 break;
1988 default:
1989 break;
1990 }
1991#endif
1992
1993 GDK_NOTE (EVENTS,
1994 g_message ("swipe gesture %s:\twindow %ld\n\tfinger_count: %u%s",
1995 event_name,
1996 xev->event,
1997 xev->detail,
1998 xev->flags & XIGestureSwipeEventCancelled ? "\n\tcancelled" : ""));
1999
2000 device = g_hash_table_lookup (device_manager->id_table,
2001 GINT_TO_POINTER (xev->deviceid));
2002
2003 state = _gdk_x11_device_xi2_translate_state (&xev->mods, NULL, &xev->group);
2004 phase = _gdk_x11_device_xi2_gesture_type_to_phase (xev->evtype, xev->flags);
2005
2006 x = (double) xev->event_x / scale;
2007 y = (double) xev->event_y / scale;
2008
2009 event = gdk_touchpad_event_new_swipe (surface,
2010 NULL, /* FIXME make up sequences */
2011 device,
2012 xev->time,
2013 state,
2014 phase,
2015 x, y,
2016 xev->detail,
2017 xev->delta_x,
2018 xev->delta_y);
2019
2020 if (ev->evtype == XI_GestureSwipeBegin)
2021 set_user_time (event);
2022 }
2023 break;
2024#endif /* XINPUT_2_4 */
2025
2026 case XI_Enter:
2027 case XI_Leave:
2028 {
2029 XIEnterEvent *xev = (XIEnterEvent *) ev;
2030 GdkModifierType state;
2031
2032 GDK_DISPLAY_NOTE (display, EVENTS,
2033 g_message ("%s notify:\twindow %ld\n\tsubwindow:%ld\n"
2034 "\tdevice: %u\n\tsource device: %u\n"
2035 "\tnotify type: %u\n\tcrossing mode: %u",
2036 (ev->evtype == XI_Enter) ? "enter" : "leave",
2037 xev->event, xev->child,
2038 xev->deviceid, xev->sourceid,
2039 xev->detail, xev->mode));
2040
2041 device = g_hash_table_lookup (hash_table: device_manager->id_table,
2042 GINT_TO_POINTER (xev->deviceid));
2043
2044 source_device = g_hash_table_lookup (hash_table: device_manager->id_table,
2045 GUINT_TO_POINTER (xev->sourceid));
2046
2047 state = _gdk_x11_device_xi2_translate_state (mods_state: &xev->mods, buttons_state: &xev->buttons, group_state: &xev->group);
2048
2049 /* Ignore normal crossing events while there is an implicit grab.
2050 * We will receive a crossing event with one of the other details if
2051 * the implicit grab were finished (eg. releasing the button outside
2052 * the window triggers a XINotifyUngrab leave).
2053 */
2054 if (xev->mode == XINotifyNormal &&
2055 (state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
2056 GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)))
2057 break;
2058
2059 if (ev->evtype == XI_Enter &&
2060 xev->detail != XINotifyInferior && xev->mode != XINotifyPassiveUngrab &&
2061 GDK_IS_TOPLEVEL (ptr: surface))
2062 {
2063 if (gdk_x11_device_xi2_get_device_type (device: (GdkX11DeviceXI2 *) device) != GDK_X11_DEVICE_TYPE_LOGICAL)
2064 _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
2065 else
2066 {
2067 GList *physical_devices, *l;
2068
2069 physical_devices = gdk_device_list_physical_devices (device: source_device);
2070
2071 for (l = physical_devices; l; l = l->next)
2072 _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (l->data));
2073
2074 g_list_free (list: physical_devices);
2075 }
2076 }
2077
2078 event = gdk_crossing_event_new (type: ev->evtype == XI_Enter
2079 ? GDK_ENTER_NOTIFY
2080 : GDK_LEAVE_NOTIFY,
2081 surface,
2082 device,
2083 time: xev->time,
2084 state,
2085 x: (double) xev->event_x / scale,
2086 y: (double) xev->event_y / scale,
2087 mode: translate_crossing_mode (mode: xev->mode),
2088 notify: translate_notify_type (detail: xev->detail));
2089 }
2090 break;
2091 case XI_FocusIn:
2092 case XI_FocusOut:
2093 {
2094 if (surface)
2095 {
2096 XIEnterEvent *xev = (XIEnterEvent *) ev;
2097
2098 device = g_hash_table_lookup (hash_table: device_manager->id_table,
2099 GINT_TO_POINTER (xev->deviceid));
2100
2101 source_device = g_hash_table_lookup (hash_table: device_manager->id_table,
2102 GUINT_TO_POINTER (xev->sourceid));
2103
2104 _gdk_device_manager_xi2_handle_focus (surface,
2105 original: xev->event,
2106 device,
2107 source_device,
2108 focus_in: (ev->evtype == XI_FocusIn) ? TRUE : FALSE,
2109 detail: xev->detail,
2110 mode: xev->mode);
2111 }
2112 }
2113 break;
2114 default:
2115 break;
2116 }
2117
2118 return event;
2119}
2120
2121static GdkEventMask
2122gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
2123{
2124 return (GDK_KEY_PRESS_MASK |
2125 GDK_KEY_RELEASE_MASK |
2126 GDK_BUTTON_PRESS_MASK |
2127 GDK_BUTTON_RELEASE_MASK |
2128 GDK_SCROLL_MASK |
2129 GDK_ENTER_NOTIFY_MASK |
2130 GDK_LEAVE_NOTIFY_MASK |
2131 GDK_POINTER_MOTION_MASK |
2132 GDK_BUTTON1_MOTION_MASK |
2133 GDK_BUTTON2_MOTION_MASK |
2134 GDK_BUTTON3_MOTION_MASK |
2135 GDK_BUTTON_MOTION_MASK |
2136 GDK_FOCUS_CHANGE_MASK |
2137 GDK_TOUCH_MASK |
2138 GDK_TOUCHPAD_GESTURE_MASK);
2139}
2140
2141static void
2142gdk_x11_device_manager_xi2_select_surface_events (GdkEventTranslator *translator,
2143 Window window,
2144 GdkEventMask evmask)
2145{
2146 XIEventMask event_mask;
2147
2148 event_mask.deviceid = XIAllMasterDevices;
2149 event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (GDK_X11_DEVICE_MANAGER_XI2 (translator),
2150 event_mask: evmask,
2151 len: &event_mask.mask_len);
2152
2153 _gdk_x11_device_manager_xi2_select_events (GDK_X11_DEVICE_MANAGER_XI2 (translator), xwindow: window, event_mask: &event_mask);
2154 g_free (mem: event_mask.mask);
2155}
2156
2157static GdkSurface *
2158gdk_x11_device_manager_xi2_get_surface (GdkEventTranslator *translator,
2159 const XEvent *xevent)
2160{
2161 GdkX11DeviceManagerXI2 *device_manager;
2162 XIEvent *ev;
2163 GdkSurface *surface = NULL;
2164
2165 device_manager = (GdkX11DeviceManagerXI2 *) translator;
2166
2167 if (xevent->type != GenericEvent ||
2168 xevent->xcookie.extension != device_manager->opcode)
2169 return NULL;
2170
2171 ev = (XIEvent *) xevent->xcookie.data;
2172 if (!ev)
2173 return NULL;
2174
2175 get_event_surface (translator, ev, surface_p: &surface);
2176 return surface;
2177}
2178
2179GdkDevice *
2180_gdk_x11_device_manager_xi2_lookup (GdkX11DeviceManagerXI2 *device_manager_xi2,
2181 int device_id)
2182{
2183 return g_hash_table_lookup (hash_table: device_manager_xi2->id_table,
2184 GINT_TO_POINTER (device_id));
2185}
2186

source code of gtk/gdk/x11/gdkdevicemanager-xi2.c