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 "gdkeventtranslator.h"
27 #include "gdkkeys-x11.h"
28 #include "gdkprivate-x11.h"
29 #include "gdkdisplay-x11.h"
30 #include "gdkintl.h"
31 #include "gdkkeysyms.h"
32 #include "gdkinternals.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
43 static const char notify_modes[][19] = {
44 "NotifyNormal",
45 "NotifyGrab",
46 "NotifyUngrab",
47 "NotifyWhileGrabbed"
48 };
49
50 static 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
65 static 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
74 enum {
75 WACOM_TYPE_STYLUS,
76 WACOM_TYPE_CURSOR,
77 WACOM_TYPE_ERASER,
78 WACOM_TYPE_PAD,
79 WACOM_TYPE_TOUCH,
80 };
81
82 struct _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
96 struct _GdkX11DeviceManagerXI2Class
97 {
98 GObjectClass parent_class;
99 };
100
101 static void gdk_x11_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
102
103 G_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
107 static void gdk_x11_device_manager_xi2_constructed (GObject *object);
108 static void gdk_x11_device_manager_xi2_dispose (GObject *object);
109 static void gdk_x11_device_manager_xi2_set_property (GObject *object,
110 guint prop_id,
111 const GValue *value,
112 GParamSpec *pspec);
113 static void gdk_x11_device_manager_xi2_get_property (GObject *object,
114 guint prop_id,
115 GValue *value,
116 GParamSpec *pspec);
117
118 static GdkEvent * gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
119 GdkDisplay *display,
120 const XEvent *xevent);
121 static GdkEventMask gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator);
122 static void gdk_x11_device_manager_xi2_select_surface_events (GdkEventTranslator *translator,
123 Window window,
124 GdkEventMask event_mask);
125 static GdkSurface * gdk_x11_device_manager_xi2_get_surface (GdkEventTranslator *translator,
126 const XEvent *xevent);
127
128 enum {
129 PROP_0,
130 PROP_DISPLAY,
131 PROP_OPCODE,
132 PROP_MAJOR,
133 PROP_MINOR
134 };
135
136 static void
gdk_x11_device_manager_xi2_class_init(GdkX11DeviceManagerXI2Class * klass)137 gdk_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 (object_class,
147 PROP_DISPLAY,
148 g_param_spec_object ("display",
149 "Display",
150 "Display for the device manager",
151 GDK_TYPE_DISPLAY,
152 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
153 G_PARAM_STATIC_STRINGS));
154 g_object_class_install_property (object_class,
155 PROP_OPCODE,
156 g_param_spec_int ("opcode",
157 P_("Opcode"),
158 P_("Opcode for XInput2 requests"),
159 0, G_MAXINT, 0,
160 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
161 G_PARAM_STATIC_STRINGS));
162 g_object_class_install_property (object_class,
163 PROP_MAJOR,
164 g_param_spec_int ("major",
165 P_("Major"),
166 P_("Major version number"),
167 0, G_MAXINT, 0,
168 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
169 G_PARAM_STATIC_STRINGS));
170 g_object_class_install_property (object_class,
171 PROP_MINOR,
172 g_param_spec_int ("minor",
173 P_("Minor"),
174 P_("Minor version number"),
175 0, G_MAXINT, 0,
176 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
177 G_PARAM_STATIC_STRINGS));
178 }
179
180 static void
gdk_x11_device_manager_xi2_init(GdkX11DeviceManagerXI2 * device_manager)181 gdk_x11_device_manager_xi2_init (GdkX11DeviceManagerXI2 *device_manager)
182 {
183 device_manager->id_table = g_hash_table_new_full (g_direct_hash,
184 g_direct_equal,
185 NULL,
186 (GDestroyNotify) g_object_unref);
187 }
188
189 static void
_gdk_x11_device_manager_xi2_select_events(GdkX11DeviceManagerXI2 * device_manager,Window xwindow,XIEventMask * event_mask)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 (xdisplay, xwindow, event_mask, 1);
201 }
202
203 static void
translate_valuator_class(GdkDisplay * display,GdkDevice * device,Atom valuator_label,double min,double max,double resolution)204 translate_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, "Abs X");
219 label_atoms [GDK_AXIS_Y] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Y");
220 label_atoms [GDK_AXIS_PRESSURE] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Pressure");
221 label_atoms [GDK_AXIS_XTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt X");
222 label_atoms [GDK_AXIS_YTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt Y");
223 label_atoms [GDK_AXIS_WHEEL] = gdk_x11_get_xatom_by_name_for_display (display, "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, 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
250 static void
translate_device_classes(GdkDisplay * display,GdkDevice * device,XIAnyClassInfo ** classes,guint n_classes)251 translate_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_info->label,
276 valuator_info->min,
277 valuator_info->max,
278 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 scroll_info->number,
302 direction,
303 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
316 static gboolean
is_touch_device(XIAnyClassInfo ** classes,guint n_classes,GdkInputSource * device_type,int * num_touches)317 is_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
351 static gboolean
has_abs_axes(GdkDisplay * display,XIAnyClassInfo ** classes,guint n_classes)352 has_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, "Abs X");
361 abs_y = gdk_x11_get_xatom_by_name_for_display (display, "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
384 static gboolean
get_device_ids(GdkDisplay * display,XIDeviceInfo * info,char ** vendor_id,char ** product_id)385 get_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 info->deviceid, prop,
407 0, 2, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
408 (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 ("%.4x", data[0]);
416 if (product_id)
417 *product_id = g_strdup_printf ("%.4x", data[1]);
418
419 XFree (data);
420
421 return TRUE;
422 }
423
424 static gboolean
has_bool_prop(GdkDisplay * display,XIDeviceInfo * info,const char * prop_name)425 has_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 info->deviceid,
438 gdk_x11_get_xatom_by_name_for_display (display, prop_name),
439 0, 1, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
440 (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
451 static gboolean
is_touchpad_device(GdkDisplay * display,XIDeviceInfo * info)452 is_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, "libinput Tapping Enabled") ||
463 has_bool_prop (display, info, "Synaptics Off") ||
464 has_bool_prop (display, info, "Raw Touch Passthrough");
465 }
466
467 static GdkDevice *
create_device(GdkX11DeviceManagerXI2 * device_manager,GdkDisplay * display,XIDeviceInfo * dev)468 create_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, dev))
482 input_source = GDK_SOURCE_TOUCHPAD;
483 else if (dev->use == XISlavePointer &&
484 is_touch_device (dev->classes, dev->num_classes, &touch_source, &num_touches))
485 input_source = touch_source;
486 else
487 {
488 char *tmp_name;
489
490 tmp_name = g_ascii_strdown (dev->name, -1);
491
492 if (strstr (tmp_name, " pad"))
493 input_source = GDK_SOURCE_TABLET_PAD;
494 else if (strstr (tmp_name, "wacom") ||
495 strstr (tmp_name, "pen") ||
496 strstr (tmp_name, "eraser"))
497 input_source = GDK_SOURCE_PEN;
498 else if (!strstr (tmp_name, "mouse") &&
499 !strstr (tmp_name, "pointer") &&
500 !strstr (tmp_name, "qemu usb tablet") &&
501 !strstr (tmp_name, "spice vdagent tablet") &&
502 !strstr (tmp_name, "virtualbox usb tablet") &&
503 has_abs_axes (display, dev->classes, dev->num_classes))
504 input_source = GDK_SOURCE_TOUCHSCREEN;
505 else if (strstr (tmp_name, "trackpoint") ||
506 strstr (tmp_name, "dualpoint stick"))
507 input_source = GDK_SOURCE_TRACKPOINT;
508 else
509 input_source = GDK_SOURCE_MOUSE;
510
511 g_free (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, dev, &vendor_id, &product_id);
545
546 device = g_object_new (GDK_TYPE_X11_DEVICE_XI2,
547 "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 ((GdkX11DeviceXI2 *) device, type);
557
558 translate_device_classes (display, device, dev->classes, dev->num_classes);
559 g_free (vendor_id);
560 g_free (product_id);
561
562 return device;
563 }
564
565 static void
ensure_seat_for_device_pair(GdkX11DeviceManagerXI2 * device_manager,GdkDevice * device1,GdkDevice * device2)566 ensure_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 (device1);
576
577 if (!seat)
578 {
579 if (gdk_device_get_source (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 (seat);
593 }
594 }
595
596 static GdkDevice *
add_device(GdkX11DeviceManagerXI2 * device_manager,XIDeviceInfo * dev,gboolean emit_signal)597 add_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 (device_manager->id_table,
608 GINT_TO_POINTER (dev->deviceid),
609 g_object_ref (device));
610
611 device_manager->devices = g_list_append (device_manager->devices, 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 (device_manager->id_table,
624 GINT_TO_POINTER (dev->attachment));
625
626 _gdk_device_set_associated_device (device, logical);
627 _gdk_device_add_physical_device (logical, device);
628
629 seat = gdk_device_get_seat (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 (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 (relative, device);
643 ensure_seat_for_device_pair (device_manager, device, relative);
644 }
645 }
646 }
647
648 return device;
649 }
650
651 static void
detach_from_seat(GdkDevice * device)652 detach_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_xi2) == GDK_X11_DEVICE_TYPE_LOGICAL)
661 gdk_display_remove_seat (gdk_device_get_display (device), seat);
662 else if (gdk_x11_device_xi2_get_device_type (device_xi2) == GDK_X11_DEVICE_TYPE_PHYSICAL)
663 gdk_seat_default_remove_physical_device (GDK_SEAT_DEFAULT (seat), device);
664 }
665
666 static void
remove_device(GdkX11DeviceManagerXI2 * device_manager,int device_id)667 remove_device (GdkX11DeviceManagerXI2 *device_manager,
668 int device_id)
669 {
670 GdkDevice *device;
671
672 device = g_hash_table_lookup (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 (device_manager->id_table,
680 GINT_TO_POINTER (device_id));
681
682 device_manager->devices = g_list_remove (device_manager->devices, device);
683 g_object_run_dispose (G_OBJECT (device));
684 g_object_unref (device);
685 }
686 }
687
688 static void
relate_logical_devices(gpointer key,gpointer value,gpointer user_data)689 relate_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 (device_manager->id_table, key);
698 relative = g_hash_table_lookup (device_manager->id_table, value);
699
700 _gdk_device_set_associated_device (device, relative);
701 _gdk_device_set_associated_device (relative, device);
702 ensure_seat_for_device_pair (device_manager, device, relative);
703 }
704
705 static void
relate_physical_devices(gpointer key,gpointer value,gpointer user_data)706 relate_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 (device_manager->id_table, key);
716 logical = g_hash_table_lookup (device_manager->id_table, value);
717
718 _gdk_device_set_associated_device (physical, logical);
719 _gdk_device_add_physical_device (logical, physical);
720
721 seat = gdk_device_get_seat (logical);
722 gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), physical);
723 }
724
725 static void
gdk_x11_device_manager_xi2_constructed(GObject * object)726 gdk_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 (xdisplay, XIAllDevices, &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 (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 (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 (logical_devices, relate_logical_devices, object);
780 g_hash_table_destroy (logical_devices);
781
782 g_hash_table_foreach (physical_devices, relate_physical_devices, object);
783 g_hash_table_destroy (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);
797 }
798
799 static void
gdk_x11_device_manager_xi2_dispose(GObject * object)800 gdk_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 (device_manager->devices, g_object_unref);
807 device_manager->devices = NULL;
808
809 if (device_manager->id_table)
810 {
811 g_hash_table_destroy (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
818 static void
gdk_x11_device_manager_xi2_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)819 gdk_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
848 static void
gdk_x11_device_manager_xi2_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)849 gdk_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, device_manager->display);
862 break;
863 case PROP_OPCODE:
864 g_value_set_int (value, device_manager->opcode);
865 break;
866 case PROP_MAJOR:
867 g_value_set_int (value, device_manager->major);
868 break;
869 case PROP_MINOR:
870 g_value_set_int (value, device_manager->minor);
871 break;
872 default:
873 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
874 break;
875 }
876 }
877
878 static void
gdk_x11_device_manager_xi2_event_translator_init(GdkEventTranslatorIface * iface)879 gdk_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
887 static void
handle_hierarchy_changed(GdkX11DeviceManagerXI2 * device_manager,XIHierarchyEvent * ev)888 handle_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 (xdisplay, ev->info[i].deviceid, &ndevices);
906 gdk_x11_display_error_trap_pop_ignored (display);
907 if (info)
908 {
909 add_device (device_manager, &info[0], TRUE);
910 XIFreeDeviceInfo (info);
911 }
912 }
913 else if (ev->info[i].flags & XIDeviceDisabled)
914 remove_device (device_manager, 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 (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 (physical);
928 gdk_seat_default_remove_physical_device (GDK_SEAT_DEFAULT (seat), 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 (xdisplay, ev->info[i].deviceid, &ndevices);
935 gdk_x11_display_error_trap_pop_ignored (display);
936 if (info)
937 {
938 logical = g_hash_table_lookup (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 (physical, logical);
946 _gdk_device_add_physical_device (logical, physical);
947
948 seat = gdk_device_get_seat (logical);
949 gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), physical);
950 }
951 }
952 }
953 }
954 }
955
956 static void
handle_device_changed(GdkX11DeviceManagerXI2 * device_manager,XIDeviceChangedEvent * ev)957 handle_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 (device_manager->id_table,
965 GUINT_TO_POINTER (ev->deviceid));
966 source_device = g_hash_table_lookup (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 ((GdkX11DeviceXI2 *) device);
973 gdk_x11_device_xi2_store_axes (GDK_X11_DEVICE_XI2 (device), NULL, 0);
974 translate_device_classes (display, device, ev->classes, ev->num_classes);
975
976 g_signal_emit_by_name (G_OBJECT (device), "changed");
977 }
978
979 if (source_device)
980 _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
981 }
982
983 static gboolean
device_get_tool_serial_and_id(GdkDevice * device,guint * serial_id,guint * id)984 device_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 gdk_x11_device_get_id (device),
1000 gdk_x11_get_xatom_by_name_for_display (display, "Wacom Serial IDs"),
1001 0, 5, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
1002 (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
1021 static GdkDeviceToolType
device_get_tool_type(GdkDevice * device)1022 device_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 gdk_x11_device_get_id (device),
1038 gdk_x11_get_xatom_by_name_for_display (display, "Wacom Tool Type"),
1039 0, 1, False, XA_ATOM, &type, &format, &nitems, &bytes_after,
1040 (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
1081 static void
handle_property_change(GdkX11DeviceManagerXI2 * device_manager,XIPropertyEvent * ev)1082 handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
1083 XIPropertyEvent *ev)
1084 {
1085 GdkDevice *device;
1086
1087 device = g_hash_table_lookup (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 (gdk_device_get_display (device), "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, &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_id, tool_id, tool_type);
1108
1109 if (!tool && serial_id > 0)
1110 {
1111 tool = gdk_device_tool_new (serial_id, tool_id, tool_type, 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
1121 static GdkCrossingMode
translate_crossing_mode(int mode)1122 translate_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
1142 static GdkNotifyType
translate_notify_type(int detail)1143 translate_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
1163 static void
set_user_time(GdkEvent * event)1164 set_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, time);
1179 }
1180
1181 static double *
translate_axes(GdkDevice * device,double x,double y,GdkSurface * surface,XIValuatorState * valuators)1182 translate_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, 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, i, val, &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
1229 static gboolean
get_event_surface(GdkEventTranslator * translator,XIEvent * ev,GdkSurface ** surface_p)1230 get_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, 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 case XI_Enter:
1279 case XI_Leave:
1280 case XI_FocusIn:
1281 case XI_FocusOut:
1282 {
1283 XIEnterEvent *xev = (XIEnterEvent *) ev;
1284
1285 surface = gdk_x11_surface_lookup_for_display (display, xev->event);
1286 }
1287 break;
1288 default:
1289 should_have_window = FALSE;
1290 break;
1291 }
1292
1293 *surface_p = surface;
1294
1295 if (should_have_window && !surface)
1296 return FALSE;
1297
1298 return TRUE;
1299 }
1300
1301 static gboolean
scroll_valuators_changed(GdkX11DeviceXI2 * device,XIValuatorState * valuators,double * dx,double * dy)1302 scroll_valuators_changed (GdkX11DeviceXI2 *device,
1303 XIValuatorState *valuators,
1304 double *dx,
1305 double *dy)
1306 {
1307 gboolean has_scroll_valuators = FALSE;
1308 GdkScrollDirection direction;
1309 guint n_axes, i, n_val;
1310 double *vals;
1311
1312 n_axes = gdk_device_get_n_axes (GDK_DEVICE (device));
1313 vals = valuators->values;
1314 *dx = *dy = 0;
1315 n_val = 0;
1316
1317 for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
1318 {
1319 double delta;
1320
1321 if (!XIMaskIsSet (valuators->mask, i))
1322 continue;
1323
1324 if (_gdk_x11_device_xi2_get_scroll_delta (device, i, vals[n_val],
1325 &direction, &delta))
1326 {
1327 has_scroll_valuators = TRUE;
1328
1329 if (direction == GDK_SCROLL_UP ||
1330 direction == GDK_SCROLL_DOWN)
1331 *dy = delta;
1332 else
1333 *dx = delta;
1334 }
1335
1336 n_val++;
1337 }
1338
1339 return has_scroll_valuators;
1340 }
1341
1342 /* We only care about focus events that indicate that _this_
1343 * surface (not an ancestor or child) got or lost the focus
1344 */
1345 static void
_gdk_device_manager_xi2_handle_focus(GdkSurface * surface,Window original,GdkDevice * device,GdkDevice * source_device,gboolean focus_in,int detail,int mode)1346 _gdk_device_manager_xi2_handle_focus (GdkSurface *surface,
1347 Window original,
1348 GdkDevice *device,
1349 GdkDevice *source_device,
1350 gboolean focus_in,
1351 int detail,
1352 int mode)
1353 {
1354 GdkToplevelX11 *toplevel;
1355 GdkX11Screen *x11_screen;
1356 gboolean had_focus;
1357
1358 g_return_if_fail (GDK_IS_SURFACE (surface));
1359 g_return_if_fail (GDK_IS_DEVICE (device));
1360 g_return_if_fail (source_device == NULL || GDK_IS_DEVICE (source_device));
1361
1362 GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS,
1363 g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
1364 GDK_SURFACE_XID (surface),
1365 notify_details[detail],
1366 notify_modes[mode]));
1367
1368 toplevel = _gdk_x11_surface_get_toplevel (surface);
1369
1370 if (!toplevel)
1371 return;
1372
1373 if (toplevel->focus_window == original)
1374 return;
1375
1376 had_focus = HAS_FOCUS (toplevel);
1377 x11_screen = GDK_X11_SCREEN (GDK_SURFACE_SCREEN (surface));
1378
1379 switch (detail)
1380 {
1381 case NotifyAncestor:
1382 case NotifyVirtual:
1383 /* When the focus moves from an ancestor of the window to
1384 * the window or a descendent of the window, *and* the
1385 * pointer is inside the window, then we were previously
1386 * receiving keystroke events in the has_pointer_focus
1387 * case and are now receiving them in the
1388 * has_focus_window case.
1389 */
1390 if (toplevel->has_pointer &&
1391 !x11_screen->wmspec_check_window &&
1392 mode != NotifyGrab &&
1393 mode != XINotifyPassiveGrab &&
1394 mode != XINotifyPassiveUngrab &&
1395 mode != NotifyUngrab)
1396 toplevel->has_pointer_focus = (focus_in) ? FALSE : TRUE;
1397 G_GNUC_FALLTHROUGH;
1398
1399 case NotifyNonlinear:
1400 case NotifyNonlinearVirtual:
1401 if (mode != NotifyGrab &&
1402 mode != XINotifyPassiveGrab &&
1403 mode != XINotifyPassiveUngrab &&
1404 mode != NotifyUngrab)
1405 toplevel->has_focus_window = (focus_in) ? TRUE : FALSE;
1406 /* We pretend that the focus moves to the grab
1407 * window, so we pay attention to NotifyGrab
1408 * NotifyUngrab, and ignore NotifyWhileGrabbed
1409 */
1410 if (mode != NotifyWhileGrabbed)
1411 toplevel->has_focus = (focus_in) ? TRUE : FALSE;
1412 break;
1413 case NotifyPointer:
1414 /* The X server sends NotifyPointer/NotifyGrab,
1415 * but the pointer focus is ignored while a
1416 * grab is in effect
1417 */
1418 if (!x11_screen->wmspec_check_window &&
1419 mode != NotifyGrab &&
1420 mode != XINotifyPassiveGrab &&
1421 mode != XINotifyPassiveUngrab &&
1422 mode != NotifyUngrab)
1423 toplevel->has_pointer_focus = (focus_in) ? TRUE : FALSE;
1424 break;
1425 case NotifyInferior:
1426 case NotifyPointerRoot:
1427 case NotifyDetailNone:
1428 default:
1429 break;
1430 }
1431
1432 if (HAS_FOCUS (toplevel) != had_focus)
1433 {
1434 GdkEvent *event;
1435
1436 event = gdk_focus_event_new (surface, device, focus_in);
1437 gdk_display_put_event (gdk_surface_get_display (surface), event);
1438 gdk_event_unref (event);
1439 }
1440 }
1441
1442 static GdkEvent *
gdk_x11_device_manager_xi2_translate_event(GdkEventTranslator * translator,GdkDisplay * display,const XEvent * xevent)1443 gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
1444 GdkDisplay *display,
1445 const XEvent *xevent)
1446 {
1447 GdkX11DeviceManagerXI2 *device_manager;
1448 const XGenericEventCookie *cookie;
1449 GdkDevice *device, *source_device;
1450 GdkSurface *surface;
1451 GdkX11Surface *impl;
1452 int scale;
1453 XIEvent *ev;
1454 GdkEvent *event;
1455
1456 event = NULL;
1457
1458 device_manager = (GdkX11DeviceManagerXI2 *) translator;
1459 cookie = &xevent->xcookie;
1460
1461 if (xevent->type != GenericEvent ||
1462 cookie->extension != device_manager->opcode)
1463 return event;
1464
1465 ev = (XIEvent *) cookie->data;
1466
1467 if (!ev)
1468 return NULL;
1469
1470 if (!get_event_surface (translator, ev, &surface))
1471 return NULL;
1472
1473 if (surface && GDK_SURFACE_DESTROYED (surface))
1474 return NULL;
1475
1476 scale = 1;
1477 if (surface)
1478 {
1479 impl = GDK_X11_SURFACE (surface);
1480 scale = impl->surface_scale;
1481 }
1482
1483 if (ev->evtype == XI_Motion ||
1484 ev->evtype == XI_ButtonRelease)
1485 {
1486 if (_gdk_x11_moveresize_handle_event (xevent))
1487 return NULL;
1488 }
1489
1490 switch (ev->evtype)
1491 {
1492 case XI_HierarchyChanged:
1493 handle_hierarchy_changed (device_manager,
1494 (XIHierarchyEvent *) ev);
1495 break;
1496 case XI_DeviceChanged:
1497 handle_device_changed (device_manager,
1498 (XIDeviceChangedEvent *) ev);
1499 break;
1500 case XI_PropertyEvent:
1501 handle_property_change (device_manager,
1502 (XIPropertyEvent *) ev);
1503 break;
1504 case XI_KeyPress:
1505 case XI_KeyRelease:
1506 {
1507 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1508 GdkKeymap *keymap = gdk_display_get_keymap (display);
1509 GdkModifierType consumed, state, orig_state;
1510 int layout, level;
1511 guint keyval;
1512 GdkTranslatedKey translated;
1513 GdkTranslatedKey no_lock;
1514
1515 GDK_DISPLAY_NOTE (display, EVENTS,
1516 g_message ("key %s:\twindow %ld\n"
1517 "\tdevice:%u\n"
1518 "\tsource device:%u\n"
1519 "\tkey number: %u\n",
1520 (ev->evtype == XI_KeyPress) ? "press" : "release",
1521 xev->event,
1522 xev->deviceid,
1523 xev->sourceid,
1524 xev->detail));
1525
1526 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1527
1528 device = g_hash_table_lookup (device_manager->id_table,
1529 GUINT_TO_POINTER (xev->deviceid));
1530
1531 source_device = g_hash_table_lookup (device_manager->id_table,
1532 GUINT_TO_POINTER (xev->sourceid));
1533
1534 keyval = GDK_KEY_VoidSymbol;
1535
1536 gdk_keymap_translate_keyboard_state (keymap,
1537 xev->detail,
1538 state,
1539 xev->group.effective,
1540 &keyval,
1541 &layout, &level, &consumed);
1542 orig_state = state;
1543 state &= ~consumed;
1544 _gdk_x11_keymap_add_virt_mods (keymap, &state);
1545 state |= orig_state;
1546
1547 translated.keyval = keyval;
1548 translated.consumed = consumed;
1549 translated.layout = layout;
1550 translated.level = level;
1551
1552 if (orig_state & GDK_LOCK_MASK)
1553 {
1554 orig_state &= ~GDK_LOCK_MASK;
1555
1556 gdk_keymap_translate_keyboard_state (keymap,
1557 xev->detail,
1558 orig_state,
1559 xev->group.effective,
1560 &keyval,
1561 &layout, &level, &consumed);
1562
1563 no_lock.keyval = keyval;
1564 no_lock.consumed = consumed;
1565 no_lock.layout = layout;
1566 no_lock.level = level;
1567 }
1568 else
1569 {
1570 no_lock = translated;
1571 }
1572 event = gdk_key_event_new (xev->evtype == XI_KeyPress
1573 ? GDK_KEY_PRESS
1574 : GDK_KEY_RELEASE,
1575 surface,
1576 device,
1577 xev->time,
1578 xev->detail,
1579 state,
1580 gdk_x11_keymap_key_is_modifier (keymap, xev->detail),
1581 &translated,
1582 &no_lock);
1583
1584 if (ev->evtype == XI_KeyPress)
1585 set_user_time (event);
1586
1587 /* FIXME: emulate autorepeat on key
1588 * release? XI2 seems attached to Xkb.
1589 */
1590 }
1591
1592 break;
1593 case XI_ButtonPress:
1594 case XI_ButtonRelease:
1595 {
1596 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1597
1598 GDK_DISPLAY_NOTE (display, EVENTS,
1599 g_message ("button %s:\twindow %ld\n"
1600 "\tdevice:%u\n"
1601 "\tsource device:%u\n"
1602 "\tbutton number: %u\n"
1603 "\tx,y: %.2f %.2f",
1604 (ev->evtype == XI_ButtonPress) ? "press" : "release",
1605 xev->event,
1606 xev->deviceid,
1607 xev->sourceid,
1608 xev->detail,
1609 xev->event_x, xev->event_y));
1610
1611 #ifdef XINPUT_2_2
1612 if (xev->flags & XIPointerEmulated)
1613 return FALSE;
1614 #endif
1615
1616 if (ev->evtype == XI_ButtonRelease &&
1617 (xev->detail >= 4 && xev->detail <= 7))
1618 return FALSE;
1619 else if (ev->evtype == XI_ButtonPress &&
1620 (xev->detail >= 4 && xev->detail <= 7))
1621 {
1622 GdkScrollDirection direction;
1623
1624 /* Button presses of button 4-7 are scroll events */
1625
1626 if (xev->detail == 4)
1627 direction = GDK_SCROLL_UP;
1628 else if (xev->detail == 5)
1629 direction = GDK_SCROLL_DOWN;
1630 else if (xev->detail == 6)
1631 direction = GDK_SCROLL_LEFT;
1632 else
1633 direction = GDK_SCROLL_RIGHT;
1634
1635 device = g_hash_table_lookup (device_manager->id_table,
1636 GUINT_TO_POINTER (xev->deviceid));
1637
1638 source_device = g_hash_table_lookup (device_manager->id_table,
1639 GUINT_TO_POINTER (xev->sourceid));
1640
1641 event = gdk_scroll_event_new_discrete (surface,
1642 source_device,
1643 NULL,
1644 xev->time,
1645 _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
1646 direction,
1647 FALSE);
1648
1649 }
1650 else
1651 {
1652 double x, y;
1653 double *axes;
1654
1655 device = g_hash_table_lookup (device_manager->id_table,
1656 GUINT_TO_POINTER (xev->deviceid));
1657
1658 source_device = g_hash_table_lookup (device_manager->id_table,
1659 GUINT_TO_POINTER (xev->sourceid));
1660
1661 axes = translate_axes (device,
1662 (double) xev->event_x / scale,
1663 (double) xev->event_y / scale,
1664 surface,
1665 &xev->valuators);
1666
1667 x = (double) xev->event_x / scale;
1668 y = (double) xev->event_y / scale;
1669
1670 event = gdk_button_event_new (ev->evtype == XI_ButtonPress
1671 ? GDK_BUTTON_PRESS
1672 : GDK_BUTTON_RELEASE,
1673 surface,
1674 device,
1675 source_device->last_tool,
1676 xev->time,
1677 _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
1678 xev->detail,
1679 x, y,
1680 axes);
1681 }
1682
1683 if (ev->evtype == XI_ButtonPress)
1684 set_user_time (event);
1685
1686 break;
1687 }
1688
1689 case XI_Motion:
1690 {
1691 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1692 double delta_x, delta_y;
1693
1694 double x, y;
1695 double *axes;
1696
1697 #ifdef XINPUT_2_2
1698 if (xev->flags & XIPointerEmulated)
1699 return FALSE;
1700 #endif
1701
1702 source_device = g_hash_table_lookup (device_manager->id_table,
1703 GUINT_TO_POINTER (xev->sourceid));
1704 device = g_hash_table_lookup (device_manager->id_table,
1705 GUINT_TO_POINTER (xev->deviceid));
1706
1707 /* When scrolling, X might send events twice here; once with both the
1708 * device and the source device set to the physical device, and once
1709 * with the device set to the logical device.
1710 *
1711 * Since we are only interested in the latter, and
1712 * scroll_valuators_changed() updates the valuator cache for the
1713 * source device, we need to explicitly ignore the first event in
1714 * order to get the correct delta for the second.
1715 */
1716 if (gdk_x11_device_xi2_get_device_type ((GdkX11DeviceXI2 *) device) != GDK_X11_DEVICE_TYPE_PHYSICAL &&
1717 scroll_valuators_changed (GDK_X11_DEVICE_XI2 (source_device),
1718 &xev->valuators, &delta_x, &delta_y))
1719 {
1720 GdkModifierType state;
1721
1722 GDK_DISPLAY_NOTE (display, EVENTS,
1723 g_message ("smooth scroll: \n\tdevice: %u\n\tsource device: %u\n\twindow %ld\n\tdeltas: %f %f",
1724 xev->deviceid, xev->sourceid,
1725 xev->event, delta_x, delta_y));
1726
1727 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1728
1729 if (gdk_device_get_source (source_device) != GDK_SOURCE_TOUCHPAD &&
1730 ((delta_x == 0.0 && ABS (delta_y) == 1.0) ||
1731 (ABS (delta_x) == 1.0 && delta_y == 0.0)))
1732 {
1733 GdkScrollDirection direction;
1734
1735 if (delta_x > 0)
1736 direction = GDK_SCROLL_RIGHT;
1737 else if (delta_x < 0)
1738 direction = GDK_SCROLL_LEFT;
1739 else if (delta_y > 0)
1740 direction = GDK_SCROLL_DOWN;
1741 else
1742 direction = GDK_SCROLL_UP;
1743
1744 event = gdk_scroll_event_new_discrete (surface,
1745 device,
1746 NULL,
1747 xev->time,
1748 state,
1749 direction,
1750 FALSE);
1751 }
1752 else
1753 {
1754 event = gdk_scroll_event_new (surface,
1755 device,
1756 NULL,
1757 xev->time,
1758 state,
1759 delta_x,
1760 delta_y,
1761 delta_x == 0.0 && delta_y == 0.0);
1762 }
1763 break;
1764 }
1765
1766 axes = translate_axes (device,
1767 (double) xev->event_x / scale,
1768 (double) xev->event_y / scale,
1769 surface,
1770 &xev->valuators);
1771
1772 x = (double) xev->event_x / scale;
1773 y = (double) xev->event_y / scale;
1774
1775 event = gdk_motion_event_new (surface,
1776 device,
1777 source_device->last_tool,
1778 xev->time,
1779 _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
1780 x, y,
1781 axes);
1782
1783 }
1784 break;
1785
1786 #ifdef XINPUT_2_2
1787 case XI_TouchBegin:
1788 case XI_TouchEnd:
1789 {
1790 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1791 GdkModifierType state;
1792
1793 double x, y;
1794 double *axes;
1795
1796 GDK_DISPLAY_NOTE (display, EVENTS,
1797 g_message ("touch %s:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %s",
1798 ev->evtype == XI_TouchBegin ? "begin" : "end",
1799 xev->event,
1800 xev->detail,
1801 xev->flags & XITouchEmulatingPointer ? "true" : "false"));
1802
1803 device = g_hash_table_lookup (device_manager->id_table,
1804 GUINT_TO_POINTER (xev->deviceid));
1805
1806 source_device = g_hash_table_lookup (device_manager->id_table,
1807 GUINT_TO_POINTER (xev->sourceid));
1808
1809 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1810 if (ev->evtype == XI_TouchBegin)
1811 state |= GDK_BUTTON1_MASK;
1812
1813 axes = translate_axes (device,
1814 (double) xev->event_x / scale,
1815 (double) xev->event_y / scale,
1816 surface,
1817 &xev->valuators);
1818
1819 x = (double) xev->event_x / scale;
1820 y = (double) xev->event_y / scale;
1821
1822 event = gdk_touch_event_new (ev->evtype == XI_TouchBegin
1823 ? GDK_TOUCH_BEGIN
1824 : GDK_TOUCH_END,
1825 GUINT_TO_POINTER (xev->detail),
1826 surface,
1827 device,
1828 xev->time,
1829 state,
1830 x, y,
1831 axes,
1832 xev->flags & XITouchEmulatingPointer);
1833
1834 if (ev->evtype == XI_TouchBegin)
1835 set_user_time (event);
1836 }
1837 break;
1838
1839 case XI_TouchUpdate:
1840 {
1841 XIDeviceEvent *xev = (XIDeviceEvent *) ev;
1842 GdkModifierType state;
1843
1844 double x, y;
1845 double *axes;
1846
1847 GDK_DISPLAY_NOTE (display, EVENTS,
1848 g_message ("touch update:\twindow %ld\n\ttouch id: %u\n\tpointer emulating: %s",
1849 xev->event,
1850 xev->detail,
1851 xev->flags & XITouchEmulatingPointer ? "true" : "false"));
1852
1853 device = g_hash_table_lookup (device_manager->id_table,
1854 GINT_TO_POINTER (xev->deviceid));
1855
1856 source_device = g_hash_table_lookup (device_manager->id_table,
1857 GUINT_TO_POINTER (xev->sourceid));
1858
1859 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1860 state |= GDK_BUTTON1_MASK;
1861
1862 axes = translate_axes (device,
1863 (double) xev->event_x / scale,
1864 (double) xev->event_y / scale,
1865 surface,
1866 &xev->valuators);
1867
1868 x = (double) xev->event_x / scale;
1869 y = (double) xev->event_y / scale;
1870
1871 event = gdk_touch_event_new (GDK_TOUCH_UPDATE,
1872 GUINT_TO_POINTER (xev->detail),
1873 surface,
1874 device,
1875 xev->time,
1876 state,
1877 x, y,
1878 axes,
1879 xev->flags & XITouchEmulatingPointer);
1880 }
1881 break;
1882 #endif /* XINPUT_2_2 */
1883
1884 case XI_Enter:
1885 case XI_Leave:
1886 {
1887 XIEnterEvent *xev = (XIEnterEvent *) ev;
1888 GdkModifierType state;
1889
1890 GDK_DISPLAY_NOTE (display, EVENTS,
1891 g_message ("%s notify:\twindow %ld\n\tsubwindow:%ld\n"
1892 "\tdevice: %u\n\tsource device: %u\n"
1893 "\tnotify type: %u\n\tcrossing mode: %u",
1894 (ev->evtype == XI_Enter) ? "enter" : "leave",
1895 xev->event, xev->child,
1896 xev->deviceid, xev->sourceid,
1897 xev->detail, xev->mode));
1898
1899 device = g_hash_table_lookup (device_manager->id_table,
1900 GINT_TO_POINTER (xev->deviceid));
1901
1902 source_device = g_hash_table_lookup (device_manager->id_table,
1903 GUINT_TO_POINTER (xev->sourceid));
1904
1905 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
1906
1907 /* Ignore normal crossing events while there is an implicit grab.
1908 * We will receive a crossing event with one of the other details if
1909 * the implicit grab were finished (eg. releasing the button outside
1910 * the window triggers a XINotifyUngrab leave).
1911 */
1912 if (xev->mode == XINotifyNormal &&
1913 (state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
1914 GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)))
1915 break;
1916
1917 if (ev->evtype == XI_Enter &&
1918 xev->detail != XINotifyInferior && xev->mode != XINotifyPassiveUngrab &&
1919 GDK_IS_TOPLEVEL (surface))
1920 {
1921 if (gdk_x11_device_xi2_get_device_type ((GdkX11DeviceXI2 *) device) != GDK_X11_DEVICE_TYPE_LOGICAL)
1922 _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
1923 else
1924 {
1925 GList *physical_devices, *l;
1926
1927 physical_devices = gdk_device_list_physical_devices (source_device);
1928
1929 for (l = physical_devices; l; l = l->next)
1930 _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (l->data));
1931
1932 g_list_free (physical_devices);
1933 }
1934 }
1935
1936 event = gdk_crossing_event_new (ev->evtype == XI_Enter
1937 ? GDK_ENTER_NOTIFY
1938 : GDK_LEAVE_NOTIFY,
1939 surface,
1940 device,
1941 xev->time,
1942 state,
1943 (double) xev->event_x / scale,
1944 (double) xev->event_y / scale,
1945 translate_crossing_mode (xev->mode),
1946 translate_notify_type (xev->detail));
1947 }
1948 break;
1949 case XI_FocusIn:
1950 case XI_FocusOut:
1951 {
1952 if (surface)
1953 {
1954 XIEnterEvent *xev = (XIEnterEvent *) ev;
1955
1956 device = g_hash_table_lookup (device_manager->id_table,
1957 GINT_TO_POINTER (xev->deviceid));
1958
1959 source_device = g_hash_table_lookup (device_manager->id_table,
1960 GUINT_TO_POINTER (xev->sourceid));
1961
1962 _gdk_device_manager_xi2_handle_focus (surface,
1963 xev->event,
1964 device,
1965 source_device,
1966 (ev->evtype == XI_FocusIn) ? TRUE : FALSE,
1967 xev->detail,
1968 xev->mode);
1969 }
1970 }
1971 break;
1972 default:
1973 break;
1974 }
1975
1976 return event;
1977 }
1978
1979 static GdkEventMask
gdk_x11_device_manager_xi2_get_handled_events(GdkEventTranslator * translator)1980 gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
1981 {
1982 return (GDK_KEY_PRESS_MASK |
1983 GDK_KEY_RELEASE_MASK |
1984 GDK_BUTTON_PRESS_MASK |
1985 GDK_BUTTON_RELEASE_MASK |
1986 GDK_SCROLL_MASK |
1987 GDK_ENTER_NOTIFY_MASK |
1988 GDK_LEAVE_NOTIFY_MASK |
1989 GDK_POINTER_MOTION_MASK |
1990 GDK_BUTTON1_MOTION_MASK |
1991 GDK_BUTTON2_MOTION_MASK |
1992 GDK_BUTTON3_MOTION_MASK |
1993 GDK_BUTTON_MOTION_MASK |
1994 GDK_FOCUS_CHANGE_MASK |
1995 GDK_TOUCH_MASK);
1996 }
1997
1998 static void
gdk_x11_device_manager_xi2_select_surface_events(GdkEventTranslator * translator,Window window,GdkEventMask evmask)1999 gdk_x11_device_manager_xi2_select_surface_events (GdkEventTranslator *translator,
2000 Window window,
2001 GdkEventMask evmask)
2002 {
2003 XIEventMask event_mask;
2004
2005 event_mask.deviceid = XIAllMasterDevices;
2006 event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (GDK_X11_DEVICE_MANAGER_XI2 (translator),
2007 evmask,
2008 &event_mask.mask_len);
2009
2010 _gdk_x11_device_manager_xi2_select_events (GDK_X11_DEVICE_MANAGER_XI2 (translator), window, &event_mask);
2011 g_free (event_mask.mask);
2012 }
2013
2014 static GdkSurface *
gdk_x11_device_manager_xi2_get_surface(GdkEventTranslator * translator,const XEvent * xevent)2015 gdk_x11_device_manager_xi2_get_surface (GdkEventTranslator *translator,
2016 const XEvent *xevent)
2017 {
2018 GdkX11DeviceManagerXI2 *device_manager;
2019 XIEvent *ev;
2020 GdkSurface *surface = NULL;
2021
2022 device_manager = (GdkX11DeviceManagerXI2 *) translator;
2023
2024 if (xevent->type != GenericEvent ||
2025 xevent->xcookie.extension != device_manager->opcode)
2026 return NULL;
2027
2028 ev = (XIEvent *) xevent->xcookie.data;
2029 if (!ev)
2030 return NULL;
2031
2032 get_event_surface (translator, ev, &surface);
2033 return surface;
2034 }
2035
2036 GdkDevice *
_gdk_x11_device_manager_xi2_lookup(GdkX11DeviceManagerXI2 * device_manager_xi2,int device_id)2037 _gdk_x11_device_manager_xi2_lookup (GdkX11DeviceManagerXI2 *device_manager_xi2,
2038 int device_id)
2039 {
2040 return g_hash_table_lookup (device_manager_xi2->id_table,
2041 GINT_TO_POINTER (device_id));
2042 }
2043