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 "gdkdevice-wayland-private.h" |
21 | |
22 | #include "gdkclipboard-wayland.h" |
23 | #include "gdkclipboardprivate.h" |
24 | #include "gdkcursorprivate.h" |
25 | #include "gdkdeviceprivate.h" |
26 | #include "gdkdevicepadprivate.h" |
27 | #include "gdkdevicetoolprivate.h" |
28 | #include "gdkdropprivate.h" |
29 | #include "gdkeventsprivate.h" |
30 | #include "gdkkeysprivate.h" |
31 | #include "gdkkeysyms.h" |
32 | #include "gdkprimary-wayland.h" |
33 | #include "gdkprivate-wayland.h" |
34 | #include "gdkseat-wayland.h" |
35 | #include "gdkseatprivate.h" |
36 | #include "gdksurfaceprivate.h" |
37 | #include "gdktypes.h" |
38 | #include "gdkwayland.h" |
39 | #include "gdk-private.h" |
40 | |
41 | #include "pointer-gestures-unstable-v1-client-protocol.h" |
42 | #include "tablet-unstable-v2-client-protocol.h" |
43 | |
44 | #include <xkbcommon/xkbcommon.h> |
45 | |
46 | #include <errno.h> |
47 | #include <fcntl.h> |
48 | #include <string.h> |
49 | #include <unistd.h> |
50 | #include <sys/time.h> |
51 | #include <sys/mman.h> |
52 | #if defined(HAVE_DEV_EVDEV_INPUT_H) |
53 | #include <dev/evdev/input.h> |
54 | #elif defined(HAVE_LINUX_INPUT_H) |
55 | #include <linux/input.h> |
56 | #endif |
57 | |
58 | /** |
59 | * GdkWaylandDevice: |
60 | * |
61 | * The Wayland implementation of `GdkDevice`. |
62 | * |
63 | * Beyond the regular [class@Gdk.Device] API, the Wayland implementation |
64 | * provides access to Wayland objects such as the `wl_seat` with |
65 | * [method@GdkWayland.WaylandDevice.get_wl_seat], the `wl_keyboard` with |
66 | * [method@GdkWayland.WaylandDevice.get_wl_keyboard] and the `wl_pointer` with |
67 | * [method@GdkWayland.WaylandDevice.get_wl_pointer]. |
68 | */ |
69 | |
70 | /** |
71 | * GdkWaylandSeat: |
72 | * |
73 | * The Wayland implementation of `GdkSeat`. |
74 | * |
75 | * Beyond the regular [class@Gdk.Seat] API, the Wayland implementation |
76 | * provides access to the Wayland `wl_seat` object with |
77 | * [method@GdkWayland.WaylandSeat.get_wl_seat]. |
78 | */ |
79 | |
80 | #define BUTTON_BASE (BTN_LEFT - 1) /* Used to translate to 1-indexed buttons */ |
81 | |
82 | #ifndef BTN_STYLUS3 |
83 | #define BTN_STYLUS3 0x149 /* Linux 4.15 */ |
84 | #endif |
85 | |
86 | #define ALL_BUTTONS_MASK (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | \ |
87 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK | \ |
88 | GDK_BUTTON5_MASK) |
89 | |
90 | #define GDK_SEAT_NOTE(seat,type,action) GDK_DISPLAY_NOTE(gdk_seat_get_display (GDK_SEAT (seat)),type,action) |
91 | |
92 | typedef struct _GdkWaylandDevicePad GdkWaylandDevicePad; |
93 | typedef struct _GdkWaylandDevicePadClass GdkWaylandDevicePadClass; |
94 | |
95 | typedef struct _GdkWaylandTouchData GdkWaylandTouchData; |
96 | typedef struct _GdkWaylandPointerFrameData GdkWaylandPointerFrameData; |
97 | typedef struct _GdkWaylandPointerData GdkWaylandPointerData; |
98 | typedef struct _GdkWaylandTabletData GdkWaylandTabletData; |
99 | typedef struct _GdkWaylandTabletToolData GdkWaylandTabletToolData; |
100 | typedef struct _GdkWaylandTabletPadGroupData GdkWaylandTabletPadGroupData; |
101 | typedef struct _GdkWaylandTabletPadData GdkWaylandTabletPadData; |
102 | |
103 | struct _GdkWaylandTouchData |
104 | { |
105 | uint32_t id; |
106 | double x; |
107 | double y; |
108 | GdkSurface *surface; |
109 | uint32_t touch_down_serial; |
110 | guint initial_touch : 1; |
111 | }; |
112 | |
113 | struct _GdkWaylandPointerFrameData |
114 | { |
115 | GdkEvent *event; |
116 | |
117 | /* Specific to the scroll event */ |
118 | double delta_x, delta_y; |
119 | int32_t discrete_x, discrete_y; |
120 | gint8 is_scroll_stop; |
121 | enum wl_pointer_axis_source source; |
122 | }; |
123 | |
124 | struct _GdkWaylandPointerData { |
125 | GdkSurface *focus; |
126 | |
127 | double surface_x, surface_y; |
128 | |
129 | GdkModifierType button_modifiers; |
130 | |
131 | uint32_t time; |
132 | uint32_t enter_serial; |
133 | uint32_t press_serial; |
134 | |
135 | GdkSurface *grab_surface; |
136 | uint32_t grab_time; |
137 | |
138 | struct wl_surface *pointer_surface; |
139 | guint cursor_is_default: 1; |
140 | GdkCursor *cursor; |
141 | guint cursor_timeout_id; |
142 | guint cursor_image_index; |
143 | guint cursor_image_delay; |
144 | guint touchpad_event_sequence; |
145 | |
146 | guint current_output_scale; |
147 | GSList *pointer_surface_outputs; |
148 | |
149 | /* Accumulated event data for a pointer frame */ |
150 | GdkWaylandPointerFrameData frame; |
151 | }; |
152 | |
153 | struct _GdkWaylandTabletToolData |
154 | { |
155 | GdkSeat *seat; |
156 | struct zwp_tablet_tool_v2 *wp_tablet_tool; |
157 | GdkAxisFlags axes; |
158 | GdkDeviceToolType type; |
159 | guint64 hardware_serial; |
160 | guint64 hardware_id_wacom; |
161 | |
162 | GdkDeviceTool *tool; |
163 | GdkWaylandTabletData *current_tablet; |
164 | }; |
165 | |
166 | struct _GdkWaylandTabletPadGroupData |
167 | { |
168 | GdkWaylandTabletPadData *pad; |
169 | struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group; |
170 | GList *rings; |
171 | GList *strips; |
172 | GList *buttons; |
173 | |
174 | guint mode_switch_serial; |
175 | guint n_modes; |
176 | guint current_mode; |
177 | |
178 | struct { |
179 | guint source; |
180 | gboolean is_stop; |
181 | double value; |
182 | } axis_tmp_info; |
183 | }; |
184 | |
185 | struct _GdkWaylandTabletPadData |
186 | { |
187 | GdkSeat *seat; |
188 | struct zwp_tablet_pad_v2 *wp_tablet_pad; |
189 | GdkDevice *device; |
190 | |
191 | GdkWaylandTabletData *current_tablet; |
192 | |
193 | guint enter_serial; |
194 | uint32_t n_buttons; |
195 | char *path; |
196 | |
197 | GList *rings; |
198 | GList *strips; |
199 | GList *mode_groups; |
200 | }; |
201 | |
202 | struct _GdkWaylandTabletData |
203 | { |
204 | struct zwp_tablet_v2 *wp_tablet; |
205 | char *name; |
206 | char *path; |
207 | uint32_t vid; |
208 | uint32_t pid; |
209 | |
210 | GdkDevice *logical_device; |
211 | GdkDevice *stylus_device; |
212 | GdkSeat *seat; |
213 | GdkWaylandPointerData pointer_info; |
214 | |
215 | GList *pads; |
216 | |
217 | GdkWaylandTabletToolData *current_tool; |
218 | |
219 | int axis_indices[GDK_AXIS_LAST]; |
220 | double axes[GDK_AXIS_LAST]; |
221 | }; |
222 | |
223 | struct _GdkWaylandSeat |
224 | { |
225 | GdkSeat parent_instance; |
226 | |
227 | guint32 id; |
228 | struct wl_seat *wl_seat; |
229 | struct wl_pointer *wl_pointer; |
230 | struct wl_keyboard *wl_keyboard; |
231 | struct wl_touch *wl_touch; |
232 | struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe; |
233 | struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch; |
234 | struct zwp_pointer_gesture_hold_v1 *wp_pointer_gesture_hold; |
235 | struct zwp_tablet_seat_v2 *wp_tablet_seat; |
236 | |
237 | GdkDisplay *display; |
238 | |
239 | GdkDevice *logical_pointer; |
240 | GdkDevice *logical_keyboard; |
241 | GdkDevice *pointer; |
242 | GdkDevice *wheel_scrolling; |
243 | GdkDevice *finger_scrolling; |
244 | GdkDevice *continuous_scrolling; |
245 | GdkDevice *keyboard; |
246 | GdkDevice *logical_touch; |
247 | GdkDevice *touch; |
248 | GdkCursor *cursor; |
249 | GdkKeymap *keymap; |
250 | |
251 | GHashTable *touches; |
252 | GList *tablets; |
253 | GList *tablet_tools; |
254 | GList *tablet_pads; |
255 | |
256 | GdkWaylandPointerData pointer_info; |
257 | GdkWaylandPointerData touch_info; |
258 | |
259 | GdkModifierType key_modifiers; |
260 | GdkSurface *keyboard_focus; |
261 | GdkSurface *grab_surface; |
262 | uint32_t grab_time; |
263 | gboolean have_server_repeat; |
264 | uint32_t server_repeat_rate; |
265 | uint32_t server_repeat_delay; |
266 | |
267 | struct wl_data_offer *pending_offer; |
268 | GdkContentFormatsBuilder *pending_builder; |
269 | GdkDragAction pending_source_actions; |
270 | GdkDragAction pending_action; |
271 | |
272 | struct wl_callback *repeat_callback; |
273 | guint32 repeat_timer; |
274 | guint32 repeat_key; |
275 | guint32 repeat_count; |
276 | gint64 repeat_deadline; |
277 | uint32_t keyboard_time; |
278 | uint32_t keyboard_key_serial; |
279 | |
280 | GdkClipboard *clipboard; |
281 | GdkClipboard *primary_clipboard; |
282 | struct wl_data_device *data_device; |
283 | GdkDrag *drag; |
284 | GdkDrop *drop; |
285 | |
286 | /* Some tracking on gesture events */ |
287 | guint gesture_n_fingers; |
288 | double gesture_scale; |
289 | |
290 | GdkCursor *grab_cursor; |
291 | }; |
292 | |
293 | G_DEFINE_TYPE (GdkWaylandSeat, gdk_wayland_seat, GDK_TYPE_SEAT) |
294 | |
295 | struct _GdkWaylandDevice |
296 | { |
297 | GdkDevice parent_instance; |
298 | GdkWaylandTouchData *emulating_touch; /* Only used on wd->logical_touch */ |
299 | GdkWaylandPointerData *pointer; |
300 | }; |
301 | |
302 | struct _GdkWaylandDeviceClass |
303 | { |
304 | GdkDeviceClass parent_class; |
305 | }; |
306 | |
307 | G_DEFINE_TYPE (GdkWaylandDevice, gdk_wayland_device, GDK_TYPE_DEVICE) |
308 | |
309 | struct _GdkWaylandDevicePad |
310 | { |
311 | GdkWaylandDevice parent_instance; |
312 | }; |
313 | |
314 | struct _GdkWaylandDevicePadClass |
315 | { |
316 | GdkWaylandDeviceClass parent_class; |
317 | }; |
318 | |
319 | static void gdk_wayland_device_pad_iface_init (GdkDevicePadInterface *iface); |
320 | static void init_pointer_data (GdkWaylandPointerData *pointer_data, |
321 | GdkDisplay *display_wayland, |
322 | GdkDevice *logical_device); |
323 | static void pointer_surface_update_scale (GdkDevice *device); |
324 | |
325 | #define GDK_TYPE_WAYLAND_DEVICE_PAD (gdk_wayland_device_pad_get_type ()) |
326 | GType gdk_wayland_device_pad_get_type (void); |
327 | |
328 | G_DEFINE_TYPE_WITH_CODE (GdkWaylandDevicePad, gdk_wayland_device_pad, |
329 | GDK_TYPE_WAYLAND_DEVICE, |
330 | G_IMPLEMENT_INTERFACE (GDK_TYPE_DEVICE_PAD, |
331 | gdk_wayland_device_pad_iface_init)) |
332 | |
333 | #define GDK_SLOT_TO_EVENT_SEQUENCE(s) ((GdkEventSequence *) GUINT_TO_POINTER((s) + 1)) |
334 | #define GDK_EVENT_SEQUENCE_TO_SLOT(s) (GPOINTER_TO_UINT(s) - 1) |
335 | |
336 | static void deliver_key_event (GdkWaylandSeat *seat, |
337 | uint32_t time_, |
338 | uint32_t key, |
339 | uint32_t state, |
340 | gboolean from_key_repeat); |
341 | |
342 | static void |
343 | gdk_wayland_pointer_stop_cursor_animation (GdkWaylandPointerData *pointer) |
344 | { |
345 | if (pointer->cursor_timeout_id > 0) |
346 | { |
347 | g_source_remove (tag: pointer->cursor_timeout_id); |
348 | pointer->cursor_timeout_id = 0; |
349 | pointer->cursor_image_delay = 0; |
350 | } |
351 | |
352 | pointer->cursor_image_index = 0; |
353 | } |
354 | |
355 | static GdkWaylandTabletData * |
356 | gdk_wayland_seat_find_tablet (GdkWaylandSeat *seat, |
357 | GdkDevice *device) |
358 | { |
359 | GList *l; |
360 | |
361 | for (l = seat->tablets; l; l = l->next) |
362 | { |
363 | GdkWaylandTabletData *tablet = l->data; |
364 | |
365 | if (tablet->logical_device == device || |
366 | tablet->stylus_device == device) |
367 | return tablet; |
368 | } |
369 | |
370 | return NULL; |
371 | } |
372 | |
373 | static GdkWaylandTabletPadData * |
374 | gdk_wayland_seat_find_pad (GdkWaylandSeat *seat, |
375 | GdkDevice *device) |
376 | { |
377 | GList *l; |
378 | |
379 | for (l = seat->tablet_pads; l; l = l->next) |
380 | { |
381 | GdkWaylandTabletPadData *pad = l->data; |
382 | |
383 | if (pad->device == device) |
384 | return pad; |
385 | } |
386 | |
387 | return NULL; |
388 | } |
389 | |
390 | |
391 | static gboolean |
392 | gdk_wayland_device_update_surface_cursor (GdkDevice *device) |
393 | { |
394 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
395 | GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer; |
396 | struct wl_buffer *buffer; |
397 | int x, y, w, h, scale; |
398 | guint next_image_index, next_image_delay; |
399 | gboolean retval = G_SOURCE_REMOVE; |
400 | GdkWaylandTabletData *tablet; |
401 | |
402 | tablet = gdk_wayland_seat_find_tablet (seat, device); |
403 | |
404 | if (pointer->cursor) |
405 | { |
406 | buffer = _gdk_wayland_cursor_get_buffer (GDK_WAYLAND_DISPLAY (seat->display), |
407 | cursor: pointer->cursor, |
408 | desired_scale: pointer->current_output_scale, |
409 | image_index: pointer->cursor_image_index, |
410 | hotspot_x: &x, hotspot_y: &y, w: &w, h: &h, scale: &scale); |
411 | } |
412 | else |
413 | { |
414 | pointer->cursor_timeout_id = 0; |
415 | return G_SOURCE_REMOVE; |
416 | } |
417 | |
418 | if (tablet) |
419 | { |
420 | if (!tablet->current_tool) |
421 | { |
422 | pointer->cursor_timeout_id = 0; |
423 | return G_SOURCE_REMOVE; |
424 | } |
425 | |
426 | zwp_tablet_tool_v2_set_cursor (tablet->current_tool->wp_tablet_tool, |
427 | pointer->enter_serial, |
428 | pointer->pointer_surface, |
429 | x, y); |
430 | } |
431 | else if (seat->wl_pointer) |
432 | { |
433 | wl_pointer_set_cursor (wl_pointer: seat->wl_pointer, |
434 | serial: pointer->enter_serial, |
435 | surface: pointer->pointer_surface, |
436 | hotspot_x: x, hotspot_y: y); |
437 | } |
438 | else |
439 | { |
440 | pointer->cursor_timeout_id = 0; |
441 | return G_SOURCE_REMOVE; |
442 | } |
443 | |
444 | if (buffer) |
445 | { |
446 | wl_surface_attach (wl_surface: pointer->pointer_surface, buffer, x: 0, y: 0); |
447 | wl_surface_set_buffer_scale (wl_surface: pointer->pointer_surface, scale); |
448 | wl_surface_damage (wl_surface: pointer->pointer_surface, x: 0, y: 0, width: w, height: h); |
449 | wl_surface_commit (wl_surface: pointer->pointer_surface); |
450 | } |
451 | else |
452 | { |
453 | wl_surface_attach (wl_surface: pointer->pointer_surface, NULL, x: 0, y: 0); |
454 | wl_surface_commit (wl_surface: pointer->pointer_surface); |
455 | } |
456 | |
457 | next_image_index = |
458 | _gdk_wayland_cursor_get_next_image_index (GDK_WAYLAND_DISPLAY (seat->display), |
459 | cursor: pointer->cursor, |
460 | scale: pointer->current_output_scale, |
461 | current_image_index: pointer->cursor_image_index, |
462 | next_image_delay: &next_image_delay); |
463 | |
464 | if (next_image_index != pointer->cursor_image_index) |
465 | { |
466 | if (next_image_delay != pointer->cursor_image_delay || |
467 | pointer->cursor_timeout_id == 0) |
468 | { |
469 | guint id; |
470 | GSource *source; |
471 | |
472 | gdk_wayland_pointer_stop_cursor_animation (pointer); |
473 | |
474 | /* Queue timeout for next frame */ |
475 | id = g_timeout_add (interval: next_image_delay, |
476 | function: (GSourceFunc) gdk_wayland_device_update_surface_cursor, |
477 | data: device); |
478 | source = g_main_context_find_source_by_id (NULL, source_id: id); |
479 | g_source_set_static_name (source, "[gtk] gdk_wayland_device_update_surface_cursor" ); |
480 | pointer->cursor_timeout_id = id; |
481 | } |
482 | else |
483 | retval = G_SOURCE_CONTINUE; |
484 | |
485 | pointer->cursor_image_index = next_image_index; |
486 | pointer->cursor_image_delay = next_image_delay; |
487 | } |
488 | else |
489 | gdk_wayland_pointer_stop_cursor_animation (pointer); |
490 | |
491 | return retval; |
492 | } |
493 | |
494 | static void |
495 | gdk_wayland_device_set_surface_cursor (GdkDevice *device, |
496 | GdkSurface *surface, |
497 | GdkCursor *cursor) |
498 | { |
499 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
500 | GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer; |
501 | |
502 | if (device == seat->logical_touch) |
503 | return; |
504 | |
505 | if (seat->grab_cursor) |
506 | cursor = seat->grab_cursor; |
507 | |
508 | if (pointer->cursor != NULL && |
509 | cursor != NULL && |
510 | gdk_cursor_equal (a: cursor, b: pointer->cursor)) |
511 | return; |
512 | |
513 | if (cursor == NULL) |
514 | { |
515 | if (!pointer->cursor_is_default) |
516 | { |
517 | g_clear_object (&pointer->cursor); |
518 | pointer->cursor = gdk_cursor_new_from_name (name: "default" , NULL); |
519 | pointer->cursor_is_default = TRUE; |
520 | |
521 | gdk_wayland_pointer_stop_cursor_animation (pointer); |
522 | gdk_wayland_device_update_surface_cursor (device); |
523 | } |
524 | else |
525 | { |
526 | /* Nothing to do, we'already using the default cursor */ |
527 | } |
528 | } |
529 | else |
530 | { |
531 | g_set_object (&pointer->cursor, cursor); |
532 | pointer->cursor_is_default = FALSE; |
533 | |
534 | gdk_wayland_pointer_stop_cursor_animation (pointer); |
535 | gdk_wayland_device_update_surface_cursor (device); |
536 | } |
537 | } |
538 | |
539 | static GdkModifierType |
540 | device_get_modifiers (GdkDevice *device) |
541 | { |
542 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
543 | GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer; |
544 | GdkModifierType mask; |
545 | |
546 | mask = seat->key_modifiers; |
547 | |
548 | if (pointer) |
549 | mask |= pointer->button_modifiers; |
550 | |
551 | return mask; |
552 | } |
553 | |
554 | void |
555 | gdk_wayland_device_query_state (GdkDevice *device, |
556 | GdkSurface *surface, |
557 | double *win_x, |
558 | double *win_y, |
559 | GdkModifierType *mask) |
560 | { |
561 | GdkWaylandPointerData *pointer; |
562 | double x, y; |
563 | |
564 | if (mask) |
565 | *mask = device_get_modifiers (device); |
566 | |
567 | pointer = GDK_WAYLAND_DEVICE (device)->pointer; |
568 | |
569 | if (pointer->focus == surface) |
570 | { |
571 | x = pointer->surface_x; |
572 | y = pointer->surface_y; |
573 | } |
574 | else |
575 | { |
576 | x = y = -1; |
577 | } |
578 | |
579 | if (win_x) |
580 | *win_x = x; |
581 | if (win_y) |
582 | *win_y = y; |
583 | } |
584 | |
585 | static void |
586 | emulate_crossing (GdkSurface *surface, |
587 | GdkSurface *child_surface, |
588 | GdkDevice *device, |
589 | GdkEventType type, |
590 | GdkCrossingMode mode, |
591 | guint32 time_) |
592 | { |
593 | GdkEvent *event; |
594 | GdkModifierType state; |
595 | double x, y; |
596 | |
597 | gdk_surface_get_device_position (surface, device, x: &x, y: &y, mask: &state); |
598 | event = gdk_crossing_event_new (type, |
599 | surface, |
600 | device, |
601 | time: time_, |
602 | state, |
603 | x, y, |
604 | mode, |
605 | notify: GDK_NOTIFY_NONLINEAR); |
606 | |
607 | _gdk_wayland_display_deliver_event (display: gdk_surface_get_display (surface), event); |
608 | } |
609 | |
610 | static void |
611 | emulate_touch_crossing (GdkSurface *surface, |
612 | GdkSurface *child_surface, |
613 | GdkDevice *device, |
614 | GdkDevice *source, |
615 | GdkWaylandTouchData *touch, |
616 | GdkEventType type, |
617 | GdkCrossingMode mode, |
618 | guint32 time_) |
619 | { |
620 | GdkEvent *event; |
621 | |
622 | event = gdk_crossing_event_new (type, |
623 | surface, |
624 | device, |
625 | time: time_, |
626 | state: 0, |
627 | x: touch->x, y: touch->y, |
628 | mode, |
629 | notify: GDK_NOTIFY_NONLINEAR); |
630 | |
631 | _gdk_wayland_display_deliver_event (display: gdk_surface_get_display (surface), event); |
632 | } |
633 | |
634 | static void |
635 | emulate_focus (GdkSurface *surface, |
636 | GdkDevice *device, |
637 | gboolean focus_in, |
638 | guint32 time_) |
639 | { |
640 | GdkEvent *event = gdk_focus_event_new (surface, device, focus_in); |
641 | |
642 | _gdk_wayland_display_deliver_event (display: gdk_surface_get_display (surface), event); |
643 | } |
644 | |
645 | static void |
646 | device_emit_grab_crossing (GdkDevice *device, |
647 | GdkSurface *from, |
648 | GdkSurface *to, |
649 | GdkCrossingMode mode, |
650 | guint32 time_) |
651 | { |
652 | if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) |
653 | { |
654 | if (from) |
655 | emulate_focus (surface: from, device, FALSE, time_); |
656 | if (to) |
657 | emulate_focus (surface: to, device, TRUE, time_); |
658 | } |
659 | else |
660 | { |
661 | if (from) |
662 | emulate_crossing (surface: from, child_surface: to, device, type: GDK_LEAVE_NOTIFY, mode, time_); |
663 | if (to) |
664 | emulate_crossing (surface: to, child_surface: from, device, type: GDK_ENTER_NOTIFY, mode, time_); |
665 | } |
666 | } |
667 | |
668 | GdkSurface * |
669 | gdk_wayland_device_get_focus (GdkDevice *device) |
670 | { |
671 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
672 | GdkWaylandPointerData *pointer; |
673 | |
674 | if (device == wayland_seat->logical_keyboard) |
675 | return wayland_seat->keyboard_focus; |
676 | else |
677 | { |
678 | pointer = GDK_WAYLAND_DEVICE (device)->pointer; |
679 | |
680 | if (pointer) |
681 | return pointer->focus; |
682 | } |
683 | |
684 | return NULL; |
685 | } |
686 | |
687 | static void |
688 | device_maybe_emit_grab_crossing (GdkDevice *device, |
689 | GdkSurface *window, |
690 | guint32 time) |
691 | { |
692 | GdkSurface *surface = gdk_wayland_device_get_focus (device); |
693 | GdkSurface *focus = window; |
694 | |
695 | if (focus != surface) |
696 | device_emit_grab_crossing (device, from: focus, to: window, mode: GDK_CROSSING_GRAB, time_: time); |
697 | } |
698 | |
699 | static GdkSurface* |
700 | device_maybe_emit_ungrab_crossing (GdkDevice *device, |
701 | guint32 time_) |
702 | { |
703 | GdkDeviceGrabInfo *grab; |
704 | GdkSurface *focus = NULL; |
705 | GdkSurface *surface = NULL; |
706 | GdkSurface *prev_focus = NULL; |
707 | |
708 | focus = gdk_wayland_device_get_focus (device); |
709 | grab = _gdk_display_get_last_device_grab (display: gdk_device_get_display (device), device); |
710 | |
711 | if (grab) |
712 | { |
713 | prev_focus = grab->surface; |
714 | surface = grab->surface; |
715 | } |
716 | |
717 | if (focus != surface) |
718 | device_emit_grab_crossing (device, from: prev_focus, to: focus, mode: GDK_CROSSING_UNGRAB, time_); |
719 | |
720 | return prev_focus; |
721 | } |
722 | |
723 | static GdkGrabStatus |
724 | gdk_wayland_device_grab (GdkDevice *device, |
725 | GdkSurface *surface, |
726 | gboolean owner_events, |
727 | GdkEventMask event_mask, |
728 | GdkSurface *confine_to, |
729 | GdkCursor *cursor, |
730 | guint32 time_) |
731 | { |
732 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
733 | GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer; |
734 | |
735 | if (GDK_IS_DRAG_SURFACE (ptr: surface) && |
736 | gdk_surface_get_mapped (surface)) |
737 | { |
738 | g_warning ("Surface %p is already mapped at the time of grabbing. " |
739 | "gdk_seat_grab() should be used to simultaneously grab input " |
740 | "and show this popup. You may find oddities ahead." , |
741 | surface); |
742 | } |
743 | |
744 | device_maybe_emit_grab_crossing (device, window: surface, time: time_); |
745 | |
746 | if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) |
747 | { |
748 | /* Device is a keyboard */ |
749 | gdk_wayland_surface_inhibit_shortcuts (surface, |
750 | gdk_seat: gdk_device_get_seat (device)); |
751 | return GDK_GRAB_SUCCESS; |
752 | } |
753 | else |
754 | { |
755 | /* Device is a pointer */ |
756 | if (pointer->grab_surface != NULL && |
757 | time_ != 0 && pointer->grab_time > time_) |
758 | { |
759 | return GDK_GRAB_ALREADY_GRABBED; |
760 | } |
761 | |
762 | if (time_ == 0) |
763 | time_ = pointer->time; |
764 | |
765 | pointer->grab_surface = surface; |
766 | pointer->grab_time = time_; |
767 | _gdk_wayland_surface_set_grab_seat (surface, GDK_SEAT (wayland_seat)); |
768 | |
769 | g_clear_object (&wayland_seat->cursor); |
770 | |
771 | if (cursor) |
772 | wayland_seat->cursor = g_object_ref (cursor); |
773 | |
774 | gdk_wayland_device_update_surface_cursor (device); |
775 | } |
776 | |
777 | return GDK_GRAB_SUCCESS; |
778 | } |
779 | |
780 | static void |
781 | gdk_wayland_device_ungrab (GdkDevice *device, |
782 | guint32 time_) |
783 | { |
784 | GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer; |
785 | GdkSurface *prev_focus; |
786 | |
787 | prev_focus = device_maybe_emit_ungrab_crossing (device, time_); |
788 | |
789 | if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) |
790 | { |
791 | /* Device is a keyboard */ |
792 | if (prev_focus) |
793 | gdk_wayland_surface_restore_shortcuts (surface: prev_focus, |
794 | gdk_seat: gdk_device_get_seat (device)); |
795 | } |
796 | else |
797 | { |
798 | /* Device is a pointer */ |
799 | gdk_wayland_device_update_surface_cursor (device); |
800 | |
801 | if (pointer->grab_surface) |
802 | _gdk_wayland_surface_set_grab_seat (surface: pointer->grab_surface, |
803 | NULL); |
804 | } |
805 | } |
806 | |
807 | static GdkSurface * |
808 | gdk_wayland_device_surface_at_position (GdkDevice *device, |
809 | double *win_x, |
810 | double *win_y, |
811 | GdkModifierType *mask) |
812 | { |
813 | GdkWaylandPointerData *pointer; |
814 | |
815 | pointer = GDK_WAYLAND_DEVICE(device)->pointer; |
816 | |
817 | if (!pointer) |
818 | return NULL; |
819 | |
820 | if (win_x) |
821 | *win_x = pointer->surface_x; |
822 | if (win_y) |
823 | *win_y = pointer->surface_y; |
824 | if (mask) |
825 | *mask = device_get_modifiers (device); |
826 | |
827 | return pointer->focus; |
828 | } |
829 | |
830 | static void |
831 | gdk_wayland_device_class_init (GdkWaylandDeviceClass *klass) |
832 | { |
833 | GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass); |
834 | |
835 | device_class->set_surface_cursor = gdk_wayland_device_set_surface_cursor; |
836 | device_class->grab = gdk_wayland_device_grab; |
837 | device_class->ungrab = gdk_wayland_device_ungrab; |
838 | device_class->surface_at_position = gdk_wayland_device_surface_at_position; |
839 | } |
840 | |
841 | static void |
842 | gdk_wayland_device_init (GdkWaylandDevice *device_core) |
843 | { |
844 | GdkDevice *device; |
845 | |
846 | device = GDK_DEVICE (device_core); |
847 | |
848 | _gdk_device_add_axis (device, use: GDK_AXIS_X, min_value: 0, max_value: 0, resolution: 1); |
849 | _gdk_device_add_axis (device, use: GDK_AXIS_Y, min_value: 0, max_value: 0, resolution: 1); |
850 | } |
851 | |
852 | static int |
853 | gdk_wayland_device_pad_get_n_groups (GdkDevicePad *pad) |
854 | { |
855 | GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad)); |
856 | GdkWaylandTabletPadData *data; |
857 | |
858 | data = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat), |
859 | GDK_DEVICE (pad)); |
860 | #ifdef G_DISABLE_ASSERT |
861 | if (data == NULL) |
862 | return 0; |
863 | #else |
864 | g_assert (data != NULL); |
865 | #endif |
866 | |
867 | return g_list_length (list: data->mode_groups); |
868 | } |
869 | |
870 | static int |
871 | gdk_wayland_device_pad_get_group_n_modes (GdkDevicePad *pad, |
872 | int n_group) |
873 | { |
874 | GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad)); |
875 | GdkWaylandTabletPadGroupData *group; |
876 | GdkWaylandTabletPadData *data; |
877 | |
878 | data = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat), |
879 | GDK_DEVICE (pad)); |
880 | #ifdef G_DISABLE_ASSERT |
881 | if (data == NULL) |
882 | return 0; |
883 | #else |
884 | g_assert (data != NULL); |
885 | #endif |
886 | |
887 | group = g_list_nth_data (list: data->mode_groups, n: n_group); |
888 | if (!group) |
889 | return -1; |
890 | |
891 | return group->n_modes; |
892 | } |
893 | |
894 | static int |
895 | gdk_wayland_device_pad_get_n_features (GdkDevicePad *pad, |
896 | GdkDevicePadFeature feature) |
897 | { |
898 | GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad)); |
899 | GdkWaylandTabletPadData *data; |
900 | |
901 | data = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat), |
902 | GDK_DEVICE (pad)); |
903 | g_assert (data != NULL); |
904 | |
905 | switch (feature) |
906 | { |
907 | case GDK_DEVICE_PAD_FEATURE_BUTTON: |
908 | return data->n_buttons; |
909 | case GDK_DEVICE_PAD_FEATURE_RING: |
910 | return g_list_length (list: data->rings); |
911 | case GDK_DEVICE_PAD_FEATURE_STRIP: |
912 | return g_list_length (list: data->strips); |
913 | default: |
914 | return -1; |
915 | } |
916 | } |
917 | |
918 | static int |
919 | gdk_wayland_device_pad_get_feature_group (GdkDevicePad *pad, |
920 | GdkDevicePadFeature feature, |
921 | int idx) |
922 | { |
923 | GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad)); |
924 | GdkWaylandTabletPadGroupData *group; |
925 | GdkWaylandTabletPadData *data; |
926 | GList *l; |
927 | int i; |
928 | |
929 | data = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat), |
930 | GDK_DEVICE (pad)); |
931 | #ifdef G_DISABLE_ASSERT |
932 | if (data == NULL) |
933 | return -1; |
934 | #else |
935 | g_assert (data != NULL); |
936 | #endif |
937 | |
938 | for (l = data->mode_groups, i = 0; l; l = l->next, i++) |
939 | { |
940 | group = l->data; |
941 | |
942 | switch (feature) |
943 | { |
944 | case GDK_DEVICE_PAD_FEATURE_BUTTON: |
945 | if (g_list_find (list: group->buttons, GINT_TO_POINTER (idx))) |
946 | return i; |
947 | break; |
948 | case GDK_DEVICE_PAD_FEATURE_RING: |
949 | { |
950 | gpointer ring; |
951 | |
952 | ring = g_list_nth_data (list: data->rings, n: idx); |
953 | if (ring && g_list_find (list: group->rings, data: ring)) |
954 | return i; |
955 | break; |
956 | } |
957 | case GDK_DEVICE_PAD_FEATURE_STRIP: |
958 | { |
959 | gpointer strip; |
960 | strip = g_list_nth_data (list: data->strips, n: idx); |
961 | if (strip && g_list_find (list: group->strips, data: strip)) |
962 | return i; |
963 | break; |
964 | } |
965 | default: |
966 | break; |
967 | } |
968 | } |
969 | |
970 | return -1; |
971 | } |
972 | |
973 | static void |
974 | gdk_wayland_device_pad_iface_init (GdkDevicePadInterface *iface) |
975 | { |
976 | iface->get_n_groups = gdk_wayland_device_pad_get_n_groups; |
977 | iface->get_group_n_modes = gdk_wayland_device_pad_get_group_n_modes; |
978 | iface->get_n_features = gdk_wayland_device_pad_get_n_features; |
979 | iface->get_feature_group = gdk_wayland_device_pad_get_feature_group; |
980 | } |
981 | |
982 | static void |
983 | gdk_wayland_device_pad_class_init (GdkWaylandDevicePadClass *klass) |
984 | { |
985 | } |
986 | |
987 | static void |
988 | gdk_wayland_device_pad_init (GdkWaylandDevicePad *pad) |
989 | { |
990 | } |
991 | |
992 | /** |
993 | * gdk_wayland_device_get_wl_seat: (skip) |
994 | * @device: (type GdkWaylandDevice): a `GdkDevice` |
995 | * |
996 | * Returns the Wayland `wl_seat` of a `GdkDevice`. |
997 | * |
998 | * Returns: (transfer none): a Wayland `wl_seat` |
999 | */ |
1000 | struct wl_seat * |
1001 | gdk_wayland_device_get_wl_seat (GdkDevice *device) |
1002 | { |
1003 | GdkWaylandSeat *seat; |
1004 | |
1005 | g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (device), NULL); |
1006 | |
1007 | seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
1008 | return seat->wl_seat; |
1009 | } |
1010 | |
1011 | /** |
1012 | * gdk_wayland_device_get_wl_pointer: (skip) |
1013 | * @device: (type GdkWaylandDevice): a `GdkDevice` |
1014 | * |
1015 | * Returns the Wayland `wl_pointer` of a `GdkDevice`. |
1016 | * |
1017 | * Returns: (transfer none): a Wayland `wl_pointer` |
1018 | */ |
1019 | struct wl_pointer * |
1020 | gdk_wayland_device_get_wl_pointer (GdkDevice *device) |
1021 | { |
1022 | GdkWaylandSeat *seat; |
1023 | |
1024 | g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (device), NULL); |
1025 | |
1026 | seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
1027 | return seat->wl_pointer; |
1028 | } |
1029 | |
1030 | /** |
1031 | * gdk_wayland_device_get_wl_keyboard: (skip) |
1032 | * @device: (type GdkWaylandDevice): a `GdkDevice` |
1033 | * |
1034 | * Returns the Wayland `wl_keyboard` of a `GdkDevice`. |
1035 | * |
1036 | * Returns: (transfer none): a Wayland `wl_keyboard` |
1037 | */ |
1038 | struct wl_keyboard * |
1039 | gdk_wayland_device_get_wl_keyboard (GdkDevice *device) |
1040 | { |
1041 | GdkWaylandSeat *seat; |
1042 | |
1043 | g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (device), NULL); |
1044 | |
1045 | seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
1046 | return seat->wl_keyboard; |
1047 | } |
1048 | |
1049 | /** |
1050 | * gdk_wayland_device_get_xkb_keymap: |
1051 | * @device: (type GdkWaylandDevice): a `GdkDevice` |
1052 | * |
1053 | * Returns the `xkb_keymap` of a `GdkDevice`. |
1054 | * |
1055 | * Returns: (transfer none): a `struct xkb_keymap` |
1056 | * |
1057 | * Since: 4.4 |
1058 | */ |
1059 | struct xkb_keymap * |
1060 | gdk_wayland_device_get_xkb_keymap (GdkDevice *device) |
1061 | { |
1062 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
1063 | return _gdk_wayland_keymap_get_xkb_keymap (keymap: seat->keymap); |
1064 | } |
1065 | |
1066 | GdkKeymap * |
1067 | _gdk_wayland_device_get_keymap (GdkDevice *device) |
1068 | { |
1069 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
1070 | return seat->keymap; |
1071 | } |
1072 | |
1073 | static void |
1074 | gdk_wayland_seat_discard_pending_offer (GdkWaylandSeat *seat) |
1075 | { |
1076 | if (seat->pending_builder) |
1077 | { |
1078 | GdkContentFormats *ignore = gdk_content_formats_builder_free_to_formats (builder: seat->pending_builder); |
1079 | gdk_content_formats_unref (formats: ignore); |
1080 | seat->pending_builder = NULL; |
1081 | } |
1082 | g_clear_pointer (&seat->pending_offer, wl_data_offer_destroy); |
1083 | seat->pending_source_actions = 0; |
1084 | seat->pending_action = 0; |
1085 | } |
1086 | |
1087 | static inline GdkDragAction |
1088 | gdk_wayland_actions_to_gdk_actions (uint32_t dnd_actions) |
1089 | { |
1090 | GdkDragAction actions = 0; |
1091 | |
1092 | if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) |
1093 | actions |= GDK_ACTION_COPY; |
1094 | if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) |
1095 | actions |= GDK_ACTION_MOVE; |
1096 | if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) |
1097 | actions |= GDK_ACTION_ASK; |
1098 | |
1099 | return actions; |
1100 | } |
1101 | |
1102 | static void |
1103 | data_offer_offer (void *data, |
1104 | struct wl_data_offer *offer, |
1105 | const char *type) |
1106 | { |
1107 | GdkWaylandSeat *seat = data; |
1108 | |
1109 | if (seat->pending_offer != offer) |
1110 | { |
1111 | GDK_SEAT_NOTE (seat, EVENTS, |
1112 | g_message ("%p: offer for unknown offer %p of %s" , |
1113 | seat, offer, type)); |
1114 | return; |
1115 | } |
1116 | |
1117 | /* skip magic mime types */ |
1118 | if (g_str_equal (v1: type, GDK_WAYLAND_LOCAL_DND_MIME_TYPE)) |
1119 | return; |
1120 | |
1121 | gdk_content_formats_builder_add_mime_type (builder: seat->pending_builder, mime_type: type); |
1122 | } |
1123 | |
1124 | static void |
1125 | data_offer_source_actions (void *data, |
1126 | struct wl_data_offer *offer, |
1127 | uint32_t source_actions) |
1128 | { |
1129 | GdkWaylandSeat *seat = data; |
1130 | |
1131 | if (offer == seat->pending_offer) |
1132 | { |
1133 | seat->pending_source_actions = gdk_wayland_actions_to_gdk_actions (dnd_actions: source_actions); |
1134 | return; |
1135 | } |
1136 | |
1137 | if (seat->drop == NULL) |
1138 | return; |
1139 | |
1140 | gdk_wayland_drop_set_source_actions (drop: seat->drop, source_actions); |
1141 | |
1142 | gdk_drop_emit_motion_event (self: seat->drop, |
1143 | FALSE, |
1144 | x: seat->pointer_info.surface_x, |
1145 | y: seat->pointer_info.surface_y, |
1146 | GDK_CURRENT_TIME); |
1147 | } |
1148 | |
1149 | static void |
1150 | data_offer_action (void *data, |
1151 | struct wl_data_offer *offer, |
1152 | uint32_t action) |
1153 | { |
1154 | GdkWaylandSeat *seat = data; |
1155 | |
1156 | if (offer == seat->pending_offer) |
1157 | { |
1158 | seat->pending_action = gdk_wayland_actions_to_gdk_actions (dnd_actions: action); |
1159 | return; |
1160 | } |
1161 | |
1162 | if (seat->drop == NULL) |
1163 | return; |
1164 | |
1165 | gdk_wayland_drop_set_action (drop: seat->drop, action); |
1166 | |
1167 | gdk_drop_emit_motion_event (self: seat->drop, |
1168 | FALSE, |
1169 | x: seat->pointer_info.surface_x, |
1170 | y: seat->pointer_info.surface_y, |
1171 | GDK_CURRENT_TIME); |
1172 | } |
1173 | |
1174 | static const struct wl_data_offer_listener data_offer_listener = { |
1175 | data_offer_offer, |
1176 | data_offer_source_actions, |
1177 | data_offer_action |
1178 | }; |
1179 | |
1180 | static void |
1181 | data_device_data_offer (void *data, |
1182 | struct wl_data_device *data_device, |
1183 | struct wl_data_offer *offer) |
1184 | { |
1185 | GdkWaylandSeat *seat = data; |
1186 | |
1187 | GDK_SEAT_NOTE (seat, EVENTS, |
1188 | g_message ("data device data offer, data device %p, offer %p" , |
1189 | data_device, offer)); |
1190 | |
1191 | gdk_wayland_seat_discard_pending_offer (seat); |
1192 | |
1193 | seat->pending_offer = offer; |
1194 | wl_data_offer_add_listener (wl_data_offer: offer, |
1195 | listener: &data_offer_listener, |
1196 | data: seat); |
1197 | |
1198 | seat->pending_builder = gdk_content_formats_builder_new (); |
1199 | seat->pending_source_actions = 0; |
1200 | seat->pending_action = 0; |
1201 | } |
1202 | |
1203 | static void |
1204 | data_device_enter (void *data, |
1205 | struct wl_data_device *data_device, |
1206 | uint32_t serial, |
1207 | struct wl_surface *surface, |
1208 | wl_fixed_t x, |
1209 | wl_fixed_t y, |
1210 | struct wl_data_offer *offer) |
1211 | { |
1212 | GdkWaylandSeat *seat = data; |
1213 | GdkSurface *dest_surface; |
1214 | GdkContentFormats *formats; |
1215 | int origin_x, origin_y; |
1216 | GdkDevice *device; |
1217 | |
1218 | dest_surface = wl_surface_get_user_data (wl_surface: surface); |
1219 | |
1220 | if (!GDK_IS_SURFACE (dest_surface)) |
1221 | return; |
1222 | |
1223 | if (offer != seat->pending_offer) |
1224 | { |
1225 | GDK_SEAT_NOTE (seat, EVENTS, |
1226 | g_message ("%p: enter event for unknown offer %p, expected %p" , |
1227 | seat, offer, seat->pending_offer)); |
1228 | return; |
1229 | } |
1230 | |
1231 | GDK_SEAT_NOTE (seat, EVENTS, |
1232 | g_message ("data device enter, data device %p serial %u, surface %p, x %f y %f, offer %p" , |
1233 | data_device, serial, surface, wl_fixed_to_double (x), wl_fixed_to_double (y), offer)); |
1234 | |
1235 | /* Update pointer state, so device state queries work during DnD */ |
1236 | seat->pointer_info.focus = g_object_ref (dest_surface); |
1237 | seat->pointer_info.surface_x = wl_fixed_to_double (f: x); |
1238 | seat->pointer_info.surface_y = wl_fixed_to_double (f: y); |
1239 | |
1240 | if (seat->logical_pointer) |
1241 | device = seat->logical_pointer; |
1242 | else if (seat->logical_touch) |
1243 | device = seat->logical_touch; |
1244 | else |
1245 | { |
1246 | g_warning ("No device for DND enter, ignoring." ); |
1247 | return; |
1248 | } |
1249 | |
1250 | formats = gdk_content_formats_builder_free_to_formats (builder: seat->pending_builder); |
1251 | seat->pending_builder = NULL; |
1252 | seat->pending_offer = NULL; |
1253 | |
1254 | seat->drop = gdk_wayland_drop_new (device, drag: seat->drag, formats, surface: dest_surface, offer, serial); |
1255 | gdk_wayland_drop_set_source_actions (drop: seat->drop, source_actions: seat->pending_source_actions); |
1256 | gdk_wayland_drop_set_action (drop: seat->drop, action: seat->pending_action); |
1257 | |
1258 | gdk_content_formats_unref (formats); |
1259 | |
1260 | gdk_wayland_seat_discard_pending_offer (seat); |
1261 | |
1262 | gdk_surface_get_origin (surface: gdk_drop_get_surface (self: seat->drop), x: &origin_x, y: &origin_y); |
1263 | |
1264 | gdk_drop_emit_enter_event (self: seat->drop, |
1265 | FALSE, |
1266 | x: origin_x + seat->pointer_info.surface_x, |
1267 | y: origin_y + seat->pointer_info.surface_y, |
1268 | GDK_CURRENT_TIME); |
1269 | } |
1270 | |
1271 | static void |
1272 | data_device_leave (void *data, |
1273 | struct wl_data_device *data_device) |
1274 | { |
1275 | GdkWaylandSeat *seat = data; |
1276 | |
1277 | GDK_SEAT_NOTE (seat, EVENTS, |
1278 | g_message ("data device leave, data device %p" , data_device)); |
1279 | |
1280 | if (seat->drop == NULL) |
1281 | return; |
1282 | |
1283 | g_object_unref (object: seat->pointer_info.focus); |
1284 | seat->pointer_info.focus = NULL; |
1285 | |
1286 | gdk_drop_emit_leave_event (self: seat->drop, |
1287 | FALSE, |
1288 | GDK_CURRENT_TIME); |
1289 | |
1290 | g_clear_object (&seat->drop); |
1291 | } |
1292 | |
1293 | static void |
1294 | data_device_motion (void *data, |
1295 | struct wl_data_device *data_device, |
1296 | uint32_t time, |
1297 | wl_fixed_t x, |
1298 | wl_fixed_t y) |
1299 | { |
1300 | GdkWaylandSeat *seat = data; |
1301 | int origin_x, origin_y; |
1302 | |
1303 | GDK_SEAT_NOTE (seat, EVENTS, |
1304 | g_message ("data device motion, data_device = %p, time = %d, x = %f, y = %f" , |
1305 | data_device, time, wl_fixed_to_double (x), wl_fixed_to_double (y))); |
1306 | |
1307 | if (seat->drop == NULL) |
1308 | return; |
1309 | |
1310 | /* Update pointer state, so device state queries work during DnD */ |
1311 | seat->pointer_info.surface_x = wl_fixed_to_double (f: x); |
1312 | seat->pointer_info.surface_y = wl_fixed_to_double (f: y); |
1313 | |
1314 | gdk_surface_get_origin (surface: gdk_drop_get_surface (self: seat->drop), x: &origin_x, y: &origin_y); |
1315 | |
1316 | gdk_drop_emit_motion_event (self: seat->drop, |
1317 | FALSE, |
1318 | x: origin_x + seat->pointer_info.surface_x, |
1319 | y: origin_y + seat->pointer_info.surface_y, |
1320 | time); |
1321 | } |
1322 | |
1323 | static void |
1324 | data_device_drop (void *data, |
1325 | struct wl_data_device *data_device) |
1326 | { |
1327 | GdkWaylandSeat *seat = data; |
1328 | int origin_x, origin_y; |
1329 | |
1330 | GDK_SEAT_NOTE (seat, EVENTS, |
1331 | g_message ("data device drop, data device %p" , data_device)); |
1332 | |
1333 | gdk_surface_get_origin (surface: gdk_drop_get_surface (self: seat->drop), x: &origin_x, y: &origin_y); |
1334 | |
1335 | gdk_drop_emit_drop_event (self: seat->drop, |
1336 | FALSE, |
1337 | x: origin_x + seat->pointer_info.surface_x, |
1338 | y: origin_y + seat->pointer_info.surface_y, |
1339 | GDK_CURRENT_TIME); |
1340 | } |
1341 | |
1342 | static void |
1343 | data_device_selection (void *data, |
1344 | struct wl_data_device *wl_data_device, |
1345 | struct wl_data_offer *offer) |
1346 | { |
1347 | GdkWaylandSeat *seat = data; |
1348 | GdkContentFormats *formats; |
1349 | |
1350 | if (offer) |
1351 | { |
1352 | if (offer == seat->pending_offer) |
1353 | { |
1354 | formats = gdk_content_formats_builder_free_to_formats (builder: seat->pending_builder); |
1355 | seat->pending_builder = NULL; |
1356 | seat->pending_offer = NULL; |
1357 | } |
1358 | else |
1359 | { |
1360 | formats = gdk_content_formats_new (NULL, n_mime_types: 0); |
1361 | offer = NULL; |
1362 | } |
1363 | |
1364 | gdk_wayland_seat_discard_pending_offer (seat); |
1365 | } |
1366 | else |
1367 | { |
1368 | formats = gdk_content_formats_new (NULL, n_mime_types: 0); |
1369 | } |
1370 | |
1371 | gdk_wayland_clipboard_claim_remote (GDK_WAYLAND_CLIPBOARD (seat->clipboard), |
1372 | offer, |
1373 | formats); |
1374 | } |
1375 | |
1376 | static const struct wl_data_device_listener data_device_listener = { |
1377 | data_device_data_offer, |
1378 | data_device_enter, |
1379 | data_device_leave, |
1380 | data_device_motion, |
1381 | data_device_drop, |
1382 | data_device_selection |
1383 | }; |
1384 | |
1385 | static GdkDevice * get_scroll_device (GdkWaylandSeat *seat, |
1386 | enum wl_pointer_axis_source source); |
1387 | |
1388 | static void |
1389 | flush_discrete_scroll_event (GdkWaylandSeat *seat, |
1390 | GdkScrollDirection direction) |
1391 | { |
1392 | GdkEvent *event; |
1393 | GdkDevice *source; |
1394 | |
1395 | source = get_scroll_device (seat, source: seat->pointer_info.frame.source); |
1396 | event = gdk_scroll_event_new_discrete (surface: seat->pointer_info.focus, |
1397 | device: source, |
1398 | NULL, |
1399 | time: seat->pointer_info.time, |
1400 | state: device_get_modifiers (device: seat->logical_pointer), |
1401 | direction, |
1402 | TRUE); |
1403 | |
1404 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
1405 | } |
1406 | |
1407 | static void |
1408 | flush_smooth_scroll_event (GdkWaylandSeat *seat, |
1409 | double delta_x, |
1410 | double delta_y, |
1411 | gboolean is_stop) |
1412 | { |
1413 | GdkEvent *event; |
1414 | GdkDevice *source; |
1415 | |
1416 | source = get_scroll_device (seat, source: seat->pointer_info.frame.source); |
1417 | event = gdk_scroll_event_new (surface: seat->pointer_info.focus, |
1418 | device: source, |
1419 | NULL, |
1420 | time: seat->pointer_info.time, |
1421 | state: device_get_modifiers (device: seat->logical_pointer), |
1422 | delta_x, delta_y, |
1423 | is_stop); |
1424 | |
1425 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
1426 | } |
1427 | |
1428 | static void |
1429 | flush_scroll_event (GdkWaylandSeat *seat, |
1430 | GdkWaylandPointerFrameData *pointer_frame) |
1431 | { |
1432 | gboolean is_stop = FALSE; |
1433 | |
1434 | if (pointer_frame->discrete_x || pointer_frame->discrete_y) |
1435 | { |
1436 | GdkScrollDirection direction; |
1437 | |
1438 | if (pointer_frame->discrete_x > 0) |
1439 | direction = GDK_SCROLL_LEFT; |
1440 | else if (pointer_frame->discrete_x < 0) |
1441 | direction = GDK_SCROLL_RIGHT; |
1442 | else if (pointer_frame->discrete_y > 0) |
1443 | direction = GDK_SCROLL_DOWN; |
1444 | else |
1445 | direction = GDK_SCROLL_UP; |
1446 | |
1447 | flush_discrete_scroll_event (seat, direction); |
1448 | pointer_frame->discrete_x = 0; |
1449 | pointer_frame->discrete_y = 0; |
1450 | } |
1451 | else if (pointer_frame->is_scroll_stop || |
1452 | pointer_frame->delta_x != 0 || |
1453 | pointer_frame->delta_y != 0) |
1454 | { |
1455 | /* Axes can stop independently, if we stop on one axis but have a |
1456 | * delta on the other, we don't count it as a stop event. |
1457 | */ |
1458 | if (pointer_frame->is_scroll_stop && |
1459 | pointer_frame->delta_x == 0 && |
1460 | pointer_frame->delta_y == 0) |
1461 | is_stop = TRUE; |
1462 | |
1463 | flush_smooth_scroll_event (seat, |
1464 | delta_x: pointer_frame->delta_x, |
1465 | delta_y: pointer_frame->delta_y, |
1466 | is_stop); |
1467 | } |
1468 | |
1469 | pointer_frame->discrete_x = 0; |
1470 | pointer_frame->discrete_y = 0; |
1471 | pointer_frame->delta_x = 0; |
1472 | pointer_frame->delta_y = 0; |
1473 | pointer_frame->is_scroll_stop = FALSE; |
1474 | } |
1475 | |
1476 | static void |
1477 | gdk_wayland_seat_flush_frame_event (GdkWaylandSeat *seat) |
1478 | { |
1479 | if (seat->pointer_info.frame.event) |
1480 | { |
1481 | _gdk_wayland_display_deliver_event (display: gdk_seat_get_display (GDK_SEAT (seat)), |
1482 | event: seat->pointer_info.frame.event); |
1483 | seat->pointer_info.frame.event = NULL; |
1484 | } |
1485 | else |
1486 | { |
1487 | flush_scroll_event (seat, pointer_frame: &seat->pointer_info.frame); |
1488 | seat->pointer_info.frame.source = 0; |
1489 | } |
1490 | } |
1491 | |
1492 | static void |
1493 | gdk_wayland_seat_set_frame_event (GdkWaylandSeat *seat, |
1494 | GdkEvent *event) |
1495 | { |
1496 | if (seat->pointer_info.frame.event && |
1497 | gdk_event_get_event_type (event: seat->pointer_info.frame.event) != gdk_event_get_event_type (event)) |
1498 | gdk_wayland_seat_flush_frame_event (seat); |
1499 | |
1500 | seat->pointer_info.frame.event = event; |
1501 | } |
1502 | |
1503 | static void |
1504 | pointer_handle_enter (void *data, |
1505 | struct wl_pointer *pointer, |
1506 | uint32_t serial, |
1507 | struct wl_surface *surface, |
1508 | wl_fixed_t sx, |
1509 | wl_fixed_t sy) |
1510 | { |
1511 | GdkWaylandSeat *seat = data; |
1512 | GdkEvent *event; |
1513 | GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display); |
1514 | |
1515 | if (!surface) |
1516 | return; |
1517 | |
1518 | if (!GDK_IS_SURFACE (wl_surface_get_user_data (surface))) |
1519 | return; |
1520 | |
1521 | _gdk_wayland_display_update_serial (display_wayland, serial); |
1522 | |
1523 | seat->pointer_info.focus = wl_surface_get_user_data (wl_surface: surface); |
1524 | g_object_ref (seat->pointer_info.focus); |
1525 | |
1526 | seat->pointer_info.button_modifiers = 0; |
1527 | |
1528 | seat->pointer_info.surface_x = wl_fixed_to_double (f: sx); |
1529 | seat->pointer_info.surface_y = wl_fixed_to_double (f: sy); |
1530 | seat->pointer_info.enter_serial = serial; |
1531 | |
1532 | event = gdk_crossing_event_new (type: GDK_ENTER_NOTIFY, |
1533 | surface: seat->pointer_info.focus, |
1534 | device: seat->logical_pointer, |
1535 | time: 0, |
1536 | state: 0, |
1537 | x: seat->pointer_info.surface_x, |
1538 | y: seat->pointer_info.surface_y, |
1539 | mode: GDK_CROSSING_NORMAL, |
1540 | notify: GDK_NOTIFY_NONLINEAR); |
1541 | gdk_wayland_seat_set_frame_event (seat, event); |
1542 | |
1543 | gdk_wayland_device_update_surface_cursor (device: seat->logical_pointer); |
1544 | |
1545 | GDK_SEAT_NOTE (seat, EVENTS, |
1546 | g_message ("enter, seat %p surface %p" , |
1547 | seat, seat->pointer_info.focus)); |
1548 | |
1549 | if (display_wayland->seat_version < WL_POINTER_HAS_FRAME) |
1550 | gdk_wayland_seat_flush_frame_event (seat); |
1551 | } |
1552 | |
1553 | static void |
1554 | pointer_handle_leave (void *data, |
1555 | struct wl_pointer *pointer, |
1556 | uint32_t serial, |
1557 | struct wl_surface *surface) |
1558 | { |
1559 | GdkWaylandSeat *seat = data; |
1560 | GdkEvent *event; |
1561 | GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display); |
1562 | GdkDeviceGrabInfo *grab; |
1563 | |
1564 | if (!seat->pointer_info.focus) |
1565 | return; |
1566 | |
1567 | _gdk_wayland_display_update_serial (display_wayland, serial); |
1568 | grab = _gdk_display_get_last_device_grab (display: seat->display, |
1569 | device: seat->logical_pointer); |
1570 | |
1571 | if (seat->pointer_info.button_modifiers != 0 && |
1572 | grab && grab->implicit) |
1573 | { |
1574 | gulong display_serial; |
1575 | |
1576 | display_serial = _gdk_display_get_next_serial (display: seat->display); |
1577 | _gdk_display_end_device_grab (display: seat->display, device: seat->logical_pointer, |
1578 | serial: display_serial, NULL, TRUE); |
1579 | _gdk_display_device_grab_update (display: seat->display, |
1580 | device: seat->logical_pointer, |
1581 | current_serial: display_serial); |
1582 | } |
1583 | |
1584 | event = gdk_crossing_event_new (type: GDK_LEAVE_NOTIFY, |
1585 | surface: seat->pointer_info.focus, |
1586 | device: seat->logical_pointer, |
1587 | time: 0, |
1588 | state: 0, |
1589 | x: seat->pointer_info.surface_x, |
1590 | y: seat->pointer_info.surface_y, |
1591 | mode: GDK_CROSSING_NORMAL, |
1592 | notify: GDK_NOTIFY_NONLINEAR); |
1593 | gdk_wayland_seat_set_frame_event (seat, event); |
1594 | |
1595 | gdk_wayland_device_update_surface_cursor (device: seat->logical_pointer); |
1596 | |
1597 | GDK_SEAT_NOTE (seat, EVENTS, |
1598 | g_message ("leave, seat %p surface %p" , |
1599 | seat, seat->pointer_info.focus)); |
1600 | |
1601 | g_object_unref (object: seat->pointer_info.focus); |
1602 | seat->pointer_info.focus = NULL; |
1603 | if (seat->cursor) |
1604 | gdk_wayland_pointer_stop_cursor_animation (pointer: &seat->pointer_info); |
1605 | |
1606 | if (display_wayland->seat_version < WL_POINTER_HAS_FRAME) |
1607 | gdk_wayland_seat_flush_frame_event (seat); |
1608 | } |
1609 | |
1610 | static void |
1611 | pointer_handle_motion (void *data, |
1612 | struct wl_pointer *pointer, |
1613 | uint32_t time, |
1614 | wl_fixed_t sx, |
1615 | wl_fixed_t sy) |
1616 | { |
1617 | GdkWaylandSeat *seat = data; |
1618 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
1619 | GdkEvent *event; |
1620 | |
1621 | if (!seat->pointer_info.focus) |
1622 | return; |
1623 | |
1624 | seat->pointer_info.time = time; |
1625 | seat->pointer_info.surface_x = wl_fixed_to_double (f: sx); |
1626 | seat->pointer_info.surface_y = wl_fixed_to_double (f: sy); |
1627 | |
1628 | event = gdk_motion_event_new (surface: seat->pointer_info.focus, |
1629 | device: seat->logical_pointer, |
1630 | NULL, |
1631 | time, |
1632 | state: device_get_modifiers (device: seat->logical_pointer), |
1633 | x: seat->pointer_info.surface_x, |
1634 | y: seat->pointer_info.surface_y, |
1635 | NULL); |
1636 | gdk_wayland_seat_set_frame_event (seat, event); |
1637 | |
1638 | if (GDK_DISPLAY_DEBUG_CHECK (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS)) |
1639 | { |
1640 | double x, y; |
1641 | gdk_event_get_position (event, x: &x, y: &y); |
1642 | g_message ("motion %f %f, seat %p state %d" , |
1643 | x, y, seat, gdk_event_get_modifier_state (event)); |
1644 | } |
1645 | |
1646 | if (display->seat_version < WL_POINTER_HAS_FRAME) |
1647 | gdk_wayland_seat_flush_frame_event (seat); |
1648 | } |
1649 | |
1650 | static void |
1651 | pointer_handle_button (void *data, |
1652 | struct wl_pointer *pointer, |
1653 | uint32_t serial, |
1654 | uint32_t time, |
1655 | uint32_t button, |
1656 | uint32_t state) |
1657 | { |
1658 | GdkWaylandSeat *seat = data; |
1659 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
1660 | GdkEvent *event; |
1661 | uint32_t modifier; |
1662 | int gdk_button; |
1663 | |
1664 | if (!seat->pointer_info.focus) |
1665 | return; |
1666 | |
1667 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
1668 | |
1669 | switch (button) |
1670 | { |
1671 | case BTN_LEFT: |
1672 | gdk_button = GDK_BUTTON_PRIMARY; |
1673 | break; |
1674 | case BTN_MIDDLE: |
1675 | gdk_button = GDK_BUTTON_MIDDLE; |
1676 | break; |
1677 | case BTN_RIGHT: |
1678 | gdk_button = GDK_BUTTON_SECONDARY; |
1679 | break; |
1680 | default: |
1681 | /* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */ |
1682 | gdk_button = button - BUTTON_BASE + 4; |
1683 | break; |
1684 | } |
1685 | |
1686 | seat->pointer_info.time = time; |
1687 | if (state) |
1688 | seat->pointer_info.press_serial = serial; |
1689 | |
1690 | event = gdk_button_event_new (type: state ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE, |
1691 | surface: seat->pointer_info.focus, |
1692 | device: seat->logical_pointer, |
1693 | NULL, |
1694 | time, |
1695 | state: device_get_modifiers (device: seat->logical_pointer), |
1696 | button: gdk_button, |
1697 | x: seat->pointer_info.surface_x, |
1698 | y: seat->pointer_info.surface_y, |
1699 | NULL); |
1700 | |
1701 | gdk_wayland_seat_set_frame_event (seat, event); |
1702 | |
1703 | modifier = (GDK_BUTTON1_MASK << (button - BUTTON_BASE - 1)) & ALL_BUTTONS_MASK; |
1704 | |
1705 | if (state) |
1706 | seat->pointer_info.button_modifiers |= modifier; |
1707 | else |
1708 | seat->pointer_info.button_modifiers &= ~modifier; |
1709 | |
1710 | GDK_SEAT_NOTE (seat, EVENTS, |
1711 | g_message ("button %d %s, seat %p state %d" , |
1712 | gdk_button_event_get_button (event), |
1713 | state ? "press" : "release" , |
1714 | seat, |
1715 | gdk_event_get_modifier_state (event))); |
1716 | |
1717 | if (display->seat_version < WL_POINTER_HAS_FRAME) |
1718 | gdk_wayland_seat_flush_frame_event (seat); |
1719 | } |
1720 | |
1721 | #ifdef G_ENABLE_DEBUG |
1722 | |
1723 | static const char * |
1724 | get_axis_name (uint32_t axis) |
1725 | { |
1726 | switch (axis) |
1727 | { |
1728 | case WL_POINTER_AXIS_VERTICAL_SCROLL: |
1729 | return "horizontal" ; |
1730 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: |
1731 | return "vertical" ; |
1732 | default: |
1733 | return "unknown" ; |
1734 | } |
1735 | } |
1736 | |
1737 | #endif |
1738 | |
1739 | static void |
1740 | pointer_handle_axis (void *data, |
1741 | struct wl_pointer *pointer, |
1742 | uint32_t time, |
1743 | uint32_t axis, |
1744 | wl_fixed_t value) |
1745 | { |
1746 | GdkWaylandSeat *seat = data; |
1747 | GdkWaylandPointerFrameData *pointer_frame = &seat->pointer_info.frame; |
1748 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
1749 | |
1750 | if (!seat->pointer_info.focus) |
1751 | return; |
1752 | |
1753 | /* get the delta and convert it into the expected range */ |
1754 | switch (axis) |
1755 | { |
1756 | case WL_POINTER_AXIS_VERTICAL_SCROLL: |
1757 | pointer_frame->delta_y = wl_fixed_to_double (f: value) / 10.0; |
1758 | break; |
1759 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: |
1760 | pointer_frame->delta_x = wl_fixed_to_double (f: value) / 10.0; |
1761 | break; |
1762 | default: |
1763 | g_return_if_reached (); |
1764 | } |
1765 | |
1766 | seat->pointer_info.time = time; |
1767 | |
1768 | GDK_SEAT_NOTE (seat, EVENTS, |
1769 | g_message ("scroll, axis %s, value %f, seat %p" , |
1770 | get_axis_name (axis), wl_fixed_to_double (value) / 10.0, |
1771 | seat)); |
1772 | |
1773 | if (display->seat_version < WL_POINTER_HAS_FRAME) |
1774 | gdk_wayland_seat_flush_frame_event (seat); |
1775 | } |
1776 | |
1777 | static void |
1778 | pointer_handle_frame (void *data, |
1779 | struct wl_pointer *pointer) |
1780 | { |
1781 | GdkWaylandSeat *seat = data; |
1782 | |
1783 | GDK_SEAT_NOTE (seat, EVENTS, |
1784 | g_message ("frame, seat %p" , seat)); |
1785 | |
1786 | gdk_wayland_seat_flush_frame_event (seat); |
1787 | } |
1788 | |
1789 | #ifdef G_ENABLE_DEBUG |
1790 | |
1791 | static const char * |
1792 | get_axis_source_name (enum wl_pointer_axis_source source) |
1793 | { |
1794 | switch (source) |
1795 | { |
1796 | case WL_POINTER_AXIS_SOURCE_WHEEL: |
1797 | return "wheel" ; |
1798 | case WL_POINTER_AXIS_SOURCE_FINGER: |
1799 | return "finger" ; |
1800 | case WL_POINTER_AXIS_SOURCE_CONTINUOUS: |
1801 | return "continuous" ; |
1802 | case WL_POINTER_AXIS_SOURCE_WHEEL_TILT: |
1803 | return "wheel-tilt" ; |
1804 | default: |
1805 | return "unknown" ; |
1806 | } |
1807 | } |
1808 | |
1809 | #endif |
1810 | |
1811 | static void |
1812 | pointer_handle_axis_source (void *data, |
1813 | struct wl_pointer *pointer, |
1814 | enum wl_pointer_axis_source source) |
1815 | { |
1816 | GdkWaylandSeat *seat = data; |
1817 | GdkWaylandPointerFrameData *pointer_frame = &seat->pointer_info.frame; |
1818 | |
1819 | if (!seat->pointer_info.focus) |
1820 | return; |
1821 | |
1822 | pointer_frame->source = source; |
1823 | |
1824 | GDK_SEAT_NOTE (seat, EVENTS, |
1825 | g_message ("axis source %s, seat %p" , get_axis_source_name (source), seat)); |
1826 | } |
1827 | |
1828 | static void |
1829 | pointer_handle_axis_stop (void *data, |
1830 | struct wl_pointer *pointer, |
1831 | uint32_t time, |
1832 | uint32_t axis) |
1833 | { |
1834 | GdkWaylandSeat *seat = data; |
1835 | GdkWaylandPointerFrameData *pointer_frame = &seat->pointer_info.frame; |
1836 | |
1837 | if (!seat->pointer_info.focus) |
1838 | return; |
1839 | |
1840 | seat->pointer_info.time = time; |
1841 | |
1842 | switch (axis) |
1843 | { |
1844 | case WL_POINTER_AXIS_VERTICAL_SCROLL: |
1845 | pointer_frame->delta_y = 0; |
1846 | break; |
1847 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: |
1848 | pointer_frame->delta_x = 0; |
1849 | break; |
1850 | default: |
1851 | g_return_if_reached (); |
1852 | } |
1853 | |
1854 | pointer_frame->is_scroll_stop = TRUE; |
1855 | |
1856 | GDK_SEAT_NOTE (seat, EVENTS, |
1857 | g_message ("axis %s stop, seat %p" , get_axis_name (axis), seat)); |
1858 | } |
1859 | |
1860 | static void |
1861 | pointer_handle_axis_discrete (void *data, |
1862 | struct wl_pointer *pointer, |
1863 | uint32_t axis, |
1864 | int32_t value) |
1865 | { |
1866 | GdkWaylandSeat *seat = data; |
1867 | GdkWaylandPointerFrameData *pointer_frame = &seat->pointer_info.frame; |
1868 | |
1869 | if (!seat->pointer_info.focus) |
1870 | return; |
1871 | |
1872 | switch (axis) |
1873 | { |
1874 | case WL_POINTER_AXIS_VERTICAL_SCROLL: |
1875 | pointer_frame->discrete_y = value; |
1876 | break; |
1877 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: |
1878 | pointer_frame->discrete_x = value; |
1879 | break; |
1880 | default: |
1881 | g_return_if_reached (); |
1882 | } |
1883 | |
1884 | GDK_SEAT_NOTE (seat, EVENTS, |
1885 | g_message ("discrete scroll, axis %s, value %d, seat %p" , |
1886 | get_axis_name (axis), value, seat)); |
1887 | } |
1888 | |
1889 | static int |
1890 | get_active_layout (GdkKeymap *keymap) |
1891 | { |
1892 | struct xkb_keymap *xkb_keymap; |
1893 | struct xkb_state *xkb_state; |
1894 | |
1895 | xkb_keymap = _gdk_wayland_keymap_get_xkb_keymap (keymap); |
1896 | xkb_state = _gdk_wayland_keymap_get_xkb_state (keymap); |
1897 | |
1898 | for (int i = 0; i < xkb_keymap_num_layouts (keymap: xkb_keymap); i++) |
1899 | { |
1900 | if (xkb_state_layout_index_is_active (state: xkb_state, idx: i, type: XKB_STATE_LAYOUT_EFFECTIVE)) |
1901 | return i; |
1902 | } |
1903 | |
1904 | return -1; |
1905 | } |
1906 | |
1907 | #ifdef G_ENABLE_DEBUG |
1908 | static const char * |
1909 | get_active_layout_name (GdkKeymap *keymap) |
1910 | { |
1911 | struct xkb_keymap *xkb_keymap; |
1912 | |
1913 | xkb_keymap = _gdk_wayland_keymap_get_xkb_keymap (keymap); |
1914 | |
1915 | return xkb_keymap_layout_get_name (keymap: xkb_keymap, idx: get_active_layout (keymap)); |
1916 | } |
1917 | #endif |
1918 | |
1919 | static void |
1920 | keyboard_handle_keymap (void *data, |
1921 | struct wl_keyboard *keyboard, |
1922 | uint32_t format, |
1923 | int fd, |
1924 | uint32_t size) |
1925 | { |
1926 | GdkWaylandSeat *seat = data; |
1927 | PangoDirection direction; |
1928 | gboolean bidi; |
1929 | gboolean caps_lock; |
1930 | gboolean num_lock; |
1931 | gboolean scroll_lock; |
1932 | GdkModifierType modifiers; |
1933 | |
1934 | direction = gdk_keymap_get_direction (keymap: seat->keymap); |
1935 | bidi = gdk_keymap_have_bidi_layouts (keymap: seat->keymap); |
1936 | caps_lock = gdk_keymap_get_caps_lock_state (keymap: seat->keymap); |
1937 | num_lock = gdk_keymap_get_num_lock_state (keymap: seat->keymap); |
1938 | scroll_lock = gdk_keymap_get_scroll_lock_state (keymap: seat->keymap); |
1939 | modifiers = gdk_keymap_get_modifier_state (keymap: seat->keymap); |
1940 | |
1941 | _gdk_wayland_keymap_update_from_fd (keymap: seat->keymap, format, fd, size); |
1942 | |
1943 | GDK_DISPLAY_NOTE(seat->keymap->display, INPUT, |
1944 | { |
1945 | GString *s = g_string_new ("" ); |
1946 | struct xkb_keymap *xkb_keymap = _gdk_wayland_keymap_get_xkb_keymap (seat->keymap); |
1947 | struct xkb_state *xkb_state = _gdk_wayland_keymap_get_xkb_state (seat->keymap); |
1948 | for (int i = 0; i < xkb_keymap_num_layouts (xkb_keymap); i++) |
1949 | { |
1950 | if (s->len > 0) |
1951 | g_string_append (s, ", " ); |
1952 | if (xkb_state_layout_index_is_active (xkb_state, i, XKB_STATE_LAYOUT_EFFECTIVE)) |
1953 | g_string_append (s, "*" ); |
1954 | g_string_append (s, xkb_keymap_layout_get_name (xkb_keymap, i)); |
1955 | } |
1956 | g_print ("layouts: %s\n" , s->str); |
1957 | g_string_free (s, TRUE); |
1958 | }); |
1959 | |
1960 | g_signal_emit_by_name (instance: seat->keymap, detailed_signal: "keys-changed" ); |
1961 | g_signal_emit_by_name (instance: seat->keymap, detailed_signal: "state-changed" ); |
1962 | if (direction != gdk_keymap_get_direction (keymap: seat->keymap)) |
1963 | g_signal_emit_by_name (instance: seat->keymap, detailed_signal: "direction-changed" ); |
1964 | |
1965 | if (direction != gdk_keymap_get_direction (keymap: seat->keymap)) |
1966 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "direction" ); |
1967 | if (bidi != gdk_keymap_have_bidi_layouts (keymap: seat->keymap)) |
1968 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "has-bidi-layouts" ); |
1969 | if (caps_lock != gdk_keymap_get_caps_lock_state (keymap: seat->keymap)) |
1970 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "caps-lock-state" ); |
1971 | if (num_lock != gdk_keymap_get_num_lock_state (keymap: seat->keymap)) |
1972 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "num-lock-state" ); |
1973 | if (scroll_lock != gdk_keymap_get_scroll_lock_state (keymap: seat->keymap)) |
1974 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "scroll-lock-state" ); |
1975 | if (modifiers != gdk_keymap_get_modifier_state (keymap: seat->keymap)) |
1976 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "modifier-state" ); |
1977 | } |
1978 | |
1979 | static void |
1980 | keyboard_handle_enter (void *data, |
1981 | struct wl_keyboard *keyboard, |
1982 | uint32_t serial, |
1983 | struct wl_surface *surface, |
1984 | struct wl_array *keys) |
1985 | { |
1986 | GdkWaylandSeat *seat = data; |
1987 | GdkEvent *event; |
1988 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
1989 | |
1990 | if (!surface) |
1991 | return; |
1992 | |
1993 | if (!GDK_IS_SURFACE (wl_surface_get_user_data (surface))) |
1994 | return; |
1995 | |
1996 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
1997 | |
1998 | seat->keyboard_focus = wl_surface_get_user_data (wl_surface: surface); |
1999 | g_object_ref (seat->keyboard_focus); |
2000 | seat->repeat_key = 0; |
2001 | |
2002 | event = gdk_focus_event_new (surface: seat->keyboard_focus, |
2003 | device: seat->logical_keyboard, |
2004 | TRUE); |
2005 | |
2006 | GDK_SEAT_NOTE (seat, EVENTS, |
2007 | g_message ("focus in, seat %p surface %p" , |
2008 | seat, seat->keyboard_focus)); |
2009 | |
2010 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2011 | } |
2012 | |
2013 | static void stop_key_repeat (GdkWaylandSeat *seat); |
2014 | |
2015 | static void |
2016 | keyboard_handle_leave (void *data, |
2017 | struct wl_keyboard *keyboard, |
2018 | uint32_t serial, |
2019 | struct wl_surface *surface) |
2020 | { |
2021 | GdkWaylandSeat *seat = data; |
2022 | GdkEvent *event; |
2023 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2024 | |
2025 | if (!seat->keyboard_focus) |
2026 | return; |
2027 | |
2028 | /* gdk_surface_is_destroyed() might already return TRUE for |
2029 | * seat->keyboard_focus here, which would happen if we destroyed the |
2030 | * surface before losing keyboard focus. |
2031 | */ |
2032 | stop_key_repeat (seat); |
2033 | |
2034 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2035 | |
2036 | event = gdk_focus_event_new (surface: seat->keyboard_focus, |
2037 | device: seat->logical_keyboard, |
2038 | FALSE); |
2039 | |
2040 | g_object_unref (object: seat->keyboard_focus); |
2041 | seat->keyboard_focus = NULL; |
2042 | seat->repeat_key = 0; |
2043 | seat->key_modifiers = 0; |
2044 | |
2045 | GDK_SEAT_NOTE (seat, EVENTS, |
2046 | g_message ("focus out, seat %p surface %p" , |
2047 | seat, gdk_event_get_surface (event))); |
2048 | |
2049 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2050 | } |
2051 | |
2052 | static gboolean keyboard_repeat (gpointer data); |
2053 | |
2054 | static gboolean |
2055 | get_key_repeat (GdkWaylandSeat *seat, |
2056 | guint *delay, |
2057 | guint *interval) |
2058 | { |
2059 | gboolean repeat; |
2060 | |
2061 | if (seat->have_server_repeat) |
2062 | { |
2063 | if (seat->server_repeat_rate > 0) |
2064 | { |
2065 | repeat = TRUE; |
2066 | *delay = seat->server_repeat_delay; |
2067 | *interval = (1000 / seat->server_repeat_rate); |
2068 | } |
2069 | else |
2070 | { |
2071 | repeat = FALSE; |
2072 | } |
2073 | } |
2074 | else |
2075 | { |
2076 | repeat = TRUE; |
2077 | *delay = 400; |
2078 | *interval = 80; |
2079 | } |
2080 | |
2081 | return repeat; |
2082 | } |
2083 | |
2084 | static void |
2085 | stop_key_repeat (GdkWaylandSeat *seat) |
2086 | { |
2087 | if (seat->repeat_timer) |
2088 | { |
2089 | g_source_remove (tag: seat->repeat_timer); |
2090 | seat->repeat_timer = 0; |
2091 | } |
2092 | |
2093 | g_clear_pointer (&seat->repeat_callback, wl_callback_destroy); |
2094 | } |
2095 | |
2096 | static void |
2097 | deliver_key_event (GdkWaylandSeat *seat, |
2098 | uint32_t time_, |
2099 | uint32_t key, |
2100 | uint32_t state, |
2101 | gboolean from_key_repeat) |
2102 | { |
2103 | GdkEvent *event; |
2104 | struct xkb_state *xkb_state; |
2105 | struct xkb_keymap *xkb_keymap; |
2106 | GdkKeymap *keymap; |
2107 | guint delay, interval, timeout; |
2108 | gint64 begin_time, now; |
2109 | xkb_mod_mask_t consumed; |
2110 | GdkTranslatedKey translated; |
2111 | GdkTranslatedKey no_lock; |
2112 | xkb_mod_mask_t modifiers; |
2113 | xkb_mod_index_t caps_lock; |
2114 | |
2115 | begin_time = g_get_monotonic_time (); |
2116 | |
2117 | stop_key_repeat (seat); |
2118 | |
2119 | keymap = seat->keymap; |
2120 | xkb_state = _gdk_wayland_keymap_get_xkb_state (keymap); |
2121 | xkb_keymap = _gdk_wayland_keymap_get_xkb_keymap (keymap); |
2122 | |
2123 | translated.keyval = xkb_state_key_get_one_sym (state: xkb_state, key); |
2124 | modifiers = xkb_state_serialize_mods (state: xkb_state, components: XKB_STATE_MODS_EFFECTIVE); |
2125 | consumed = modifiers & ~xkb_state_mod_mask_remove_consumed (state: xkb_state, key, mask: modifiers); |
2126 | translated.consumed = gdk_wayland_keymap_get_gdk_modifiers (keymap, mods: consumed); |
2127 | translated.layout = xkb_state_key_get_layout (state: xkb_state, key); |
2128 | translated.level = xkb_state_key_get_level (state: xkb_state, key, layout: translated.layout); |
2129 | |
2130 | if (translated.keyval == XKB_KEY_NoSymbol) |
2131 | return; |
2132 | |
2133 | seat->pointer_info.time = time_; |
2134 | seat->key_modifiers = gdk_keymap_get_modifier_state (keymap); |
2135 | |
2136 | |
2137 | modifiers = xkb_state_serialize_mods (state: xkb_state, components: XKB_STATE_MODS_EFFECTIVE); |
2138 | caps_lock = xkb_keymap_mod_get_index (keymap: xkb_keymap, XKB_MOD_NAME_CAPS); |
2139 | if (modifiers & (1 << caps_lock)) |
2140 | { |
2141 | struct xkb_state *tmp_state = xkb_state_new (keymap: xkb_keymap); |
2142 | xkb_layout_index_t layout; |
2143 | |
2144 | modifiers &= ~(1 << caps_lock); |
2145 | layout = xkb_state_serialize_layout (state: xkb_state, components: XKB_STATE_LAYOUT_EFFECTIVE); |
2146 | xkb_state_update_mask (state: tmp_state, depressed_mods: modifiers, latched_mods: 0, locked_mods: 0, depressed_layout: layout, latched_layout: 0, locked_layout: 0); |
2147 | |
2148 | no_lock.keyval = xkb_state_key_get_one_sym (state: tmp_state, key); |
2149 | consumed = modifiers & ~xkb_state_mod_mask_remove_consumed (state: tmp_state, key, mask: modifiers); |
2150 | no_lock.consumed = gdk_wayland_keymap_get_gdk_modifiers (keymap, mods: consumed); |
2151 | no_lock.layout = xkb_state_key_get_layout (state: tmp_state, key); |
2152 | no_lock.level = xkb_state_key_get_level (state: tmp_state, key, layout: no_lock.layout); |
2153 | |
2154 | xkb_state_unref (state: tmp_state); |
2155 | } |
2156 | else |
2157 | { |
2158 | no_lock = translated; |
2159 | } |
2160 | |
2161 | event = gdk_key_event_new (type: state ? GDK_KEY_PRESS : GDK_KEY_RELEASE, |
2162 | surface: seat->keyboard_focus, |
2163 | device: seat->logical_keyboard, |
2164 | time: time_, |
2165 | keycode: key, |
2166 | modifiers: device_get_modifiers (device: seat->logical_pointer), |
2167 | is_modifier: _gdk_wayland_keymap_key_is_modifier (keymap, keycode: key), |
2168 | translated: &translated, |
2169 | no_lock: &no_lock); |
2170 | |
2171 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2172 | |
2173 | GDK_SEAT_NOTE (seat, EVENTS, |
2174 | g_message ("keyboard %s event%s, surface %p, code %d, sym %d, " |
2175 | "mods 0x%x, consumed 0x%x, layout %d level %d" , |
2176 | (state ? "press" : "release" ), |
2177 | (from_key_repeat ? " (repeat)" : "" ), |
2178 | gdk_event_get_surface (event), |
2179 | gdk_key_event_get_keycode (event), |
2180 | gdk_key_event_get_keyval (event), |
2181 | gdk_event_get_modifier_state (event), |
2182 | gdk_key_event_get_consumed_modifiers (event), |
2183 | gdk_key_event_get_layout (event), |
2184 | gdk_key_event_get_level (event))); |
2185 | |
2186 | if (!xkb_keymap_key_repeats (keymap: xkb_keymap, key)) |
2187 | return; |
2188 | |
2189 | if (!get_key_repeat (seat, delay: &delay, interval: &interval)) |
2190 | return; |
2191 | |
2192 | if (!from_key_repeat) |
2193 | { |
2194 | if (state) /* Another key is pressed */ |
2195 | { |
2196 | seat->repeat_key = key; |
2197 | } |
2198 | else if (seat->repeat_key == key) /* Repeated key is released */ |
2199 | { |
2200 | seat->repeat_key = 0; |
2201 | } |
2202 | } |
2203 | |
2204 | if (!seat->repeat_key) |
2205 | return; |
2206 | |
2207 | seat->repeat_count++; |
2208 | |
2209 | interval *= 1000L; |
2210 | delay *= 1000L; |
2211 | |
2212 | now = g_get_monotonic_time (); |
2213 | |
2214 | if (seat->repeat_count == 1) |
2215 | seat->repeat_deadline = begin_time + delay; |
2216 | else if (seat->repeat_deadline + interval > now) |
2217 | seat->repeat_deadline += interval; |
2218 | else |
2219 | /* frame delay caused us to miss repeat deadline */ |
2220 | seat->repeat_deadline = now; |
2221 | |
2222 | timeout = (seat->repeat_deadline - now) / 1000L; |
2223 | |
2224 | seat->repeat_timer = g_timeout_add (interval: timeout, function: keyboard_repeat, data: seat); |
2225 | gdk_source_set_static_name_by_id (tag: seat->repeat_timer, name: "[gtk] keyboard_repeat" ); |
2226 | } |
2227 | |
2228 | static void |
2229 | sync_after_repeat_callback (void *data, |
2230 | struct wl_callback *callback, |
2231 | uint32_t time) |
2232 | { |
2233 | GdkWaylandSeat *seat = data; |
2234 | |
2235 | g_clear_pointer (&seat->repeat_callback, wl_callback_destroy); |
2236 | deliver_key_event (seat, time_: seat->keyboard_time, key: seat->repeat_key, state: 1, TRUE); |
2237 | } |
2238 | |
2239 | static const struct wl_callback_listener sync_after_repeat_callback_listener = { |
2240 | sync_after_repeat_callback |
2241 | }; |
2242 | |
2243 | static gboolean |
2244 | keyboard_repeat (gpointer data) |
2245 | { |
2246 | GdkWaylandSeat *seat = data; |
2247 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2248 | |
2249 | /* Ping the server and wait for the timeout. We won't process |
2250 | * key repeat until it responds, since a hung server could lead |
2251 | * to a delayed key release event. We don't want to generate |
2252 | * repeat events long after the user released the key, just because |
2253 | * the server is tardy in telling us the user released the key. |
2254 | */ |
2255 | seat->repeat_callback = wl_display_sync (wl_display: display->wl_display); |
2256 | |
2257 | wl_callback_add_listener (wl_callback: seat->repeat_callback, |
2258 | listener: &sync_after_repeat_callback_listener, |
2259 | data: seat); |
2260 | |
2261 | seat->repeat_timer = 0; |
2262 | return G_SOURCE_REMOVE; |
2263 | } |
2264 | |
2265 | static void |
2266 | keyboard_handle_key (void *data, |
2267 | struct wl_keyboard *keyboard, |
2268 | uint32_t serial, |
2269 | uint32_t time, |
2270 | uint32_t key, |
2271 | uint32_t state_w) |
2272 | { |
2273 | GdkWaylandSeat *seat = data; |
2274 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2275 | |
2276 | if (!seat->keyboard_focus) |
2277 | return; |
2278 | |
2279 | seat->keyboard_time = time; |
2280 | seat->keyboard_key_serial = serial; |
2281 | seat->repeat_count = 0; |
2282 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2283 | deliver_key_event (seat: data, time_: time, key: key + 8, state: state_w, FALSE); |
2284 | |
2285 | } |
2286 | |
2287 | static void |
2288 | keyboard_handle_modifiers (void *data, |
2289 | struct wl_keyboard *keyboard, |
2290 | uint32_t serial, |
2291 | uint32_t mods_depressed, |
2292 | uint32_t mods_latched, |
2293 | uint32_t mods_locked, |
2294 | uint32_t group) |
2295 | { |
2296 | GdkWaylandSeat *seat = data; |
2297 | GdkKeymap *keymap; |
2298 | struct xkb_state *xkb_state; |
2299 | PangoDirection direction; |
2300 | gboolean bidi; |
2301 | gboolean caps_lock; |
2302 | gboolean num_lock; |
2303 | gboolean scroll_lock; |
2304 | GdkModifierType modifiers; |
2305 | int layout; |
2306 | |
2307 | keymap = seat->keymap; |
2308 | xkb_state = _gdk_wayland_keymap_get_xkb_state (keymap); |
2309 | |
2310 | direction = gdk_keymap_get_direction (keymap); |
2311 | bidi = gdk_keymap_have_bidi_layouts (keymap); |
2312 | caps_lock = gdk_keymap_get_caps_lock_state (keymap); |
2313 | num_lock = gdk_keymap_get_num_lock_state (keymap); |
2314 | scroll_lock = gdk_keymap_get_scroll_lock_state (keymap); |
2315 | modifiers = gdk_keymap_get_modifier_state (keymap); |
2316 | layout = get_active_layout (keymap); |
2317 | |
2318 | /* Note: the docs for xkb_state_update mask state that all parameters |
2319 | * must be passed, or we may end up with an 'incoherent' state. But the |
2320 | * Wayland modifiers event only includes a single group field, so we |
2321 | * can't pass depressed/latched/locked groups. |
2322 | * |
2323 | * We assume that the compositor is sending us the 'effective' group |
2324 | * (the protocol is not clear on that point), and pass it as the depressed |
2325 | * group - we are basically pretending that the user holds down a key for |
2326 | * this group at all times. |
2327 | * |
2328 | * This means that our xkb_state would answer a few questions differently |
2329 | * from the compositors xkb_state - e.g. if you asked it about the latched |
2330 | * group. But nobody is asking it those questions, so it does not really |
2331 | * matter. We hope. |
2332 | */ |
2333 | xkb_state_update_mask (state: xkb_state, depressed_mods: mods_depressed, latched_mods: mods_latched, locked_mods: mods_locked, depressed_layout: group, latched_layout: 0, locked_layout: 0); |
2334 | |
2335 | seat->key_modifiers = gdk_keymap_get_modifier_state (keymap); |
2336 | |
2337 | g_signal_emit_by_name (instance: keymap, detailed_signal: "state-changed" ); |
2338 | if (layout != get_active_layout (keymap)) |
2339 | { |
2340 | GDK_DISPLAY_NOTE(keymap->display, INPUT, g_print ("active layout now: %s\n" , get_active_layout_name (keymap))); |
2341 | |
2342 | g_signal_emit_by_name (instance: keymap, detailed_signal: "keys-changed" ); |
2343 | } |
2344 | if (direction != gdk_keymap_get_direction (keymap)) |
2345 | { |
2346 | g_signal_emit_by_name (instance: keymap, detailed_signal: "direction-changed" ); |
2347 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "direction" ); |
2348 | } |
2349 | if (bidi != gdk_keymap_have_bidi_layouts (keymap)) |
2350 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "has-bidi-layouts" ); |
2351 | if (caps_lock != gdk_keymap_get_caps_lock_state (keymap)) |
2352 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "caps-lock-state" ); |
2353 | if (num_lock != gdk_keymap_get_num_lock_state (keymap)) |
2354 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "num-lock-state" ); |
2355 | if (scroll_lock != gdk_keymap_get_scroll_lock_state (keymap)) |
2356 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "scroll-lock-state" ); |
2357 | if (modifiers != gdk_keymap_get_modifier_state (keymap)) |
2358 | g_object_notify (G_OBJECT (seat->logical_keyboard), property_name: "modifier-state" ); |
2359 | } |
2360 | |
2361 | static void |
2362 | keyboard_handle_repeat_info (void *data, |
2363 | struct wl_keyboard *keyboard, |
2364 | int32_t rate, |
2365 | int32_t delay) |
2366 | { |
2367 | GdkWaylandSeat *seat = data; |
2368 | |
2369 | seat->have_server_repeat = TRUE; |
2370 | seat->server_repeat_rate = rate; |
2371 | seat->server_repeat_delay = delay; |
2372 | } |
2373 | |
2374 | static GdkWaylandTouchData * |
2375 | gdk_wayland_seat_add_touch (GdkWaylandSeat *seat, |
2376 | uint32_t id, |
2377 | struct wl_surface *surface) |
2378 | { |
2379 | GdkWaylandTouchData *touch; |
2380 | |
2381 | touch = g_new0 (GdkWaylandTouchData, 1); |
2382 | touch->id = id; |
2383 | touch->surface = wl_surface_get_user_data (wl_surface: surface); |
2384 | touch->initial_touch = (g_hash_table_size (hash_table: seat->touches) == 0); |
2385 | |
2386 | g_hash_table_insert (hash_table: seat->touches, GUINT_TO_POINTER (id), value: touch); |
2387 | |
2388 | return touch; |
2389 | } |
2390 | |
2391 | static GdkWaylandTouchData * |
2392 | gdk_wayland_seat_get_touch (GdkWaylandSeat *seat, |
2393 | uint32_t id) |
2394 | { |
2395 | return g_hash_table_lookup (hash_table: seat->touches, GUINT_TO_POINTER (id)); |
2396 | } |
2397 | |
2398 | static void |
2399 | gdk_wayland_seat_remove_touch (GdkWaylandSeat *seat, |
2400 | uint32_t id) |
2401 | { |
2402 | g_hash_table_remove (hash_table: seat->touches, GUINT_TO_POINTER (id)); |
2403 | } |
2404 | |
2405 | void |
2406 | gdk_wayland_seat_clear_touchpoints (GdkWaylandSeat *seat, |
2407 | GdkSurface *surface) |
2408 | { |
2409 | GHashTableIter iter; |
2410 | GdkWaylandTouchData *touch; |
2411 | |
2412 | g_hash_table_iter_init (iter: &iter, hash_table: seat->touches); |
2413 | |
2414 | while (g_hash_table_iter_next (iter: &iter, NULL, value: (gpointer *) &touch)) |
2415 | { |
2416 | if (touch->surface == surface) |
2417 | g_hash_table_iter_remove (iter: &iter); |
2418 | } |
2419 | } |
2420 | |
2421 | static void |
2422 | mimic_pointer_emulating_touch_info (GdkDevice *device, |
2423 | GdkWaylandTouchData *touch) |
2424 | { |
2425 | GdkWaylandPointerData *pointer; |
2426 | |
2427 | pointer = GDK_WAYLAND_DEVICE (device)->pointer; |
2428 | g_set_object (&pointer->focus, touch->surface); |
2429 | pointer->press_serial = pointer->enter_serial = touch->touch_down_serial; |
2430 | pointer->surface_x = touch->x; |
2431 | pointer->surface_y = touch->y; |
2432 | } |
2433 | |
2434 | static void |
2435 | touch_handle_logical_pointer_crossing (GdkWaylandSeat *seat, |
2436 | GdkWaylandTouchData *touch, |
2437 | uint32_t time) |
2438 | { |
2439 | GdkWaylandPointerData *pointer; |
2440 | |
2441 | pointer = GDK_WAYLAND_DEVICE (seat->logical_touch)->pointer; |
2442 | |
2443 | if (pointer->focus == touch->surface) |
2444 | return; |
2445 | |
2446 | if (pointer->focus) |
2447 | { |
2448 | emulate_touch_crossing (surface: pointer->focus, NULL, |
2449 | device: seat->logical_touch, source: seat->touch, touch, |
2450 | type: GDK_LEAVE_NOTIFY, mode: GDK_CROSSING_NORMAL, time_: time); |
2451 | } |
2452 | |
2453 | if (touch->surface) |
2454 | { |
2455 | emulate_touch_crossing (surface: touch->surface, NULL, |
2456 | device: seat->logical_touch, source: seat->touch, touch, |
2457 | type: GDK_ENTER_NOTIFY, mode: GDK_CROSSING_NORMAL, time_: time); |
2458 | } |
2459 | } |
2460 | |
2461 | static void |
2462 | touch_handle_down (void *data, |
2463 | struct wl_touch *wl_touch, |
2464 | uint32_t serial, |
2465 | uint32_t time, |
2466 | struct wl_surface *wl_surface, |
2467 | int32_t id, |
2468 | wl_fixed_t x, |
2469 | wl_fixed_t y) |
2470 | { |
2471 | GdkWaylandSeat *seat = data; |
2472 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2473 | GdkWaylandTouchData *touch; |
2474 | GdkEvent *event; |
2475 | |
2476 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2477 | |
2478 | if (!wl_surface) |
2479 | return; |
2480 | |
2481 | touch = gdk_wayland_seat_add_touch (seat, id, surface: wl_surface); |
2482 | touch->x = wl_fixed_to_double (f: x); |
2483 | touch->y = wl_fixed_to_double (f: y); |
2484 | touch->touch_down_serial = serial; |
2485 | |
2486 | event = gdk_touch_event_new (type: GDK_TOUCH_BEGIN, |
2487 | GDK_SLOT_TO_EVENT_SEQUENCE (touch->id), |
2488 | surface: touch->surface, |
2489 | device: seat->logical_touch, |
2490 | time, |
2491 | state: device_get_modifiers (device: seat->logical_touch), |
2492 | x: touch->x, y: touch->y, |
2493 | NULL, |
2494 | emulating: touch->initial_touch); |
2495 | |
2496 | if (touch->initial_touch) |
2497 | { |
2498 | touch_handle_logical_pointer_crossing (seat, touch, time); |
2499 | GDK_WAYLAND_DEVICE(seat->logical_touch)->emulating_touch = touch; |
2500 | mimic_pointer_emulating_touch_info (device: seat->logical_touch, touch); |
2501 | } |
2502 | |
2503 | if (GDK_DISPLAY_DEBUG_CHECK (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS)) |
2504 | { |
2505 | double xx, yy; |
2506 | gdk_event_get_position (event, x: &xx, y: &yy); |
2507 | g_message ("touch begin %f %f" , xx, yy); |
2508 | } |
2509 | |
2510 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2511 | } |
2512 | |
2513 | static void |
2514 | touch_handle_up (void *data, |
2515 | struct wl_touch *wl_touch, |
2516 | uint32_t serial, |
2517 | uint32_t time, |
2518 | int32_t id) |
2519 | { |
2520 | GdkWaylandSeat *seat = data; |
2521 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2522 | GdkWaylandTouchData *touch; |
2523 | GdkEvent *event; |
2524 | |
2525 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2526 | |
2527 | touch = gdk_wayland_seat_get_touch (seat, id); |
2528 | if (!touch) |
2529 | return; |
2530 | |
2531 | event = gdk_touch_event_new (type: GDK_TOUCH_END, |
2532 | GDK_SLOT_TO_EVENT_SEQUENCE (touch->id), |
2533 | surface: touch->surface, |
2534 | device: seat->logical_touch, |
2535 | time, |
2536 | state: device_get_modifiers (device: seat->logical_touch), |
2537 | x: touch->x, y: touch->y, |
2538 | NULL, |
2539 | emulating: touch->initial_touch); |
2540 | |
2541 | if (GDK_DISPLAY_DEBUG_CHECK (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS)) |
2542 | { |
2543 | double x, y; |
2544 | gdk_event_get_position (event, x: &x, y: &y); |
2545 | g_message ("touch end %f %f" , x, y); |
2546 | } |
2547 | |
2548 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2549 | |
2550 | if (touch->initial_touch) |
2551 | GDK_WAYLAND_DEVICE(seat->logical_touch)->emulating_touch = NULL; |
2552 | |
2553 | gdk_wayland_seat_remove_touch (seat, id); |
2554 | } |
2555 | |
2556 | static void |
2557 | touch_handle_motion (void *data, |
2558 | struct wl_touch *wl_touch, |
2559 | uint32_t time, |
2560 | int32_t id, |
2561 | wl_fixed_t x, |
2562 | wl_fixed_t y) |
2563 | { |
2564 | GdkWaylandSeat *seat = data; |
2565 | GdkWaylandTouchData *touch; |
2566 | GdkEvent *event; |
2567 | |
2568 | touch = gdk_wayland_seat_get_touch (seat, id); |
2569 | if (!touch) |
2570 | return; |
2571 | |
2572 | touch->x = wl_fixed_to_double (f: x); |
2573 | touch->y = wl_fixed_to_double (f: y); |
2574 | |
2575 | if (touch->initial_touch) |
2576 | mimic_pointer_emulating_touch_info (device: seat->logical_touch, touch); |
2577 | |
2578 | event = gdk_touch_event_new (type: GDK_TOUCH_UPDATE, |
2579 | GDK_SLOT_TO_EVENT_SEQUENCE (touch->id), |
2580 | surface: touch->surface, |
2581 | device: seat->logical_touch, |
2582 | time, |
2583 | state: device_get_modifiers (device: seat->logical_touch), |
2584 | x: touch->x, y: touch->y, |
2585 | NULL, |
2586 | emulating: touch->initial_touch); |
2587 | |
2588 | if (GDK_DISPLAY_DEBUG_CHECK (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS)) |
2589 | { |
2590 | double xx, yy; |
2591 | gdk_event_get_position (event, x: &xx, y: &yy); |
2592 | g_message ("touch update %f %f" , xx, yy); |
2593 | } |
2594 | |
2595 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2596 | } |
2597 | |
2598 | static void |
2599 | touch_handle_frame (void *data, |
2600 | struct wl_touch *wl_touch) |
2601 | { |
2602 | } |
2603 | |
2604 | static void |
2605 | touch_handle_cancel (void *data, |
2606 | struct wl_touch *wl_touch) |
2607 | { |
2608 | GdkWaylandSeat *seat = data; |
2609 | GdkWaylandTouchData *touch; |
2610 | GHashTableIter iter; |
2611 | GdkEvent *event; |
2612 | |
2613 | if (GDK_WAYLAND_DEVICE (seat->logical_touch)->emulating_touch) |
2614 | { |
2615 | touch = GDK_WAYLAND_DEVICE (seat->logical_touch)->emulating_touch; |
2616 | GDK_WAYLAND_DEVICE (seat->logical_touch)->emulating_touch = NULL; |
2617 | } |
2618 | |
2619 | g_hash_table_iter_init (iter: &iter, hash_table: seat->touches); |
2620 | |
2621 | while (g_hash_table_iter_next (iter: &iter, NULL, value: (gpointer *) &touch)) |
2622 | { |
2623 | event = gdk_touch_event_new (type: GDK_TOUCH_CANCEL, |
2624 | GDK_SLOT_TO_EVENT_SEQUENCE (touch->id), |
2625 | surface: touch->surface, |
2626 | device: seat->logical_touch, |
2627 | GDK_CURRENT_TIME, |
2628 | state: device_get_modifiers (device: seat->logical_touch), |
2629 | x: touch->x, y: touch->y, |
2630 | NULL, |
2631 | emulating: touch->initial_touch); |
2632 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2633 | g_hash_table_iter_remove (iter: &iter); |
2634 | } |
2635 | |
2636 | GDK_SEAT_NOTE (seat, EVENTS, g_message ("touch cancel" )); |
2637 | } |
2638 | |
2639 | static void |
2640 | touch_handle_shape (void *data, |
2641 | struct wl_touch *touch, |
2642 | int32_t id, |
2643 | wl_fixed_t major, |
2644 | wl_fixed_t minor) |
2645 | { |
2646 | } |
2647 | |
2648 | static void |
2649 | touch_handle_orientation (void *data, |
2650 | struct wl_touch *touch, |
2651 | int32_t id, |
2652 | wl_fixed_t orientation) |
2653 | { |
2654 | } |
2655 | |
2656 | static void |
2657 | emit_gesture_swipe_event (GdkWaylandSeat *seat, |
2658 | GdkTouchpadGesturePhase phase, |
2659 | guint32 _time, |
2660 | guint32 n_fingers, |
2661 | double dx, |
2662 | double dy) |
2663 | { |
2664 | GdkEvent *event; |
2665 | |
2666 | if (!seat->pointer_info.focus) |
2667 | return; |
2668 | |
2669 | seat->pointer_info.time = _time; |
2670 | |
2671 | if (phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN) |
2672 | seat->pointer_info.touchpad_event_sequence++; |
2673 | |
2674 | event = gdk_touchpad_event_new_swipe (surface: seat->pointer_info.focus, |
2675 | GDK_SLOT_TO_EVENT_SEQUENCE (seat->pointer_info.touchpad_event_sequence), |
2676 | device: seat->logical_pointer, |
2677 | time: _time, |
2678 | state: device_get_modifiers (device: seat->logical_pointer), |
2679 | phase, |
2680 | x: seat->pointer_info.surface_x, |
2681 | y: seat->pointer_info.surface_y, |
2682 | n_fingers, |
2683 | dx, dy); |
2684 | |
2685 | if (GDK_DISPLAY_DEBUG_CHECK (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS)) |
2686 | { |
2687 | double x, y; |
2688 | gdk_event_get_position (event, x: &x, y: &y); |
2689 | g_message ("swipe event %d, coords: %f %f, seat %p state %d" , |
2690 | gdk_event_get_event_type (event), x, y, seat, |
2691 | gdk_event_get_modifier_state (event)); |
2692 | } |
2693 | |
2694 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2695 | } |
2696 | |
2697 | static void |
2698 | gesture_swipe_begin (void *data, |
2699 | struct zwp_pointer_gesture_swipe_v1 *swipe, |
2700 | uint32_t serial, |
2701 | uint32_t time, |
2702 | struct wl_surface *surface, |
2703 | uint32_t fingers) |
2704 | { |
2705 | GdkWaylandSeat *seat = data; |
2706 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2707 | |
2708 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2709 | |
2710 | emit_gesture_swipe_event (seat, |
2711 | phase: GDK_TOUCHPAD_GESTURE_PHASE_BEGIN, |
2712 | time: time, n_fingers: fingers, dx: 0, dy: 0); |
2713 | seat->gesture_n_fingers = fingers; |
2714 | } |
2715 | |
2716 | static void |
2717 | gesture_swipe_update (void *data, |
2718 | struct zwp_pointer_gesture_swipe_v1 *swipe, |
2719 | uint32_t time, |
2720 | wl_fixed_t dx, |
2721 | wl_fixed_t dy) |
2722 | { |
2723 | GdkWaylandSeat *seat = data; |
2724 | |
2725 | emit_gesture_swipe_event (seat, |
2726 | phase: GDK_TOUCHPAD_GESTURE_PHASE_UPDATE, |
2727 | time: time, |
2728 | n_fingers: seat->gesture_n_fingers, |
2729 | dx: wl_fixed_to_double (f: dx), |
2730 | dy: wl_fixed_to_double (f: dy)); |
2731 | } |
2732 | |
2733 | static void |
2734 | gesture_swipe_end (void *data, |
2735 | struct zwp_pointer_gesture_swipe_v1 *swipe, |
2736 | uint32_t serial, |
2737 | uint32_t time, |
2738 | int32_t cancelled) |
2739 | { |
2740 | GdkWaylandSeat *seat = data; |
2741 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2742 | GdkTouchpadGesturePhase phase; |
2743 | |
2744 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2745 | |
2746 | phase = (cancelled) ? |
2747 | GDK_TOUCHPAD_GESTURE_PHASE_CANCEL : |
2748 | GDK_TOUCHPAD_GESTURE_PHASE_END; |
2749 | |
2750 | emit_gesture_swipe_event (seat, phase, time: time, |
2751 | n_fingers: seat->gesture_n_fingers, dx: 0, dy: 0); |
2752 | } |
2753 | |
2754 | static void |
2755 | emit_gesture_pinch_event (GdkWaylandSeat *seat, |
2756 | GdkTouchpadGesturePhase phase, |
2757 | guint32 _time, |
2758 | guint n_fingers, |
2759 | double dx, |
2760 | double dy, |
2761 | double scale, |
2762 | double angle_delta) |
2763 | { |
2764 | GdkEvent *event; |
2765 | |
2766 | if (!seat->pointer_info.focus) |
2767 | return; |
2768 | |
2769 | seat->pointer_info.time = _time; |
2770 | |
2771 | if (phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN) |
2772 | seat->pointer_info.touchpad_event_sequence++; |
2773 | |
2774 | event = gdk_touchpad_event_new_pinch (surface: seat->pointer_info.focus, |
2775 | GDK_SLOT_TO_EVENT_SEQUENCE (seat->pointer_info.touchpad_event_sequence), |
2776 | device: seat->logical_pointer, |
2777 | time: _time, |
2778 | state: device_get_modifiers (device: seat->logical_pointer), |
2779 | phase, |
2780 | x: seat->pointer_info.surface_x, |
2781 | y: seat->pointer_info.surface_y, |
2782 | n_fingers, |
2783 | dx, dy, |
2784 | scale, angle_delta: angle_delta * G_PI / 180); |
2785 | |
2786 | if (GDK_DISPLAY_DEBUG_CHECK (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS)) |
2787 | { |
2788 | double x, y; |
2789 | gdk_event_get_position (event, x: &x, y: &y); |
2790 | g_message ("pinch event %d, coords: %f %f, seat %p state %d" , |
2791 | gdk_event_get_event_type (event), |
2792 | x, y, seat, |
2793 | gdk_event_get_modifier_state (event)); |
2794 | } |
2795 | |
2796 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2797 | } |
2798 | |
2799 | static void |
2800 | gesture_pinch_begin (void *data, |
2801 | struct zwp_pointer_gesture_pinch_v1 *pinch, |
2802 | uint32_t serial, |
2803 | uint32_t time, |
2804 | struct wl_surface *surface, |
2805 | uint32_t fingers) |
2806 | { |
2807 | GdkWaylandSeat *seat = data; |
2808 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2809 | |
2810 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2811 | emit_gesture_pinch_event (seat, |
2812 | phase: GDK_TOUCHPAD_GESTURE_PHASE_BEGIN, |
2813 | time: time, n_fingers: fingers, dx: 0, dy: 0, scale: 1, angle_delta: 0); |
2814 | seat->gesture_n_fingers = fingers; |
2815 | } |
2816 | |
2817 | static void |
2818 | gesture_pinch_update (void *data, |
2819 | struct zwp_pointer_gesture_pinch_v1 *pinch, |
2820 | uint32_t time, |
2821 | wl_fixed_t dx, |
2822 | wl_fixed_t dy, |
2823 | wl_fixed_t scale, |
2824 | wl_fixed_t rotation) |
2825 | { |
2826 | GdkWaylandSeat *seat = data; |
2827 | |
2828 | emit_gesture_pinch_event (seat, |
2829 | phase: GDK_TOUCHPAD_GESTURE_PHASE_UPDATE, time: time, |
2830 | n_fingers: seat->gesture_n_fingers, |
2831 | dx: wl_fixed_to_double (f: dx), |
2832 | dy: wl_fixed_to_double (f: dy), |
2833 | scale: wl_fixed_to_double (f: scale), |
2834 | angle_delta: wl_fixed_to_double (f: rotation)); |
2835 | } |
2836 | |
2837 | static void |
2838 | gesture_pinch_end (void *data, |
2839 | struct zwp_pointer_gesture_pinch_v1 *pinch, |
2840 | uint32_t serial, |
2841 | uint32_t time, |
2842 | int32_t cancelled) |
2843 | { |
2844 | GdkWaylandSeat *seat = data; |
2845 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2846 | GdkTouchpadGesturePhase phase; |
2847 | |
2848 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2849 | |
2850 | phase = (cancelled) ? |
2851 | GDK_TOUCHPAD_GESTURE_PHASE_CANCEL : |
2852 | GDK_TOUCHPAD_GESTURE_PHASE_END; |
2853 | |
2854 | emit_gesture_pinch_event (seat, phase, |
2855 | time: time, n_fingers: seat->gesture_n_fingers, |
2856 | dx: 0, dy: 0, scale: 1, angle_delta: 0); |
2857 | } |
2858 | |
2859 | static void |
2860 | emit_gesture_hold_event (GdkWaylandSeat *seat, |
2861 | GdkTouchpadGesturePhase phase, |
2862 | guint32 _time, |
2863 | guint32 n_fingers) |
2864 | { |
2865 | GdkEvent *event; |
2866 | |
2867 | if (!seat->pointer_info.focus) |
2868 | return; |
2869 | |
2870 | seat->pointer_info.time = _time; |
2871 | |
2872 | event = gdk_touchpad_event_new_hold (surface: seat->pointer_info.focus, |
2873 | device: seat->logical_pointer, |
2874 | time: _time, |
2875 | state: device_get_modifiers (device: seat->logical_pointer), |
2876 | phase, |
2877 | x: seat->pointer_info.surface_x, |
2878 | y: seat->pointer_info.surface_y, |
2879 | n_fingers); |
2880 | |
2881 | if (GDK_DISPLAY_DEBUG_CHECK (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS)) |
2882 | { |
2883 | double x, y; |
2884 | gdk_event_get_position (event, x: &x, y: &y); |
2885 | g_message ("hold event %d, coords: %f %f, seat %p state %d" , |
2886 | gdk_event_get_event_type (event), |
2887 | x, y, seat, |
2888 | gdk_event_get_modifier_state (event)); |
2889 | } |
2890 | |
2891 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
2892 | } |
2893 | |
2894 | static void |
2895 | gesture_hold_begin (void *data, |
2896 | struct zwp_pointer_gesture_hold_v1 *hold, |
2897 | uint32_t serial, |
2898 | uint32_t time, |
2899 | struct wl_surface *surface, |
2900 | uint32_t fingers) |
2901 | { |
2902 | GdkWaylandSeat *seat = data; |
2903 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2904 | |
2905 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2906 | |
2907 | emit_gesture_hold_event (seat, |
2908 | phase: GDK_TOUCHPAD_GESTURE_PHASE_BEGIN, |
2909 | time: time, n_fingers: fingers); |
2910 | seat->gesture_n_fingers = fingers; |
2911 | } |
2912 | |
2913 | static void |
2914 | gesture_hold_end (void *data, |
2915 | struct zwp_pointer_gesture_hold_v1 *hold, |
2916 | uint32_t serial, |
2917 | uint32_t time, |
2918 | int32_t cancelled) |
2919 | { |
2920 | GdkWaylandSeat *seat = data; |
2921 | GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (seat->display); |
2922 | GdkTouchpadGesturePhase phase; |
2923 | |
2924 | _gdk_wayland_display_update_serial (display_wayland: display, serial); |
2925 | |
2926 | phase = (cancelled) ? |
2927 | GDK_TOUCHPAD_GESTURE_PHASE_CANCEL : |
2928 | GDK_TOUCHPAD_GESTURE_PHASE_END; |
2929 | |
2930 | emit_gesture_hold_event (seat, phase, time: time, |
2931 | n_fingers: seat->gesture_n_fingers); |
2932 | } |
2933 | |
2934 | static void |
2935 | _gdk_wayland_seat_remove_tool (GdkWaylandSeat *seat, |
2936 | GdkWaylandTabletToolData *tool) |
2937 | { |
2938 | seat->tablet_tools = g_list_remove (list: seat->tablet_tools, data: tool); |
2939 | |
2940 | gdk_seat_tool_removed (GDK_SEAT (seat), tool: tool->tool); |
2941 | |
2942 | zwp_tablet_tool_v2_destroy (tool->wp_tablet_tool); |
2943 | g_object_unref (object: tool->tool); |
2944 | g_free (mem: tool); |
2945 | } |
2946 | |
2947 | static void |
2948 | _gdk_wayland_seat_remove_tablet (GdkWaylandSeat *seat, |
2949 | GdkWaylandTabletData *tablet) |
2950 | { |
2951 | seat->tablets = g_list_remove (list: seat->tablets, data: tablet); |
2952 | |
2953 | gdk_seat_device_removed (GDK_SEAT (seat), device: tablet->stylus_device); |
2954 | gdk_seat_device_removed (GDK_SEAT (seat), device: tablet->logical_device); |
2955 | |
2956 | while (tablet->pads) |
2957 | { |
2958 | GdkWaylandTabletPadData *pad = tablet->pads->data; |
2959 | |
2960 | pad->current_tablet = NULL; |
2961 | tablet->pads = g_list_remove (list: tablet->pads, data: pad); |
2962 | } |
2963 | |
2964 | zwp_tablet_v2_destroy (tablet->wp_tablet); |
2965 | |
2966 | _gdk_device_set_associated_device (device: tablet->logical_device, NULL); |
2967 | _gdk_device_set_associated_device (device: tablet->stylus_device, NULL); |
2968 | |
2969 | if (tablet->pointer_info.focus) |
2970 | g_object_unref (object: tablet->pointer_info.focus); |
2971 | |
2972 | wl_surface_destroy (wl_surface: tablet->pointer_info.pointer_surface); |
2973 | g_object_unref (object: tablet->logical_device); |
2974 | g_object_unref (object: tablet->stylus_device); |
2975 | g_free (mem: tablet); |
2976 | } |
2977 | |
2978 | static void |
2979 | _gdk_wayland_seat_remove_tablet_pad (GdkWaylandSeat *seat, |
2980 | GdkWaylandTabletPadData *pad) |
2981 | { |
2982 | seat->tablet_pads = g_list_remove (list: seat->tablet_pads, data: pad); |
2983 | |
2984 | gdk_seat_device_removed (GDK_SEAT (seat), device: pad->device); |
2985 | _gdk_device_set_associated_device (device: pad->device, NULL); |
2986 | |
2987 | g_object_unref (object: pad->device); |
2988 | g_free (mem: pad); |
2989 | } |
2990 | |
2991 | static GdkWaylandTabletPadGroupData * |
2992 | tablet_pad_lookup_button_group (GdkWaylandTabletPadData *pad, |
2993 | uint32_t button) |
2994 | { |
2995 | GdkWaylandTabletPadGroupData *group; |
2996 | GList *l; |
2997 | |
2998 | for (l = pad->mode_groups; l; l = l->next) |
2999 | { |
3000 | group = l->data; |
3001 | |
3002 | if (g_list_find (list: group->buttons, GUINT_TO_POINTER (button))) |
3003 | return group; |
3004 | } |
3005 | |
3006 | return NULL; |
3007 | } |
3008 | |
3009 | static void |
3010 | tablet_handle_name (void *data, |
3011 | struct zwp_tablet_v2 *wp_tablet, |
3012 | const char *name) |
3013 | { |
3014 | GdkWaylandTabletData *tablet = data; |
3015 | |
3016 | tablet->name = g_strdup (str: name); |
3017 | } |
3018 | |
3019 | static void |
3020 | tablet_handle_id (void *data, |
3021 | struct zwp_tablet_v2 *wp_tablet, |
3022 | uint32_t vid, |
3023 | uint32_t pid) |
3024 | { |
3025 | GdkWaylandTabletData *tablet = data; |
3026 | |
3027 | tablet->vid = vid; |
3028 | tablet->pid = pid; |
3029 | } |
3030 | |
3031 | static void |
3032 | tablet_handle_path (void *data, |
3033 | struct zwp_tablet_v2 *wp_tablet, |
3034 | const char *path) |
3035 | { |
3036 | GdkWaylandTabletData *tablet = data; |
3037 | |
3038 | tablet->path = g_strdup (str: path); |
3039 | } |
3040 | |
3041 | static void |
3042 | tablet_handle_done (void *data, |
3043 | struct zwp_tablet_v2 *wp_tablet) |
3044 | { |
3045 | GdkWaylandTabletData *tablet = data; |
3046 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tablet->seat); |
3047 | GdkDisplay *display = gdk_seat_get_display (GDK_SEAT (seat)); |
3048 | GdkDevice *logical_device, *stylus_device; |
3049 | char *logical_name; |
3050 | char *vid, *pid; |
3051 | |
3052 | vid = g_strdup_printf (format: "%.4x" , tablet->vid); |
3053 | pid = g_strdup_printf (format: "%.4x" , tablet->pid); |
3054 | |
3055 | logical_name = g_strdup_printf (format: "Logical pointer for %s" , tablet->name); |
3056 | logical_device = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
3057 | first_property_name: "name" , logical_name, |
3058 | "source" , GDK_SOURCE_MOUSE, |
3059 | "has-cursor" , TRUE, |
3060 | "display" , display, |
3061 | "seat" , seat, |
3062 | NULL); |
3063 | GDK_WAYLAND_DEVICE (logical_device)->pointer = &tablet->pointer_info; |
3064 | |
3065 | stylus_device = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
3066 | first_property_name: "name" , tablet->name, |
3067 | "source" , GDK_SOURCE_PEN, |
3068 | "has-cursor" , FALSE, |
3069 | "display" , display, |
3070 | "seat" , seat, |
3071 | "vendor-id" , vid, |
3072 | "product-id" , pid, |
3073 | NULL); |
3074 | |
3075 | tablet->logical_device = logical_device; |
3076 | init_pointer_data (pointer_data: &tablet->pointer_info, display_wayland: display, logical_device: tablet->logical_device); |
3077 | |
3078 | tablet->stylus_device = stylus_device; |
3079 | |
3080 | _gdk_device_set_associated_device (device: logical_device, relative: seat->logical_keyboard); |
3081 | _gdk_device_set_associated_device (device: stylus_device, relative: logical_device); |
3082 | |
3083 | gdk_seat_device_added (GDK_SEAT (seat), device: logical_device); |
3084 | gdk_seat_device_added (GDK_SEAT (seat), device: stylus_device); |
3085 | |
3086 | g_free (mem: logical_name); |
3087 | g_free (mem: vid); |
3088 | g_free (mem: pid); |
3089 | } |
3090 | |
3091 | static void |
3092 | tablet_handle_removed (void *data, |
3093 | struct zwp_tablet_v2 *wp_tablet) |
3094 | { |
3095 | GdkWaylandTabletData *tablet = data; |
3096 | |
3097 | _gdk_wayland_seat_remove_tablet (GDK_WAYLAND_SEAT (tablet->seat), tablet); |
3098 | } |
3099 | |
3100 | static const struct wl_pointer_listener pointer_listener = { |
3101 | pointer_handle_enter, |
3102 | pointer_handle_leave, |
3103 | pointer_handle_motion, |
3104 | pointer_handle_button, |
3105 | pointer_handle_axis, |
3106 | pointer_handle_frame, |
3107 | pointer_handle_axis_source, |
3108 | pointer_handle_axis_stop, |
3109 | pointer_handle_axis_discrete, |
3110 | }; |
3111 | |
3112 | static const struct wl_keyboard_listener keyboard_listener = { |
3113 | keyboard_handle_keymap, |
3114 | keyboard_handle_enter, |
3115 | keyboard_handle_leave, |
3116 | keyboard_handle_key, |
3117 | keyboard_handle_modifiers, |
3118 | keyboard_handle_repeat_info, |
3119 | }; |
3120 | |
3121 | static const struct wl_touch_listener touch_listener = { |
3122 | touch_handle_down, |
3123 | touch_handle_up, |
3124 | touch_handle_motion, |
3125 | touch_handle_frame, |
3126 | touch_handle_cancel, |
3127 | touch_handle_shape, |
3128 | touch_handle_orientation, |
3129 | }; |
3130 | |
3131 | static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener = { |
3132 | gesture_swipe_begin, |
3133 | gesture_swipe_update, |
3134 | gesture_swipe_end |
3135 | }; |
3136 | |
3137 | static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener = { |
3138 | gesture_pinch_begin, |
3139 | gesture_pinch_update, |
3140 | gesture_pinch_end |
3141 | }; |
3142 | |
3143 | static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = { |
3144 | gesture_hold_begin, |
3145 | gesture_hold_end |
3146 | }; |
3147 | |
3148 | static const struct zwp_tablet_v2_listener tablet_listener = { |
3149 | tablet_handle_name, |
3150 | tablet_handle_id, |
3151 | tablet_handle_path, |
3152 | tablet_handle_done, |
3153 | tablet_handle_removed, |
3154 | }; |
3155 | |
3156 | static void |
3157 | seat_handle_capabilities (void *data, |
3158 | struct wl_seat *wl_seat, |
3159 | enum wl_seat_capability caps) |
3160 | { |
3161 | GdkWaylandSeat *seat = data; |
3162 | GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display); |
3163 | |
3164 | GDK_SEAT_NOTE (seat, MISC, |
3165 | g_message ("seat %p with %s%s%s" , wl_seat, |
3166 | (caps & WL_SEAT_CAPABILITY_POINTER) ? " pointer, " : "" , |
3167 | (caps & WL_SEAT_CAPABILITY_KEYBOARD) ? " keyboard, " : "" , |
3168 | (caps & WL_SEAT_CAPABILITY_TOUCH) ? " touch" : "" )); |
3169 | |
3170 | if ((caps & WL_SEAT_CAPABILITY_POINTER) && !seat->wl_pointer) |
3171 | { |
3172 | seat->wl_pointer = wl_seat_get_pointer (wl_seat); |
3173 | wl_pointer_set_user_data (wl_pointer: seat->wl_pointer, user_data: seat); |
3174 | wl_pointer_add_listener (wl_pointer: seat->wl_pointer, listener: &pointer_listener, data: seat); |
3175 | |
3176 | seat->pointer = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
3177 | first_property_name: "name" , "Wayland Pointer" , |
3178 | "source" , GDK_SOURCE_MOUSE, |
3179 | "has-cursor" , TRUE, |
3180 | "display" , seat->display, |
3181 | "seat" , seat, |
3182 | NULL); |
3183 | _gdk_device_set_associated_device (device: seat->pointer, relative: seat->logical_pointer); |
3184 | gdk_seat_device_added (GDK_SEAT (seat), device: seat->pointer); |
3185 | |
3186 | if (display_wayland->pointer_gestures) |
3187 | { |
3188 | seat->wp_pointer_gesture_swipe = |
3189 | zwp_pointer_gestures_v1_get_swipe_gesture (display_wayland->pointer_gestures, |
3190 | seat->wl_pointer); |
3191 | zwp_pointer_gesture_swipe_v1_set_user_data (seat->wp_pointer_gesture_swipe, |
3192 | seat); |
3193 | zwp_pointer_gesture_swipe_v1_add_listener (seat->wp_pointer_gesture_swipe, |
3194 | &gesture_swipe_listener, seat); |
3195 | |
3196 | seat->wp_pointer_gesture_pinch = |
3197 | zwp_pointer_gestures_v1_get_pinch_gesture (display_wayland->pointer_gestures, |
3198 | seat->wl_pointer); |
3199 | zwp_pointer_gesture_pinch_v1_set_user_data (seat->wp_pointer_gesture_pinch, |
3200 | seat); |
3201 | zwp_pointer_gesture_pinch_v1_add_listener (seat->wp_pointer_gesture_pinch, |
3202 | &gesture_pinch_listener, seat); |
3203 | |
3204 | if (display_wayland->pointer_gestures_version >= ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE_SINCE_VERSION) |
3205 | { |
3206 | seat->wp_pointer_gesture_hold = |
3207 | zwp_pointer_gestures_v1_get_hold_gesture (display_wayland->pointer_gestures, |
3208 | seat->wl_pointer); |
3209 | zwp_pointer_gesture_hold_v1_set_user_data (seat->wp_pointer_gesture_hold, |
3210 | seat); |
3211 | zwp_pointer_gesture_hold_v1_add_listener (seat->wp_pointer_gesture_hold, |
3212 | &gesture_hold_listener, seat); |
3213 | } |
3214 | } |
3215 | } |
3216 | else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer) |
3217 | { |
3218 | g_clear_pointer (&seat->wp_pointer_gesture_swipe, |
3219 | zwp_pointer_gesture_swipe_v1_destroy); |
3220 | g_clear_pointer (&seat->wp_pointer_gesture_pinch, |
3221 | zwp_pointer_gesture_pinch_v1_destroy); |
3222 | |
3223 | wl_pointer_release (wl_pointer: seat->wl_pointer); |
3224 | seat->wl_pointer = NULL; |
3225 | gdk_seat_device_removed (GDK_SEAT (seat), device: seat->pointer); |
3226 | _gdk_device_set_associated_device (device: seat->pointer, NULL); |
3227 | |
3228 | g_clear_object (&seat->pointer); |
3229 | |
3230 | if (seat->wheel_scrolling) |
3231 | { |
3232 | gdk_seat_device_removed (GDK_SEAT (seat), device: seat->wheel_scrolling); |
3233 | _gdk_device_set_associated_device (device: seat->wheel_scrolling, NULL); |
3234 | |
3235 | g_clear_object (&seat->wheel_scrolling); |
3236 | } |
3237 | |
3238 | if (seat->finger_scrolling) |
3239 | { |
3240 | gdk_seat_device_removed (GDK_SEAT (seat), device: seat->finger_scrolling); |
3241 | _gdk_device_set_associated_device (device: seat->finger_scrolling, NULL); |
3242 | |
3243 | g_clear_object (&seat->finger_scrolling); |
3244 | } |
3245 | |
3246 | if (seat->continuous_scrolling) |
3247 | { |
3248 | gdk_seat_device_removed (GDK_SEAT (seat), device: seat->continuous_scrolling); |
3249 | _gdk_device_set_associated_device (device: seat->continuous_scrolling, NULL); |
3250 | |
3251 | g_clear_object (&seat->continuous_scrolling); |
3252 | } |
3253 | } |
3254 | |
3255 | if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !seat->wl_keyboard) |
3256 | { |
3257 | seat->wl_keyboard = wl_seat_get_keyboard (wl_seat); |
3258 | wl_keyboard_set_user_data (wl_keyboard: seat->wl_keyboard, user_data: seat); |
3259 | wl_keyboard_add_listener (wl_keyboard: seat->wl_keyboard, listener: &keyboard_listener, data: seat); |
3260 | |
3261 | seat->keyboard = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
3262 | first_property_name: "name" , "Wayland Keyboard" , |
3263 | "source" , GDK_SOURCE_KEYBOARD, |
3264 | "has-cursor" , FALSE, |
3265 | "display" , seat->display, |
3266 | "seat" , seat, |
3267 | NULL); |
3268 | _gdk_device_reset_axes (device: seat->keyboard); |
3269 | _gdk_device_set_associated_device (device: seat->keyboard, relative: seat->logical_keyboard); |
3270 | gdk_seat_device_added (GDK_SEAT (seat), device: seat->keyboard); |
3271 | } |
3272 | else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->wl_keyboard) |
3273 | { |
3274 | wl_keyboard_release (wl_keyboard: seat->wl_keyboard); |
3275 | seat->wl_keyboard = NULL; |
3276 | gdk_seat_device_removed (GDK_SEAT (seat), device: seat->keyboard); |
3277 | _gdk_device_set_associated_device (device: seat->keyboard, NULL); |
3278 | |
3279 | g_clear_object (&seat->keyboard); |
3280 | } |
3281 | |
3282 | if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !seat->wl_touch) |
3283 | { |
3284 | seat->wl_touch = wl_seat_get_touch (wl_seat); |
3285 | wl_touch_set_user_data (wl_touch: seat->wl_touch, user_data: seat); |
3286 | wl_touch_add_listener (wl_touch: seat->wl_touch, listener: &touch_listener, data: seat); |
3287 | |
3288 | seat->logical_touch = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
3289 | first_property_name: "name" , "Wayland Touch Logical Pointer" , |
3290 | "source" , GDK_SOURCE_TOUCHSCREEN, |
3291 | "has-cursor" , TRUE, |
3292 | "display" , seat->display, |
3293 | "seat" , seat, |
3294 | NULL); |
3295 | GDK_WAYLAND_DEVICE (seat->logical_touch)->pointer = &seat->touch_info; |
3296 | _gdk_device_set_associated_device (device: seat->logical_touch, relative: seat->logical_keyboard); |
3297 | gdk_seat_device_added (GDK_SEAT (seat), device: seat->logical_touch); |
3298 | |
3299 | seat->touch = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
3300 | first_property_name: "name" , "Wayland Touch" , |
3301 | "source" , GDK_SOURCE_TOUCHSCREEN, |
3302 | "has-cursor" , FALSE, |
3303 | "display" , seat->display, |
3304 | "seat" , seat, |
3305 | NULL); |
3306 | _gdk_device_set_associated_device (device: seat->touch, relative: seat->logical_touch); |
3307 | gdk_seat_device_added (GDK_SEAT (seat), device: seat->touch); |
3308 | } |
3309 | else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch) |
3310 | { |
3311 | wl_touch_release (wl_touch: seat->wl_touch); |
3312 | seat->wl_touch = NULL; |
3313 | gdk_seat_device_removed (GDK_SEAT (seat), device: seat->touch); |
3314 | gdk_seat_device_removed (GDK_SEAT (seat), device: seat->logical_touch); |
3315 | _gdk_device_set_associated_device (device: seat->logical_touch, NULL); |
3316 | _gdk_device_set_associated_device (device: seat->touch, NULL); |
3317 | |
3318 | g_clear_object (&seat->logical_touch); |
3319 | g_clear_object (&seat->touch); |
3320 | } |
3321 | } |
3322 | |
3323 | static GdkDevice * |
3324 | get_scroll_device (GdkWaylandSeat *seat, |
3325 | enum wl_pointer_axis_source source) |
3326 | { |
3327 | if (!seat->pointer) |
3328 | return NULL; |
3329 | |
3330 | switch (source) |
3331 | { |
3332 | case WL_POINTER_AXIS_SOURCE_WHEEL: |
3333 | if (seat->wheel_scrolling == NULL) |
3334 | { |
3335 | seat->wheel_scrolling = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
3336 | first_property_name: "name" , "Wayland Wheel Scrolling" , |
3337 | "source" , GDK_SOURCE_MOUSE, |
3338 | "has-cursor" , TRUE, |
3339 | "display" , seat->display, |
3340 | "seat" , seat, |
3341 | NULL); |
3342 | gdk_seat_device_added (GDK_SEAT (seat), device: seat->wheel_scrolling); |
3343 | } |
3344 | return seat->wheel_scrolling; |
3345 | |
3346 | case WL_POINTER_AXIS_SOURCE_FINGER: |
3347 | if (seat->finger_scrolling == NULL) |
3348 | { |
3349 | seat->finger_scrolling = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
3350 | first_property_name: "name" , "Wayland Finger Scrolling" , |
3351 | "source" , GDK_SOURCE_TOUCHPAD, |
3352 | "has-cursor" , TRUE, |
3353 | "display" , seat->display, |
3354 | "seat" , seat, |
3355 | NULL); |
3356 | gdk_seat_device_added (GDK_SEAT (seat), device: seat->finger_scrolling); |
3357 | } |
3358 | return seat->finger_scrolling; |
3359 | |
3360 | case WL_POINTER_AXIS_SOURCE_CONTINUOUS: |
3361 | if (seat->continuous_scrolling == NULL) |
3362 | { |
3363 | seat->continuous_scrolling = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
3364 | first_property_name: "name" , "Wayland Continuous Scrolling" , |
3365 | "source" , GDK_SOURCE_TRACKPOINT, |
3366 | "has-cursor" , TRUE, |
3367 | "display" , seat->display, |
3368 | "seat" , seat, |
3369 | NULL); |
3370 | gdk_seat_device_added (GDK_SEAT (seat), device: seat->continuous_scrolling); |
3371 | } |
3372 | return seat->continuous_scrolling; |
3373 | |
3374 | case WL_POINTER_AXIS_SOURCE_WHEEL_TILT: |
3375 | default: |
3376 | return seat->pointer; |
3377 | } |
3378 | } |
3379 | |
3380 | static void |
3381 | seat_handle_name (void *data, |
3382 | struct wl_seat *seat, |
3383 | const char *name) |
3384 | { |
3385 | /* We don't care about the name. */ |
3386 | GDK_SEAT_NOTE (GDK_WAYLAND_SEAT (data), MISC, |
3387 | g_message ("seat %p name %s" , seat, name)); |
3388 | } |
3389 | |
3390 | static const struct wl_seat_listener seat_listener = { |
3391 | seat_handle_capabilities, |
3392 | seat_handle_name, |
3393 | }; |
3394 | |
3395 | static void |
3396 | tablet_tool_handle_type (void *data, |
3397 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3398 | uint32_t tool_type) |
3399 | { |
3400 | GdkWaylandTabletToolData *tool = data; |
3401 | |
3402 | switch (tool_type) |
3403 | { |
3404 | case ZWP_TABLET_TOOL_V2_TYPE_PEN: |
3405 | tool->type = GDK_DEVICE_TOOL_TYPE_PEN; |
3406 | break; |
3407 | case ZWP_TABLET_TOOL_V2_TYPE_BRUSH: |
3408 | tool->type = GDK_DEVICE_TOOL_TYPE_BRUSH; |
3409 | break; |
3410 | case ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH: |
3411 | tool->type = GDK_DEVICE_TOOL_TYPE_AIRBRUSH; |
3412 | break; |
3413 | case ZWP_TABLET_TOOL_V2_TYPE_PENCIL: |
3414 | tool->type = GDK_DEVICE_TOOL_TYPE_PENCIL; |
3415 | break; |
3416 | case ZWP_TABLET_TOOL_V2_TYPE_ERASER: |
3417 | tool->type = GDK_DEVICE_TOOL_TYPE_ERASER; |
3418 | break; |
3419 | case ZWP_TABLET_TOOL_V2_TYPE_MOUSE: |
3420 | tool->type = GDK_DEVICE_TOOL_TYPE_MOUSE; |
3421 | break; |
3422 | case ZWP_TABLET_TOOL_V2_TYPE_LENS: |
3423 | tool->type = GDK_DEVICE_TOOL_TYPE_LENS; |
3424 | break; |
3425 | default: |
3426 | tool->type = GDK_DEVICE_TOOL_TYPE_UNKNOWN; |
3427 | break; |
3428 | }; |
3429 | } |
3430 | |
3431 | static void |
3432 | tablet_tool_handle_hardware_serial (void *data, |
3433 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3434 | uint32_t serial_hi, |
3435 | uint32_t serial_lo) |
3436 | { |
3437 | GdkWaylandTabletToolData *tool = data; |
3438 | |
3439 | tool->hardware_serial = ((guint64) serial_hi) << 32 | serial_lo; |
3440 | } |
3441 | |
3442 | static void |
3443 | tablet_tool_handle_hardware_id_wacom (void *data, |
3444 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3445 | uint32_t id_hi, |
3446 | uint32_t id_lo) |
3447 | { |
3448 | GdkWaylandTabletToolData *tool = data; |
3449 | |
3450 | tool->hardware_id_wacom = ((guint64) id_hi) << 32 | id_lo; |
3451 | } |
3452 | |
3453 | static void |
3454 | tablet_tool_handle_capability (void *data, |
3455 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3456 | uint32_t capability) |
3457 | { |
3458 | GdkWaylandTabletToolData *tool = data; |
3459 | |
3460 | switch (capability) |
3461 | { |
3462 | case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT: |
3463 | tool->axes |= GDK_AXIS_FLAG_XTILT | GDK_AXIS_FLAG_YTILT; |
3464 | break; |
3465 | case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE: |
3466 | tool->axes |= GDK_AXIS_FLAG_PRESSURE; |
3467 | break; |
3468 | case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE: |
3469 | tool->axes |= GDK_AXIS_FLAG_DISTANCE; |
3470 | break; |
3471 | case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION: |
3472 | tool->axes |= GDK_AXIS_FLAG_ROTATION; |
3473 | break; |
3474 | case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER: |
3475 | tool->axes |= GDK_AXIS_FLAG_SLIDER; |
3476 | break; |
3477 | default: |
3478 | break; |
3479 | } |
3480 | } |
3481 | |
3482 | static void |
3483 | tablet_tool_handle_done (void *data, |
3484 | struct zwp_tablet_tool_v2 *wp_tablet_tool) |
3485 | { |
3486 | GdkWaylandTabletToolData *tool = data; |
3487 | |
3488 | tool->tool = gdk_device_tool_new (serial: tool->hardware_serial, |
3489 | hw_id: tool->hardware_id_wacom, |
3490 | type: tool->type, tool_axes: tool->axes); |
3491 | gdk_seat_tool_added (seat: tool->seat, tool: tool->tool); |
3492 | } |
3493 | |
3494 | static void |
3495 | tablet_tool_handle_removed (void *data, |
3496 | struct zwp_tablet_tool_v2 *wp_tablet_tool) |
3497 | { |
3498 | GdkWaylandTabletToolData *tool = data; |
3499 | |
3500 | _gdk_wayland_seat_remove_tool (GDK_WAYLAND_SEAT (tool->seat), tool); |
3501 | } |
3502 | |
3503 | static void |
3504 | gdk_wayland_tablet_flush_frame_event (GdkWaylandTabletData *tablet, |
3505 | guint32 time) |
3506 | { |
3507 | GdkEvent *event; |
3508 | GdkEventType type; |
3509 | |
3510 | event = tablet->pointer_info.frame.event; |
3511 | tablet->pointer_info.frame.event = NULL; |
3512 | |
3513 | if (!event) |
3514 | return; |
3515 | |
3516 | gdk_event_ref (event); |
3517 | |
3518 | type = gdk_event_get_event_type (event); |
3519 | |
3520 | if (type == GDK_PROXIMITY_OUT) |
3521 | emulate_crossing (surface: gdk_event_get_surface (event), NULL, |
3522 | device: tablet->logical_device, type: GDK_LEAVE_NOTIFY, |
3523 | mode: GDK_CROSSING_NORMAL, time_: time); |
3524 | |
3525 | _gdk_wayland_display_deliver_event (display: gdk_seat_get_display (seat: tablet->seat), |
3526 | event); |
3527 | |
3528 | if (type == GDK_PROXIMITY_IN) |
3529 | emulate_crossing (surface: gdk_event_get_surface (event), NULL, |
3530 | device: tablet->logical_device, type: GDK_ENTER_NOTIFY, |
3531 | mode: GDK_CROSSING_NORMAL, time_: time); |
3532 | |
3533 | gdk_event_unref (event); |
3534 | } |
3535 | |
3536 | static void |
3537 | gdk_wayland_tablet_set_frame_event (GdkWaylandTabletData *tablet, |
3538 | GdkEvent *event) |
3539 | { |
3540 | if (tablet->pointer_info.frame.event && |
3541 | gdk_event_get_event_type (event: tablet->pointer_info.frame.event) != gdk_event_get_event_type (event)) |
3542 | gdk_wayland_tablet_flush_frame_event (tablet, GDK_CURRENT_TIME); |
3543 | |
3544 | tablet->pointer_info.frame.event = event; |
3545 | } |
3546 | |
3547 | static void |
3548 | gdk_wayland_device_tablet_clone_tool_axes (GdkWaylandTabletData *tablet, |
3549 | GdkDeviceTool *tool) |
3550 | { |
3551 | int axis_pos; |
3552 | |
3553 | g_object_freeze_notify (G_OBJECT (tablet->stylus_device)); |
3554 | _gdk_device_reset_axes (device: tablet->stylus_device); |
3555 | |
3556 | _gdk_device_add_axis (device: tablet->stylus_device, use: GDK_AXIS_X, min_value: 0, max_value: 0, resolution: 0); |
3557 | _gdk_device_add_axis (device: tablet->stylus_device, use: GDK_AXIS_Y, min_value: 0, max_value: 0, resolution: 0); |
3558 | |
3559 | if (tool->tool_axes & (GDK_AXIS_FLAG_XTILT | GDK_AXIS_FLAG_YTILT)) |
3560 | { |
3561 | axis_pos = _gdk_device_add_axis (device: tablet->stylus_device, |
3562 | use: GDK_AXIS_XTILT, min_value: -90, max_value: 90, resolution: 0); |
3563 | tablet->axis_indices[GDK_AXIS_XTILT] = axis_pos; |
3564 | |
3565 | axis_pos = _gdk_device_add_axis (device: tablet->stylus_device, |
3566 | use: GDK_AXIS_YTILT, min_value: -90, max_value: 90, resolution: 0); |
3567 | tablet->axis_indices[GDK_AXIS_YTILT] = axis_pos; |
3568 | } |
3569 | if (tool->tool_axes & GDK_AXIS_FLAG_DISTANCE) |
3570 | { |
3571 | axis_pos = _gdk_device_add_axis (device: tablet->stylus_device, |
3572 | use: GDK_AXIS_DISTANCE, min_value: 0, max_value: 65535, resolution: 0); |
3573 | tablet->axis_indices[GDK_AXIS_DISTANCE] = axis_pos; |
3574 | } |
3575 | if (tool->tool_axes & GDK_AXIS_FLAG_PRESSURE) |
3576 | { |
3577 | axis_pos = _gdk_device_add_axis (device: tablet->stylus_device, |
3578 | use: GDK_AXIS_PRESSURE, min_value: 0, max_value: 65535, resolution: 0); |
3579 | tablet->axis_indices[GDK_AXIS_PRESSURE] = axis_pos; |
3580 | } |
3581 | |
3582 | if (tool->tool_axes & GDK_AXIS_FLAG_ROTATION) |
3583 | { |
3584 | axis_pos = _gdk_device_add_axis (device: tablet->stylus_device, |
3585 | use: GDK_AXIS_ROTATION, min_value: 0, max_value: 360, resolution: 0); |
3586 | tablet->axis_indices[GDK_AXIS_ROTATION] = axis_pos; |
3587 | } |
3588 | |
3589 | if (tool->tool_axes & GDK_AXIS_FLAG_SLIDER) |
3590 | { |
3591 | axis_pos = _gdk_device_add_axis (device: tablet->stylus_device, |
3592 | use: GDK_AXIS_SLIDER, min_value: -65535, max_value: 65535, resolution: 0); |
3593 | tablet->axis_indices[GDK_AXIS_SLIDER] = axis_pos; |
3594 | } |
3595 | |
3596 | g_object_thaw_notify (G_OBJECT (tablet->stylus_device)); |
3597 | } |
3598 | |
3599 | static void |
3600 | gdk_wayland_mimic_device_axes (GdkDevice *logical, |
3601 | GdkDevice *physical) |
3602 | { |
3603 | double axis_min, axis_max, axis_resolution; |
3604 | GdkAxisUse axis_use; |
3605 | int axis_count; |
3606 | int i; |
3607 | |
3608 | g_object_freeze_notify (G_OBJECT (logical)); |
3609 | _gdk_device_reset_axes (device: logical); |
3610 | axis_count = gdk_device_get_n_axes (device: physical); |
3611 | |
3612 | for (i = 0; i < axis_count; i++) |
3613 | { |
3614 | _gdk_device_get_axis_info (device: physical, index: i, use: &axis_use, min_value: &axis_min, |
3615 | max_value: &axis_max, resolution: &axis_resolution); |
3616 | _gdk_device_add_axis (device: logical, use: axis_use, min_value: axis_min, |
3617 | max_value: axis_max, resolution: axis_resolution); |
3618 | } |
3619 | |
3620 | g_object_thaw_notify (G_OBJECT (logical)); |
3621 | } |
3622 | |
3623 | static void |
3624 | tablet_tool_handle_proximity_in (void *data, |
3625 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3626 | uint32_t serial, |
3627 | struct zwp_tablet_v2 *wp_tablet, |
3628 | struct wl_surface *wsurface) |
3629 | { |
3630 | GdkWaylandTabletToolData *tool = data; |
3631 | GdkWaylandTabletData *tablet = zwp_tablet_v2_get_user_data (wp_tablet); |
3632 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tablet->seat); |
3633 | GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display); |
3634 | GdkSurface *surface; |
3635 | GdkEvent *event; |
3636 | |
3637 | if (!wsurface) |
3638 | return; |
3639 | |
3640 | surface = wl_surface_get_user_data (wl_surface: wsurface); |
3641 | |
3642 | if (!surface) |
3643 | return; |
3644 | if (!GDK_IS_SURFACE (surface)) |
3645 | return; |
3646 | |
3647 | tool->current_tablet = tablet; |
3648 | tablet->current_tool = tool; |
3649 | |
3650 | _gdk_wayland_display_update_serial (display_wayland, serial); |
3651 | tablet->pointer_info.enter_serial = serial; |
3652 | |
3653 | tablet->pointer_info.focus = g_object_ref (surface); |
3654 | |
3655 | gdk_device_update_tool (device: tablet->stylus_device, tool: tool->tool); |
3656 | gdk_wayland_device_tablet_clone_tool_axes (tablet, tool: tool->tool); |
3657 | gdk_wayland_mimic_device_axes (logical: tablet->logical_device, physical: tablet->stylus_device); |
3658 | |
3659 | event = gdk_proximity_event_new (type: GDK_PROXIMITY_IN, |
3660 | surface: tablet->pointer_info.focus, |
3661 | device: tablet->logical_device, |
3662 | tool: tool->tool, |
3663 | time: tablet->pointer_info.time); |
3664 | gdk_wayland_tablet_set_frame_event (tablet, event); |
3665 | |
3666 | tablet->pointer_info.pointer_surface_outputs = |
3667 | g_slist_append (list: tablet->pointer_info.pointer_surface_outputs, |
3668 | data: gdk_wayland_surface_get_wl_output (surface)); |
3669 | pointer_surface_update_scale (device: tablet->logical_device); |
3670 | |
3671 | GDK_SEAT_NOTE (seat, EVENTS, |
3672 | g_message ("proximity in, seat %p surface %p tool %d" , |
3673 | seat, tablet->pointer_info.focus, |
3674 | gdk_device_tool_get_tool_type (tool->tool))); |
3675 | } |
3676 | |
3677 | static void |
3678 | tablet_tool_handle_proximity_out (void *data, |
3679 | struct zwp_tablet_tool_v2 *wp_tablet_tool) |
3680 | { |
3681 | GdkWaylandTabletToolData *tool = data; |
3682 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3683 | GdkEvent *event; |
3684 | |
3685 | if (!tablet) |
3686 | return; |
3687 | |
3688 | GDK_SEAT_NOTE (tool->seat, EVENTS, |
3689 | g_message ("proximity out, seat %p, tool %d" , tool->seat, |
3690 | gdk_device_tool_get_tool_type (tool->tool))); |
3691 | |
3692 | event = gdk_proximity_event_new (type: GDK_PROXIMITY_OUT, |
3693 | surface: tablet->pointer_info.focus, |
3694 | device: tablet->logical_device, |
3695 | tool: tool->tool, |
3696 | time: tablet->pointer_info.time); |
3697 | gdk_wayland_tablet_set_frame_event (tablet, event); |
3698 | |
3699 | gdk_wayland_pointer_stop_cursor_animation (pointer: &tablet->pointer_info); |
3700 | |
3701 | tablet->pointer_info.pointer_surface_outputs = |
3702 | g_slist_remove (list: tablet->pointer_info.pointer_surface_outputs, |
3703 | data: gdk_wayland_surface_get_wl_output (surface: tablet->pointer_info.focus)); |
3704 | pointer_surface_update_scale (device: tablet->logical_device); |
3705 | |
3706 | g_object_unref (object: tablet->pointer_info.focus); |
3707 | tablet->pointer_info.focus = NULL; |
3708 | |
3709 | tablet->pointer_info.button_modifiers &= |
3710 | ~(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | |
3711 | GDK_BUTTON4_MASK | GDK_BUTTON5_MASK); |
3712 | |
3713 | gdk_device_update_tool (device: tablet->stylus_device, NULL); |
3714 | g_clear_object (&tablet->pointer_info.cursor); |
3715 | } |
3716 | |
3717 | static double * |
3718 | tablet_copy_axes (GdkWaylandTabletData *tablet) |
3719 | { |
3720 | return g_memdup2 (mem: tablet->axes, byte_size: sizeof (double) * GDK_AXIS_LAST); |
3721 | } |
3722 | |
3723 | static void |
3724 | tablet_create_button_event_frame (GdkWaylandTabletData *tablet, |
3725 | GdkEventType evtype, |
3726 | guint button) |
3727 | { |
3728 | GdkEvent *event; |
3729 | |
3730 | event = gdk_button_event_new (type: evtype, |
3731 | surface: tablet->pointer_info.focus, |
3732 | device: tablet->logical_device, |
3733 | tool: tablet->current_tool->tool, |
3734 | time: tablet->pointer_info.time, |
3735 | state: device_get_modifiers (device: tablet->logical_device), |
3736 | button, |
3737 | x: tablet->pointer_info.surface_x, |
3738 | y: tablet->pointer_info.surface_y, |
3739 | axes: tablet_copy_axes (tablet)); |
3740 | gdk_wayland_tablet_set_frame_event (tablet, event); |
3741 | } |
3742 | |
3743 | static void |
3744 | tablet_tool_handle_down (void *data, |
3745 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3746 | uint32_t serial) |
3747 | { |
3748 | GdkWaylandTabletToolData *tool = data; |
3749 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3750 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tool->seat); |
3751 | GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display); |
3752 | |
3753 | if (!tablet || !tablet->pointer_info.focus) |
3754 | return; |
3755 | |
3756 | _gdk_wayland_display_update_serial (display_wayland, serial); |
3757 | tablet->pointer_info.press_serial = serial; |
3758 | |
3759 | tablet_create_button_event_frame (tablet, evtype: GDK_BUTTON_PRESS, GDK_BUTTON_PRIMARY); |
3760 | tablet->pointer_info.button_modifiers |= GDK_BUTTON1_MASK; |
3761 | } |
3762 | |
3763 | static void |
3764 | tablet_tool_handle_up (void *data, |
3765 | struct zwp_tablet_tool_v2 *wp_tablet_tool) |
3766 | { |
3767 | GdkWaylandTabletToolData *tool = data; |
3768 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3769 | |
3770 | if (!tablet || !tablet->pointer_info.focus) |
3771 | return; |
3772 | |
3773 | tablet_create_button_event_frame (tablet, evtype: GDK_BUTTON_RELEASE, GDK_BUTTON_PRIMARY); |
3774 | tablet->pointer_info.button_modifiers &= ~GDK_BUTTON1_MASK; |
3775 | } |
3776 | |
3777 | static void |
3778 | tablet_tool_handle_motion (void *data, |
3779 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3780 | wl_fixed_t sx, |
3781 | wl_fixed_t sy) |
3782 | { |
3783 | GdkWaylandTabletToolData *tool = data; |
3784 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3785 | GdkEvent *event; |
3786 | |
3787 | if (!tablet) |
3788 | return; |
3789 | |
3790 | tablet->pointer_info.surface_x = wl_fixed_to_double (f: sx); |
3791 | tablet->pointer_info.surface_y = wl_fixed_to_double (f: sy); |
3792 | |
3793 | GDK_SEAT_NOTE (tool->seat, EVENTS, |
3794 | g_message ("tablet motion %f %f" , |
3795 | tablet->pointer_info.surface_x, |
3796 | tablet->pointer_info.surface_y)); |
3797 | |
3798 | event = gdk_motion_event_new (surface: tablet->pointer_info.focus, |
3799 | device: tablet->logical_device, |
3800 | tool: tool->tool, |
3801 | time: tablet->pointer_info.time, |
3802 | state: device_get_modifiers (device: tablet->logical_device), |
3803 | x: tablet->pointer_info.surface_x, |
3804 | y: tablet->pointer_info.surface_y, |
3805 | axes: tablet_copy_axes (tablet)); |
3806 | |
3807 | gdk_wayland_tablet_set_frame_event (tablet, event); |
3808 | } |
3809 | |
3810 | static void |
3811 | tablet_tool_handle_pressure (void *data, |
3812 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3813 | uint32_t pressure) |
3814 | { |
3815 | GdkWaylandTabletToolData *tool = data; |
3816 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3817 | int axis_index; |
3818 | |
3819 | if (!tablet) |
3820 | return; |
3821 | |
3822 | axis_index = tablet->axis_indices[GDK_AXIS_PRESSURE]; |
3823 | |
3824 | _gdk_device_translate_axis (device: tablet->stylus_device, index: axis_index, |
3825 | value: pressure, axis_value: &tablet->axes[GDK_AXIS_PRESSURE]); |
3826 | |
3827 | GDK_SEAT_NOTE (tool->seat, EVENTS, |
3828 | g_message ("tablet tool %d pressure %d" , |
3829 | gdk_device_tool_get_tool_type (tool->tool), pressure)); |
3830 | } |
3831 | |
3832 | static void |
3833 | tablet_tool_handle_distance (void *data, |
3834 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3835 | uint32_t distance) |
3836 | { |
3837 | GdkWaylandTabletToolData *tool = data; |
3838 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3839 | int axis_index; |
3840 | |
3841 | if (!tablet) |
3842 | return; |
3843 | |
3844 | axis_index = tablet->axis_indices[GDK_AXIS_DISTANCE]; |
3845 | |
3846 | _gdk_device_translate_axis (device: tablet->stylus_device, index: axis_index, |
3847 | value: distance, axis_value: &tablet->axes[GDK_AXIS_DISTANCE]); |
3848 | |
3849 | GDK_SEAT_NOTE (tool->seat, EVENTS, |
3850 | g_message ("tablet tool %d distance %d" , |
3851 | gdk_device_tool_get_tool_type (tool->tool), distance)); |
3852 | } |
3853 | |
3854 | static void |
3855 | tablet_tool_handle_tilt (void *data, |
3856 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3857 | wl_fixed_t xtilt, |
3858 | wl_fixed_t ytilt) |
3859 | { |
3860 | GdkWaylandTabletToolData *tool = data; |
3861 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3862 | int xtilt_axis_index; |
3863 | int ytilt_axis_index; |
3864 | |
3865 | if (!tablet) |
3866 | return; |
3867 | |
3868 | xtilt_axis_index = tablet->axis_indices[GDK_AXIS_XTILT]; |
3869 | ytilt_axis_index = tablet->axis_indices[GDK_AXIS_YTILT]; |
3870 | |
3871 | _gdk_device_translate_axis (device: tablet->stylus_device, index: xtilt_axis_index, |
3872 | value: wl_fixed_to_double (f: xtilt), |
3873 | axis_value: &tablet->axes[GDK_AXIS_XTILT]); |
3874 | _gdk_device_translate_axis (device: tablet->stylus_device, index: ytilt_axis_index, |
3875 | value: wl_fixed_to_double (f: ytilt), |
3876 | axis_value: &tablet->axes[GDK_AXIS_YTILT]); |
3877 | |
3878 | GDK_SEAT_NOTE (tool->seat, EVENTS, |
3879 | g_message ("tablet tool %d tilt %f/%f" , |
3880 | gdk_device_tool_get_tool_type (tool->tool), |
3881 | wl_fixed_to_double (xtilt), wl_fixed_to_double (ytilt))); |
3882 | } |
3883 | |
3884 | static void |
3885 | tablet_tool_handle_button (void *data, |
3886 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3887 | uint32_t serial, |
3888 | uint32_t button, |
3889 | uint32_t state) |
3890 | { |
3891 | GdkWaylandTabletToolData *tool = data; |
3892 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3893 | GdkEventType evtype; |
3894 | guint n_button; |
3895 | |
3896 | if (!tablet || !tablet->pointer_info.focus) |
3897 | return; |
3898 | |
3899 | tablet->pointer_info.press_serial = serial; |
3900 | |
3901 | if (button == BTN_STYLUS) |
3902 | n_button = GDK_BUTTON_SECONDARY; |
3903 | else if (button == BTN_STYLUS2) |
3904 | n_button = GDK_BUTTON_MIDDLE; |
3905 | else if (button == BTN_STYLUS3) |
3906 | n_button = 8; /* Back */ |
3907 | else |
3908 | return; |
3909 | |
3910 | if (state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_PRESSED) |
3911 | evtype = GDK_BUTTON_PRESS; |
3912 | else if (state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED) |
3913 | evtype = GDK_BUTTON_RELEASE; |
3914 | else |
3915 | return; |
3916 | |
3917 | tablet_create_button_event_frame (tablet, evtype, button: n_button); |
3918 | } |
3919 | |
3920 | static void |
3921 | tablet_tool_handle_rotation (void *data, |
3922 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3923 | wl_fixed_t degrees) |
3924 | { |
3925 | GdkWaylandTabletToolData *tool = data; |
3926 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3927 | int axis_index; |
3928 | |
3929 | if (!tablet) |
3930 | return; |
3931 | |
3932 | axis_index = tablet->axis_indices[GDK_AXIS_ROTATION]; |
3933 | |
3934 | _gdk_device_translate_axis (device: tablet->stylus_device, index: axis_index, |
3935 | value: wl_fixed_to_double (f: degrees), |
3936 | axis_value: &tablet->axes[GDK_AXIS_ROTATION]); |
3937 | |
3938 | GDK_SEAT_NOTE (tool->seat, EVENTS, |
3939 | g_message ("tablet tool %d rotation %f" , |
3940 | gdk_device_tool_get_tool_type (tool->tool), |
3941 | wl_fixed_to_double (degrees))); |
3942 | } |
3943 | |
3944 | static void |
3945 | tablet_tool_handle_slider (void *data, |
3946 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3947 | int32_t position) |
3948 | { |
3949 | GdkWaylandTabletToolData *tool = data; |
3950 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3951 | int axis_index; |
3952 | |
3953 | if (!tablet) |
3954 | return; |
3955 | |
3956 | axis_index = tablet->axis_indices[GDK_AXIS_SLIDER]; |
3957 | |
3958 | _gdk_device_translate_axis (device: tablet->stylus_device, index: axis_index, |
3959 | value: position, axis_value: &tablet->axes[GDK_AXIS_SLIDER]); |
3960 | |
3961 | GDK_SEAT_NOTE (tool->seat, EVENTS, |
3962 | g_message ("tablet tool %d slider %d" , |
3963 | gdk_device_tool_get_tool_type (tool->tool), position)); |
3964 | } |
3965 | |
3966 | static void |
3967 | tablet_tool_handle_wheel (void *data, |
3968 | struct zwp_tablet_tool_v2 *wp_tablet_tool, |
3969 | int32_t degrees, |
3970 | int32_t clicks) |
3971 | { |
3972 | GdkWaylandTabletToolData *tool = data; |
3973 | GdkWaylandTabletData *tablet = tool->current_tablet; |
3974 | GdkWaylandSeat *seat; |
3975 | GdkEvent *event; |
3976 | |
3977 | if (!tablet) |
3978 | return; |
3979 | |
3980 | seat = GDK_WAYLAND_SEAT (tablet->seat); |
3981 | |
3982 | GDK_SEAT_NOTE (seat, EVENTS, |
3983 | g_message ("tablet tool %d wheel %d/%d" , |
3984 | gdk_device_tool_get_tool_type (tool->tool), degrees, clicks)); |
3985 | |
3986 | if (clicks == 0) |
3987 | return; |
3988 | |
3989 | /* Send smooth event */ |
3990 | event = gdk_scroll_event_new (surface: tablet->pointer_info.focus, |
3991 | device: tablet->logical_device, |
3992 | tool: tablet->current_tool->tool, |
3993 | time: tablet->pointer_info.time, |
3994 | state: device_get_modifiers (device: tablet->logical_device), |
3995 | delta_x: 0, delta_y: clicks, |
3996 | FALSE); |
3997 | |
3998 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
3999 | |
4000 | /* Send discrete event */ |
4001 | event = gdk_scroll_event_new_discrete (surface: tablet->pointer_info.focus, |
4002 | device: tablet->stylus_device, |
4003 | tool: tablet->current_tool->tool, |
4004 | time: tablet->pointer_info.time, |
4005 | state: device_get_modifiers (device: tablet->logical_device), |
4006 | direction: clicks > 0 ? GDK_SCROLL_DOWN : GDK_SCROLL_UP, |
4007 | TRUE); |
4008 | |
4009 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
4010 | } |
4011 | |
4012 | static void |
4013 | tablet_tool_handle_frame (void *data, |
4014 | struct zwp_tablet_tool_v2 *wl_tablet_tool, |
4015 | uint32_t time) |
4016 | { |
4017 | GdkWaylandTabletToolData *tool = data; |
4018 | GdkWaylandTabletData *tablet = tool->current_tablet; |
4019 | GdkEvent *frame_event; |
4020 | |
4021 | if (!tablet) |
4022 | return; |
4023 | |
4024 | GDK_SEAT_NOTE (tablet->seat, EVENTS, |
4025 | g_message ("tablet frame, time %d" , time)); |
4026 | |
4027 | frame_event = tablet->pointer_info.frame.event; |
4028 | |
4029 | if (frame_event && gdk_event_get_event_type (event: frame_event) == GDK_PROXIMITY_OUT) |
4030 | { |
4031 | tool->current_tablet = NULL; |
4032 | tablet->current_tool = NULL; |
4033 | } |
4034 | |
4035 | tablet->pointer_info.time = time; |
4036 | gdk_wayland_tablet_flush_frame_event (tablet, time); |
4037 | } |
4038 | |
4039 | static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { |
4040 | tablet_tool_handle_type, |
4041 | tablet_tool_handle_hardware_serial, |
4042 | tablet_tool_handle_hardware_id_wacom, |
4043 | tablet_tool_handle_capability, |
4044 | tablet_tool_handle_done, |
4045 | tablet_tool_handle_removed, |
4046 | tablet_tool_handle_proximity_in, |
4047 | tablet_tool_handle_proximity_out, |
4048 | tablet_tool_handle_down, |
4049 | tablet_tool_handle_up, |
4050 | tablet_tool_handle_motion, |
4051 | tablet_tool_handle_pressure, |
4052 | tablet_tool_handle_distance, |
4053 | tablet_tool_handle_tilt, |
4054 | tablet_tool_handle_rotation, |
4055 | tablet_tool_handle_slider, |
4056 | tablet_tool_handle_wheel, |
4057 | tablet_tool_handle_button, |
4058 | tablet_tool_handle_frame, |
4059 | }; |
4060 | |
4061 | static void |
4062 | tablet_pad_ring_handle_source (void *data, |
4063 | struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring, |
4064 | uint32_t source) |
4065 | { |
4066 | GdkWaylandTabletPadGroupData *group = data; |
4067 | |
4068 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4069 | g_message ("tablet pad ring handle source, ring = %p source = %d" , |
4070 | wp_tablet_pad_ring, source)); |
4071 | |
4072 | group->axis_tmp_info.source = source; |
4073 | } |
4074 | |
4075 | static void |
4076 | tablet_pad_ring_handle_angle (void *data, |
4077 | struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring, |
4078 | wl_fixed_t angle) |
4079 | { |
4080 | GdkWaylandTabletPadGroupData *group = data; |
4081 | |
4082 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4083 | g_message ("tablet pad ring handle angle, ring = %p angle = %f" , |
4084 | wp_tablet_pad_ring, wl_fixed_to_double (angle))); |
4085 | |
4086 | group->axis_tmp_info.value = wl_fixed_to_double (f: angle); |
4087 | } |
4088 | |
4089 | static void |
4090 | tablet_pad_ring_handle_stop (void *data, |
4091 | struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring) |
4092 | { |
4093 | GdkWaylandTabletPadGroupData *group = data; |
4094 | |
4095 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4096 | g_message ("tablet pad ring handle stop, ring = %p" , wp_tablet_pad_ring)); |
4097 | |
4098 | group->axis_tmp_info.is_stop = TRUE; |
4099 | } |
4100 | |
4101 | static void |
4102 | tablet_pad_ring_handle_frame (void *data, |
4103 | struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring, |
4104 | uint32_t time) |
4105 | { |
4106 | GdkWaylandTabletPadGroupData *group = data; |
4107 | GdkWaylandTabletPadData *pad = group->pad; |
4108 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat); |
4109 | GdkEvent *event; |
4110 | |
4111 | GDK_SEAT_NOTE (seat, EVENTS, |
4112 | g_message ("tablet pad ring handle frame, ring = %p" , wp_tablet_pad_ring)); |
4113 | |
4114 | event = gdk_pad_event_new_ring (surface: seat->keyboard_focus, |
4115 | device: pad->device, |
4116 | time, |
4117 | group: g_list_index (list: pad->mode_groups, data: group), |
4118 | index: g_list_index (list: pad->rings, data: wp_tablet_pad_ring), |
4119 | mode: group->current_mode, |
4120 | value: group->axis_tmp_info.value); |
4121 | |
4122 | _gdk_wayland_display_deliver_event (display: gdk_seat_get_display (seat: pad->seat), |
4123 | event); |
4124 | } |
4125 | |
4126 | static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = { |
4127 | tablet_pad_ring_handle_source, |
4128 | tablet_pad_ring_handle_angle, |
4129 | tablet_pad_ring_handle_stop, |
4130 | tablet_pad_ring_handle_frame, |
4131 | }; |
4132 | |
4133 | static void |
4134 | tablet_pad_strip_handle_source (void *data, |
4135 | struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip, |
4136 | uint32_t source) |
4137 | { |
4138 | GdkWaylandTabletPadGroupData *group = data; |
4139 | |
4140 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4141 | g_message ("tablet pad strip handle source, strip = %p source = %d" , |
4142 | wp_tablet_pad_strip, source)); |
4143 | |
4144 | group->axis_tmp_info.source = source; |
4145 | } |
4146 | |
4147 | static void |
4148 | tablet_pad_strip_handle_position (void *data, |
4149 | struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip, |
4150 | uint32_t position) |
4151 | { |
4152 | GdkWaylandTabletPadGroupData *group = data; |
4153 | |
4154 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4155 | g_message ("tablet pad strip handle position, strip = %p position = %d" , |
4156 | wp_tablet_pad_strip, position)); |
4157 | |
4158 | group->axis_tmp_info.value = (double) position / 65535; |
4159 | } |
4160 | |
4161 | static void |
4162 | tablet_pad_strip_handle_stop (void *data, |
4163 | struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip) |
4164 | { |
4165 | GdkWaylandTabletPadGroupData *group = data; |
4166 | |
4167 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4168 | g_message ("tablet pad strip handle stop, strip = %p" , |
4169 | wp_tablet_pad_strip)); |
4170 | |
4171 | group->axis_tmp_info.is_stop = TRUE; |
4172 | } |
4173 | |
4174 | static void |
4175 | tablet_pad_strip_handle_frame (void *data, |
4176 | struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip, |
4177 | uint32_t time) |
4178 | { |
4179 | GdkWaylandTabletPadGroupData *group = data; |
4180 | GdkWaylandTabletPadData *pad = group->pad; |
4181 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat); |
4182 | GdkEvent *event; |
4183 | |
4184 | GDK_SEAT_NOTE (seat, EVENTS, |
4185 | g_message ("tablet pad strip handle frame, strip = %p" , |
4186 | wp_tablet_pad_strip)); |
4187 | |
4188 | event = gdk_pad_event_new_strip (surface: seat->keyboard_focus, |
4189 | device: pad->device, |
4190 | time, |
4191 | group: g_list_index (list: pad->mode_groups, data: group), |
4192 | index: g_list_index (list: pad->strips, data: wp_tablet_pad_strip), |
4193 | mode: group->current_mode, |
4194 | value: group->axis_tmp_info.value); |
4195 | |
4196 | _gdk_wayland_display_deliver_event (display: gdk_seat_get_display (seat: pad->seat), |
4197 | event); |
4198 | } |
4199 | |
4200 | static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener = { |
4201 | tablet_pad_strip_handle_source, |
4202 | tablet_pad_strip_handle_position, |
4203 | tablet_pad_strip_handle_stop, |
4204 | tablet_pad_strip_handle_frame, |
4205 | }; |
4206 | |
4207 | static void |
4208 | tablet_pad_group_handle_buttons (void *data, |
4209 | struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group, |
4210 | struct wl_array *buttons) |
4211 | { |
4212 | GdkWaylandTabletPadGroupData *group = data; |
4213 | uint32_t *p; |
4214 | |
4215 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4216 | g_message ("tablet pad group handle buttons, pad group = %p, n_buttons = %" G_GSIZE_FORMAT, |
4217 | wp_tablet_pad_group, buttons->size)); |
4218 | |
4219 | wl_array_for_each (p, buttons) |
4220 | { |
4221 | group->buttons = g_list_prepend (list: group->buttons, GUINT_TO_POINTER (*p)); |
4222 | } |
4223 | |
4224 | group->buttons = g_list_reverse (list: group->buttons); |
4225 | } |
4226 | |
4227 | static void |
4228 | tablet_pad_group_handle_ring (void *data, |
4229 | struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group, |
4230 | struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring) |
4231 | { |
4232 | GdkWaylandTabletPadGroupData *group = data; |
4233 | |
4234 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4235 | g_message ("tablet pad group handle ring, pad group = %p, ring = %p" , |
4236 | wp_tablet_pad_group, wp_tablet_pad_ring)); |
4237 | |
4238 | zwp_tablet_pad_ring_v2_add_listener (wp_tablet_pad_ring, |
4239 | &tablet_pad_ring_listener, group); |
4240 | zwp_tablet_pad_ring_v2_set_user_data (wp_tablet_pad_ring, group); |
4241 | |
4242 | group->rings = g_list_append (list: group->rings, data: wp_tablet_pad_ring); |
4243 | group->pad->rings = g_list_append (list: group->pad->rings, data: wp_tablet_pad_ring); |
4244 | } |
4245 | |
4246 | static void |
4247 | tablet_pad_group_handle_strip (void *data, |
4248 | struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group, |
4249 | struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip) |
4250 | { |
4251 | GdkWaylandTabletPadGroupData *group = data; |
4252 | |
4253 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4254 | g_message ("tablet pad group handle strip, pad group = %p, strip = %p" , |
4255 | wp_tablet_pad_group, wp_tablet_pad_strip)); |
4256 | |
4257 | zwp_tablet_pad_strip_v2_add_listener (wp_tablet_pad_strip, |
4258 | &tablet_pad_strip_listener, group); |
4259 | zwp_tablet_pad_strip_v2_set_user_data (wp_tablet_pad_strip, group); |
4260 | |
4261 | group->strips = g_list_append (list: group->strips, data: wp_tablet_pad_strip); |
4262 | group->pad->strips = g_list_append (list: group->pad->strips, data: wp_tablet_pad_strip); |
4263 | } |
4264 | |
4265 | static void |
4266 | tablet_pad_group_handle_modes (void *data, |
4267 | struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group, |
4268 | uint32_t modes) |
4269 | { |
4270 | GdkWaylandTabletPadGroupData *group = data; |
4271 | |
4272 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4273 | g_message ("tablet pad group handle modes, pad group = %p, n_modes = %d" , |
4274 | wp_tablet_pad_group, modes)); |
4275 | |
4276 | group->n_modes = modes; |
4277 | } |
4278 | |
4279 | static void |
4280 | tablet_pad_group_handle_done (void *data, |
4281 | struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group) |
4282 | { |
4283 | #ifdef G_ENABLE_DEBUG |
4284 | GdkWaylandTabletPadGroupData *group = data; |
4285 | #endif |
4286 | |
4287 | GDK_SEAT_NOTE (group->pad->seat, EVENTS, |
4288 | g_message ("tablet pad group handle done, pad group = %p" , |
4289 | wp_tablet_pad_group)); |
4290 | } |
4291 | |
4292 | static void |
4293 | tablet_pad_group_handle_mode (void *data, |
4294 | struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group, |
4295 | uint32_t time, |
4296 | uint32_t serial, |
4297 | uint32_t mode) |
4298 | { |
4299 | GdkWaylandTabletPadGroupData *group = data; |
4300 | GdkWaylandTabletPadData *pad = group->pad; |
4301 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat); |
4302 | GdkEvent *event; |
4303 | guint n_group; |
4304 | |
4305 | GDK_SEAT_NOTE (seat, EVENTS, |
4306 | g_message ("tablet pad group handle mode, pad group = %p, mode = %d" , |
4307 | wp_tablet_pad_group, mode)); |
4308 | |
4309 | group->mode_switch_serial = serial; |
4310 | group->current_mode = mode; |
4311 | n_group = g_list_index (list: pad->mode_groups, data: group); |
4312 | |
4313 | event = gdk_pad_event_new_group_mode (surface: seat->keyboard_focus, |
4314 | device: pad->device, |
4315 | time, |
4316 | group: n_group, |
4317 | mode); |
4318 | |
4319 | _gdk_wayland_display_deliver_event (display: gdk_seat_get_display (seat: pad->seat), |
4320 | event); |
4321 | } |
4322 | |
4323 | static const struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = { |
4324 | tablet_pad_group_handle_buttons, |
4325 | tablet_pad_group_handle_ring, |
4326 | tablet_pad_group_handle_strip, |
4327 | tablet_pad_group_handle_modes, |
4328 | tablet_pad_group_handle_done, |
4329 | tablet_pad_group_handle_mode, |
4330 | }; |
4331 | |
4332 | static void |
4333 | tablet_pad_handle_group (void *data, |
4334 | struct zwp_tablet_pad_v2 *wp_tablet_pad, |
4335 | struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group) |
4336 | { |
4337 | GdkWaylandTabletPadData *pad = data; |
4338 | GdkWaylandTabletPadGroupData *group; |
4339 | |
4340 | GDK_SEAT_NOTE (pad->seat, EVENTS, |
4341 | g_message ("tablet pad handle group, pad group = %p, group = %p" , |
4342 | wp_tablet_pad_group, wp_tablet_pad_group)); |
4343 | |
4344 | group = g_new0 (GdkWaylandTabletPadGroupData, 1); |
4345 | group->wp_tablet_pad_group = wp_tablet_pad_group; |
4346 | group->pad = pad; |
4347 | |
4348 | zwp_tablet_pad_group_v2_add_listener (wp_tablet_pad_group, |
4349 | &tablet_pad_group_listener, group); |
4350 | zwp_tablet_pad_group_v2_set_user_data (wp_tablet_pad_group, group); |
4351 | pad->mode_groups = g_list_append (list: pad->mode_groups, data: group); |
4352 | } |
4353 | |
4354 | static void |
4355 | tablet_pad_handle_path (void *data, |
4356 | struct zwp_tablet_pad_v2 *wp_tablet_pad, |
4357 | const char *path) |
4358 | { |
4359 | GdkWaylandTabletPadData *pad = data; |
4360 | |
4361 | GDK_SEAT_NOTE (pad->seat, EVENTS, |
4362 | g_message ("tablet pad handle path, pad = %p, path = %s" , |
4363 | wp_tablet_pad, path)); |
4364 | |
4365 | pad->path = g_strdup (str: path); |
4366 | } |
4367 | |
4368 | static void |
4369 | tablet_pad_handle_buttons (void *data, |
4370 | struct zwp_tablet_pad_v2 *wp_tablet_pad, |
4371 | uint32_t buttons) |
4372 | { |
4373 | GdkWaylandTabletPadData *pad = data; |
4374 | |
4375 | GDK_SEAT_NOTE (pad->seat, EVENTS, |
4376 | g_message ("tablet pad handle buttons, pad = %p, n_buttons = %d" , |
4377 | wp_tablet_pad, buttons)); |
4378 | |
4379 | pad->n_buttons = buttons; |
4380 | } |
4381 | |
4382 | static void |
4383 | tablet_pad_handle_done (void *data, |
4384 | struct zwp_tablet_pad_v2 *wp_tablet_pad) |
4385 | { |
4386 | GdkWaylandTabletPadData *pad = data; |
4387 | |
4388 | GDK_SEAT_NOTE (pad->seat, EVENTS, |
4389 | g_message ("tablet pad handle done, pad = %p" , wp_tablet_pad)); |
4390 | |
4391 | pad->device = |
4392 | g_object_new (GDK_TYPE_WAYLAND_DEVICE_PAD, |
4393 | first_property_name: "name" , "Pad device" , |
4394 | "source" , GDK_SOURCE_TABLET_PAD, |
4395 | "display" , gdk_seat_get_display (seat: pad->seat), |
4396 | "seat" , pad->seat, |
4397 | NULL); |
4398 | |
4399 | _gdk_device_set_associated_device (device: pad->device, GDK_WAYLAND_SEAT (pad->seat)->logical_keyboard); |
4400 | gdk_seat_device_added (GDK_SEAT (pad->seat), device: pad->device); |
4401 | } |
4402 | |
4403 | static void |
4404 | tablet_pad_handle_button (void *data, |
4405 | struct zwp_tablet_pad_v2 *wp_tablet_pad, |
4406 | uint32_t time, |
4407 | uint32_t button, |
4408 | uint32_t state) |
4409 | { |
4410 | GdkWaylandTabletPadData *pad = data; |
4411 | GdkWaylandTabletPadGroupData *group; |
4412 | GdkEvent *event; |
4413 | int n_group; |
4414 | |
4415 | GDK_SEAT_NOTE (pad->seat, EVENTS, |
4416 | g_message ("tablet pad handle button, pad = %p, button = %d, state = %d" , |
4417 | wp_tablet_pad, button, state)); |
4418 | |
4419 | group = tablet_pad_lookup_button_group (pad, button); |
4420 | |
4421 | #ifdef G_DISABLE_ASSERT |
4422 | if (group == NULL) |
4423 | return; |
4424 | #else |
4425 | g_assert (group != NULL); |
4426 | #endif |
4427 | |
4428 | n_group = g_list_index (list: pad->mode_groups, data: group); |
4429 | |
4430 | event = gdk_pad_event_new_button (type: state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED |
4431 | ? GDK_PAD_BUTTON_PRESS |
4432 | : GDK_PAD_BUTTON_RELEASE, |
4433 | GDK_WAYLAND_SEAT (pad->seat)->keyboard_focus, |
4434 | device: pad->device, |
4435 | time, |
4436 | group: n_group, |
4437 | button, |
4438 | mode: group->current_mode); |
4439 | |
4440 | _gdk_wayland_display_deliver_event (display: gdk_seat_get_display (seat: pad->seat), event); |
4441 | } |
4442 | |
4443 | static void |
4444 | tablet_pad_handle_enter (void *data, |
4445 | struct zwp_tablet_pad_v2 *wp_tablet_pad, |
4446 | uint32_t serial, |
4447 | struct zwp_tablet_v2 *wp_tablet, |
4448 | struct wl_surface *surface) |
4449 | { |
4450 | GdkWaylandTabletPadData *pad = data; |
4451 | GdkWaylandTabletData *tablet = zwp_tablet_v2_get_user_data (wp_tablet); |
4452 | |
4453 | GDK_SEAT_NOTE (pad->seat, EVENTS, |
4454 | g_message ("tablet pad handle enter, pad = %p, tablet = %p surface = %p" , |
4455 | wp_tablet_pad, wp_tablet, surface)); |
4456 | |
4457 | /* Relate pad and tablet */ |
4458 | tablet->pads = g_list_prepend (list: tablet->pads, data: pad); |
4459 | pad->current_tablet = tablet; |
4460 | } |
4461 | |
4462 | static void |
4463 | tablet_pad_handle_leave (void *data, |
4464 | struct zwp_tablet_pad_v2 *wp_tablet_pad, |
4465 | uint32_t serial, |
4466 | struct wl_surface *surface) |
4467 | { |
4468 | GdkWaylandTabletPadData *pad = data; |
4469 | |
4470 | GDK_SEAT_NOTE (pad->seat, EVENTS, |
4471 | g_message ("tablet pad handle leave, pad = %p, surface = %p" , |
4472 | wp_tablet_pad, surface)); |
4473 | |
4474 | if (pad->current_tablet) |
4475 | { |
4476 | pad->current_tablet->pads = g_list_remove (list: pad->current_tablet->pads, data: pad); |
4477 | pad->current_tablet = NULL; |
4478 | } |
4479 | } |
4480 | |
4481 | static void |
4482 | tablet_pad_handle_removed (void *data, |
4483 | struct zwp_tablet_pad_v2 *wp_tablet_pad) |
4484 | { |
4485 | GdkWaylandTabletPadData *pad = data; |
4486 | |
4487 | GDK_SEAT_NOTE (pad->seat, EVENTS, |
4488 | g_message ("tablet pad handle removed, pad = %p" , wp_tablet_pad)); |
4489 | |
4490 | /* Remove from the current tablet */ |
4491 | if (pad->current_tablet) |
4492 | { |
4493 | pad->current_tablet->pads = g_list_remove (list: pad->current_tablet->pads, data: pad); |
4494 | pad->current_tablet = NULL; |
4495 | } |
4496 | |
4497 | _gdk_wayland_seat_remove_tablet_pad (GDK_WAYLAND_SEAT (pad->seat), pad); |
4498 | } |
4499 | |
4500 | static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { |
4501 | tablet_pad_handle_group, |
4502 | tablet_pad_handle_path, |
4503 | tablet_pad_handle_buttons, |
4504 | tablet_pad_handle_done, |
4505 | tablet_pad_handle_button, |
4506 | tablet_pad_handle_enter, |
4507 | tablet_pad_handle_leave, |
4508 | tablet_pad_handle_removed, |
4509 | }; |
4510 | |
4511 | static void |
4512 | tablet_seat_handle_tablet_added (void *data, |
4513 | struct zwp_tablet_seat_v2 *wp_tablet_seat, |
4514 | struct zwp_tablet_v2 *wp_tablet) |
4515 | { |
4516 | GdkWaylandSeat *seat = data; |
4517 | GdkWaylandTabletData *tablet; |
4518 | |
4519 | tablet = g_new0 (GdkWaylandTabletData, 1); |
4520 | tablet->seat = GDK_SEAT (seat); |
4521 | |
4522 | tablet->wp_tablet = wp_tablet; |
4523 | |
4524 | seat->tablets = g_list_prepend (list: seat->tablets, data: tablet); |
4525 | |
4526 | zwp_tablet_v2_add_listener (wp_tablet, &tablet_listener, tablet); |
4527 | zwp_tablet_v2_set_user_data (wp_tablet, tablet); |
4528 | } |
4529 | |
4530 | static void |
4531 | tablet_seat_handle_tool_added (void *data, |
4532 | struct zwp_tablet_seat_v2 *wp_tablet_seat, |
4533 | struct zwp_tablet_tool_v2 *wp_tablet_tool) |
4534 | { |
4535 | GdkWaylandSeat *seat = data; |
4536 | GdkWaylandTabletToolData *tool; |
4537 | |
4538 | tool = g_new0 (GdkWaylandTabletToolData, 1); |
4539 | tool->wp_tablet_tool = wp_tablet_tool; |
4540 | tool->seat = GDK_SEAT (seat); |
4541 | |
4542 | zwp_tablet_tool_v2_add_listener (wp_tablet_tool, &tablet_tool_listener, tool); |
4543 | zwp_tablet_tool_v2_set_user_data (wp_tablet_tool, tool); |
4544 | |
4545 | seat->tablet_tools = g_list_prepend (list: seat->tablet_tools, data: tool); |
4546 | } |
4547 | |
4548 | static void |
4549 | tablet_seat_handle_pad_added (void *data, |
4550 | struct zwp_tablet_seat_v2 *wp_tablet_seat, |
4551 | struct zwp_tablet_pad_v2 *wp_tablet_pad) |
4552 | { |
4553 | GdkWaylandSeat *seat = data; |
4554 | GdkWaylandTabletPadData *pad; |
4555 | |
4556 | pad = g_new0 (GdkWaylandTabletPadData, 1); |
4557 | pad->wp_tablet_pad = wp_tablet_pad; |
4558 | pad->seat = GDK_SEAT (seat); |
4559 | |
4560 | zwp_tablet_pad_v2_add_listener (wp_tablet_pad, &tablet_pad_listener, pad); |
4561 | zwp_tablet_pad_v2_set_user_data (wp_tablet_pad, pad); |
4562 | |
4563 | seat->tablet_pads = g_list_prepend (list: seat->tablet_pads, data: pad); |
4564 | } |
4565 | |
4566 | static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { |
4567 | tablet_seat_handle_tablet_added, |
4568 | tablet_seat_handle_tool_added, |
4569 | tablet_seat_handle_pad_added, |
4570 | }; |
4571 | |
4572 | static void |
4573 | init_devices (GdkWaylandSeat *seat) |
4574 | { |
4575 | /* pointer */ |
4576 | seat->logical_pointer = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
4577 | first_property_name: "name" , "Core Pointer" , |
4578 | "source" , GDK_SOURCE_MOUSE, |
4579 | "has-cursor" , TRUE, |
4580 | "display" , seat->display, |
4581 | "seat" , seat, |
4582 | NULL); |
4583 | |
4584 | GDK_WAYLAND_DEVICE (seat->logical_pointer)->pointer = &seat->pointer_info; |
4585 | |
4586 | /* keyboard */ |
4587 | seat->logical_keyboard = g_object_new (GDK_TYPE_WAYLAND_DEVICE, |
4588 | first_property_name: "name" , "Core Keyboard" , |
4589 | "source" , GDK_SOURCE_KEYBOARD, |
4590 | "has-cursor" , FALSE, |
4591 | "display" , seat->display, |
4592 | "seat" , seat, |
4593 | NULL); |
4594 | _gdk_device_reset_axes (device: seat->logical_keyboard); |
4595 | |
4596 | /* link both */ |
4597 | _gdk_device_set_associated_device (device: seat->logical_pointer, relative: seat->logical_keyboard); |
4598 | _gdk_device_set_associated_device (device: seat->logical_keyboard, relative: seat->logical_pointer); |
4599 | |
4600 | gdk_seat_device_added (GDK_SEAT (seat), device: seat->logical_pointer); |
4601 | gdk_seat_device_added (GDK_SEAT (seat), device: seat->logical_keyboard); |
4602 | } |
4603 | |
4604 | static void |
4605 | pointer_surface_update_scale (GdkDevice *device) |
4606 | { |
4607 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
4608 | GdkWaylandPointerData *pointer = GDK_WAYLAND_DEVICE (device)->pointer; |
4609 | GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display); |
4610 | guint32 scale; |
4611 | GSList *l; |
4612 | |
4613 | if (display_wayland->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE) |
4614 | { |
4615 | /* We can't set the scale on this surface */ |
4616 | return; |
4617 | } |
4618 | |
4619 | if (!pointer->pointer_surface_outputs) |
4620 | return; |
4621 | |
4622 | scale = 1; |
4623 | for (l = pointer->pointer_surface_outputs; l != NULL; l = l->next) |
4624 | { |
4625 | guint32 output_scale = gdk_wayland_display_get_output_scale (display_wayland, output: l->data); |
4626 | scale = MAX (scale, output_scale); |
4627 | } |
4628 | |
4629 | if (pointer->current_output_scale == scale) |
4630 | return; |
4631 | pointer->current_output_scale = scale; |
4632 | |
4633 | gdk_wayland_device_update_surface_cursor (device); |
4634 | } |
4635 | |
4636 | void |
4637 | gdk_wayland_seat_update_cursor_scale (GdkWaylandSeat *seat) |
4638 | { |
4639 | GList *l; |
4640 | |
4641 | pointer_surface_update_scale (device: seat->logical_pointer); |
4642 | |
4643 | for (l = seat->tablets; l; l = l->next) |
4644 | { |
4645 | GdkWaylandTabletData *tablet = l->data; |
4646 | pointer_surface_update_scale (device: tablet->logical_device); |
4647 | } |
4648 | } |
4649 | |
4650 | static void |
4651 | pointer_surface_enter (void *data, |
4652 | struct wl_surface *wl_surface, |
4653 | struct wl_output *output) |
4654 | |
4655 | { |
4656 | GdkDevice *device = data; |
4657 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
4658 | GdkWaylandTabletData *tablet; |
4659 | |
4660 | GDK_SEAT_NOTE (seat, EVENTS, |
4661 | g_message ("pointer surface of seat %p entered output %p" , |
4662 | seat, output)); |
4663 | |
4664 | tablet = gdk_wayland_seat_find_tablet (seat, device); |
4665 | |
4666 | if (tablet) |
4667 | { |
4668 | tablet->pointer_info.pointer_surface_outputs = |
4669 | g_slist_append (list: tablet->pointer_info.pointer_surface_outputs, data: output); |
4670 | } |
4671 | else |
4672 | { |
4673 | seat->pointer_info.pointer_surface_outputs = |
4674 | g_slist_append (list: seat->pointer_info.pointer_surface_outputs, data: output); |
4675 | } |
4676 | |
4677 | pointer_surface_update_scale (device); |
4678 | } |
4679 | |
4680 | static void |
4681 | pointer_surface_leave (void *data, |
4682 | struct wl_surface *wl_surface, |
4683 | struct wl_output *output) |
4684 | { |
4685 | GdkDevice *device = data; |
4686 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device)); |
4687 | GdkWaylandTabletData *tablet; |
4688 | |
4689 | GDK_SEAT_NOTE (seat, EVENTS, |
4690 | g_message ("pointer surface of seat %p left output %p" , |
4691 | seat, output)); |
4692 | |
4693 | tablet = gdk_wayland_seat_find_tablet (seat, device); |
4694 | |
4695 | if (tablet) |
4696 | { |
4697 | tablet->pointer_info.pointer_surface_outputs = |
4698 | g_slist_remove (list: tablet->pointer_info.pointer_surface_outputs, data: output); |
4699 | } |
4700 | else |
4701 | { |
4702 | seat->pointer_info.pointer_surface_outputs = |
4703 | g_slist_remove (list: seat->pointer_info.pointer_surface_outputs, data: output); |
4704 | } |
4705 | |
4706 | pointer_surface_update_scale (device); |
4707 | } |
4708 | |
4709 | static const struct wl_surface_listener pointer_surface_listener = { |
4710 | pointer_surface_enter, |
4711 | pointer_surface_leave |
4712 | }; |
4713 | |
4714 | static void |
4715 | gdk_wayland_pointer_data_finalize (GdkWaylandPointerData *pointer) |
4716 | { |
4717 | g_clear_object (&pointer->focus); |
4718 | g_clear_object (&pointer->cursor); |
4719 | wl_surface_destroy (wl_surface: pointer->pointer_surface); |
4720 | g_slist_free (list: pointer->pointer_surface_outputs); |
4721 | } |
4722 | |
4723 | static void |
4724 | gdk_wayland_seat_finalize (GObject *object) |
4725 | { |
4726 | GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (object); |
4727 | GList *l; |
4728 | |
4729 | for (l = seat->tablet_tools; l != NULL; l = l->next) |
4730 | _gdk_wayland_seat_remove_tool (seat, tool: l->data); |
4731 | |
4732 | for (l = seat->tablet_pads; l != NULL; l = l->next) |
4733 | _gdk_wayland_seat_remove_tablet_pad (seat, pad: l->data); |
4734 | |
4735 | for (l = seat->tablets; l != NULL; l = l->next) |
4736 | _gdk_wayland_seat_remove_tablet (seat, tablet: l->data); |
4737 | |
4738 | seat_handle_capabilities (data: seat, wl_seat: seat->wl_seat, caps: 0); |
4739 | g_object_unref (object: seat->keymap); |
4740 | gdk_wayland_pointer_data_finalize (pointer: &seat->pointer_info); |
4741 | /* FIXME: destroy data_device */ |
4742 | g_clear_object (&seat->drag); |
4743 | g_clear_object (&seat->drop); |
4744 | g_clear_object (&seat->clipboard); |
4745 | g_clear_object (&seat->primary_clipboard); |
4746 | g_hash_table_destroy (hash_table: seat->touches); |
4747 | zwp_tablet_seat_v2_destroy (seat->wp_tablet_seat); |
4748 | stop_key_repeat (seat); |
4749 | |
4750 | G_OBJECT_CLASS (gdk_wayland_seat_parent_class)->finalize (object); |
4751 | } |
4752 | |
4753 | static GdkSeatCapabilities |
4754 | gdk_wayland_seat_get_capabilities (GdkSeat *seat) |
4755 | { |
4756 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); |
4757 | GdkSeatCapabilities caps = 0; |
4758 | |
4759 | if (wayland_seat->logical_pointer) |
4760 | caps |= GDK_SEAT_CAPABILITY_POINTER; |
4761 | if (wayland_seat->logical_keyboard) |
4762 | caps |= GDK_SEAT_CAPABILITY_KEYBOARD; |
4763 | if (wayland_seat->logical_touch) |
4764 | caps |= GDK_SEAT_CAPABILITY_TOUCH; |
4765 | |
4766 | return caps; |
4767 | } |
4768 | |
4769 | static void |
4770 | gdk_wayland_seat_set_grab_surface (GdkWaylandSeat *seat, |
4771 | GdkSurface *surface) |
4772 | { |
4773 | if (seat->grab_surface) |
4774 | { |
4775 | _gdk_wayland_surface_set_grab_seat (surface: seat->grab_surface, NULL); |
4776 | g_object_remove_weak_pointer (G_OBJECT (seat->grab_surface), |
4777 | weak_pointer_location: (gpointer *) &seat->grab_surface); |
4778 | seat->grab_surface = NULL; |
4779 | } |
4780 | |
4781 | if (surface) |
4782 | { |
4783 | seat->grab_surface = surface; |
4784 | g_object_add_weak_pointer (G_OBJECT (surface), |
4785 | weak_pointer_location: (gpointer *) &seat->grab_surface); |
4786 | _gdk_wayland_surface_set_grab_seat (surface, GDK_SEAT (seat)); |
4787 | } |
4788 | } |
4789 | |
4790 | static GdkGrabStatus |
4791 | gdk_wayland_seat_grab (GdkSeat *seat, |
4792 | GdkSurface *surface, |
4793 | GdkSeatCapabilities capabilities, |
4794 | gboolean owner_events, |
4795 | GdkCursor *cursor, |
4796 | GdkEvent *event, |
4797 | GdkSeatGrabPrepareFunc prepare_func, |
4798 | gpointer prepare_func_data) |
4799 | { |
4800 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); |
4801 | guint32 evtime = event ? gdk_event_get_time (event) : GDK_CURRENT_TIME; |
4802 | GdkDisplay *display = gdk_seat_get_display (seat); |
4803 | GList *l; |
4804 | |
4805 | if (surface == NULL || GDK_SURFACE_DESTROYED (surface)) |
4806 | return GDK_GRAB_NOT_VIEWABLE; |
4807 | |
4808 | gdk_wayland_seat_set_grab_surface (seat: wayland_seat, surface); |
4809 | wayland_seat->grab_time = evtime; |
4810 | |
4811 | if (prepare_func) |
4812 | (prepare_func) (seat, surface, prepare_func_data); |
4813 | |
4814 | if (!gdk_wayland_surface_has_surface (surface)) |
4815 | { |
4816 | gdk_wayland_seat_set_grab_surface (seat: wayland_seat, NULL); |
4817 | return GDK_GRAB_NOT_VIEWABLE; |
4818 | } |
4819 | |
4820 | if (wayland_seat->logical_pointer && |
4821 | capabilities & GDK_SEAT_CAPABILITY_POINTER) |
4822 | { |
4823 | device_maybe_emit_grab_crossing (device: wayland_seat->logical_pointer, |
4824 | window: surface, time: evtime); |
4825 | |
4826 | _gdk_display_add_device_grab (display, |
4827 | device: wayland_seat->logical_pointer, |
4828 | surface, |
4829 | owner_events, |
4830 | event_mask: GDK_ALL_EVENTS_MASK, |
4831 | serial_start: _gdk_display_get_next_serial (display), |
4832 | time: evtime, |
4833 | FALSE); |
4834 | |
4835 | gdk_wayland_seat_set_global_cursor (seat, cursor); |
4836 | g_set_object (&wayland_seat->cursor, cursor); |
4837 | gdk_wayland_device_update_surface_cursor (device: wayland_seat->logical_pointer); |
4838 | } |
4839 | |
4840 | if (wayland_seat->logical_touch && |
4841 | capabilities & GDK_SEAT_CAPABILITY_TOUCH) |
4842 | { |
4843 | device_maybe_emit_grab_crossing (device: wayland_seat->logical_touch, |
4844 | window: surface, time: evtime); |
4845 | |
4846 | _gdk_display_add_device_grab (display, |
4847 | device: wayland_seat->logical_touch, |
4848 | surface, |
4849 | owner_events, |
4850 | event_mask: GDK_ALL_EVENTS_MASK, |
4851 | serial_start: _gdk_display_get_next_serial (display), |
4852 | time: evtime, |
4853 | FALSE); |
4854 | } |
4855 | |
4856 | if (wayland_seat->logical_keyboard && |
4857 | capabilities & GDK_SEAT_CAPABILITY_KEYBOARD) |
4858 | { |
4859 | device_maybe_emit_grab_crossing (device: wayland_seat->logical_keyboard, |
4860 | window: surface, time: evtime); |
4861 | |
4862 | _gdk_display_add_device_grab (display, |
4863 | device: wayland_seat->logical_keyboard, |
4864 | surface, |
4865 | owner_events, |
4866 | event_mask: GDK_ALL_EVENTS_MASK, |
4867 | serial_start: _gdk_display_get_next_serial (display), |
4868 | time: evtime, |
4869 | FALSE); |
4870 | |
4871 | /* Inhibit shortcuts if the seat grab is for the keyboard only */ |
4872 | if (capabilities == GDK_SEAT_CAPABILITY_KEYBOARD) |
4873 | gdk_wayland_surface_inhibit_shortcuts (surface, gdk_seat: seat); |
4874 | } |
4875 | |
4876 | if (wayland_seat->tablets && |
4877 | capabilities & GDK_SEAT_CAPABILITY_TABLET_STYLUS) |
4878 | { |
4879 | for (l = wayland_seat->tablets; l; l = l->next) |
4880 | { |
4881 | GdkWaylandTabletData *tablet = l->data; |
4882 | |
4883 | device_maybe_emit_grab_crossing (device: tablet->logical_device, |
4884 | window: surface, |
4885 | time: evtime); |
4886 | |
4887 | _gdk_display_add_device_grab (display, |
4888 | device: tablet->logical_device, |
4889 | surface, |
4890 | owner_events, |
4891 | event_mask: GDK_ALL_EVENTS_MASK, |
4892 | serial_start: _gdk_display_get_next_serial (display), |
4893 | time: evtime, |
4894 | FALSE); |
4895 | |
4896 | gdk_wayland_device_update_surface_cursor (device: tablet->logical_device); |
4897 | } |
4898 | } |
4899 | |
4900 | return GDK_GRAB_SUCCESS; |
4901 | } |
4902 | |
4903 | static void |
4904 | gdk_wayland_seat_ungrab (GdkSeat *seat) |
4905 | { |
4906 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); |
4907 | GdkDisplay *display = gdk_seat_get_display (seat); |
4908 | GdkDeviceGrabInfo *grab; |
4909 | GList *l; |
4910 | |
4911 | g_clear_object (&wayland_seat->grab_cursor); |
4912 | |
4913 | gdk_wayland_seat_set_grab_surface (seat: wayland_seat, NULL); |
4914 | |
4915 | if (wayland_seat->logical_pointer) |
4916 | { |
4917 | device_maybe_emit_ungrab_crossing (device: wayland_seat->logical_pointer, |
4918 | GDK_CURRENT_TIME); |
4919 | |
4920 | gdk_wayland_device_update_surface_cursor (device: wayland_seat->logical_pointer); |
4921 | } |
4922 | |
4923 | if (wayland_seat->logical_keyboard) |
4924 | { |
4925 | GdkSurface *prev_focus; |
4926 | |
4927 | prev_focus = device_maybe_emit_ungrab_crossing (device: wayland_seat->logical_keyboard, |
4928 | GDK_CURRENT_TIME); |
4929 | if (prev_focus) |
4930 | gdk_wayland_surface_restore_shortcuts (surface: prev_focus, gdk_seat: seat); |
4931 | } |
4932 | |
4933 | if (wayland_seat->logical_touch) |
4934 | { |
4935 | grab = _gdk_display_get_last_device_grab (display, device: wayland_seat->logical_touch); |
4936 | |
4937 | if (grab) |
4938 | grab->serial_end = grab->serial_start; |
4939 | } |
4940 | |
4941 | for (l = wayland_seat->tablets; l; l = l->next) |
4942 | { |
4943 | GdkWaylandTabletData *tablet = l->data; |
4944 | |
4945 | grab = _gdk_display_get_last_device_grab (display, device: tablet->logical_device); |
4946 | |
4947 | if (grab) |
4948 | grab->serial_end = grab->serial_start; |
4949 | } |
4950 | } |
4951 | |
4952 | static GdkDevice * |
4953 | gdk_wayland_seat_get_logical_device (GdkSeat *seat, |
4954 | GdkSeatCapabilities capabilities) |
4955 | { |
4956 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); |
4957 | |
4958 | if (capabilities == GDK_SEAT_CAPABILITY_POINTER) |
4959 | return wayland_seat->logical_pointer; |
4960 | else if (capabilities == GDK_SEAT_CAPABILITY_KEYBOARD) |
4961 | return wayland_seat->logical_keyboard; |
4962 | else if (capabilities == GDK_SEAT_CAPABILITY_TOUCH) |
4963 | return wayland_seat->logical_touch; |
4964 | |
4965 | return NULL; |
4966 | } |
4967 | |
4968 | static GList * |
4969 | gdk_wayland_seat_get_devices (GdkSeat *seat, |
4970 | GdkSeatCapabilities capabilities) |
4971 | { |
4972 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); |
4973 | GList *physical_devices = NULL; |
4974 | |
4975 | if (wayland_seat->finger_scrolling && (capabilities & GDK_SEAT_CAPABILITY_POINTER)) |
4976 | physical_devices = g_list_prepend (list: physical_devices, data: wayland_seat->finger_scrolling); |
4977 | if (wayland_seat->continuous_scrolling && (capabilities & GDK_SEAT_CAPABILITY_POINTER)) |
4978 | physical_devices = g_list_prepend (list: physical_devices, data: wayland_seat->continuous_scrolling); |
4979 | if (wayland_seat->wheel_scrolling && (capabilities & GDK_SEAT_CAPABILITY_POINTER)) |
4980 | physical_devices = g_list_prepend (list: physical_devices, data: wayland_seat->wheel_scrolling); |
4981 | if (wayland_seat->pointer && (capabilities & GDK_SEAT_CAPABILITY_POINTER)) |
4982 | physical_devices = g_list_prepend (list: physical_devices, data: wayland_seat->pointer); |
4983 | if (wayland_seat->keyboard && (capabilities & GDK_SEAT_CAPABILITY_KEYBOARD)) |
4984 | physical_devices = g_list_prepend (list: physical_devices, data: wayland_seat->keyboard); |
4985 | if (wayland_seat->touch && (capabilities & GDK_SEAT_CAPABILITY_TOUCH)) |
4986 | physical_devices = g_list_prepend (list: physical_devices, data: wayland_seat->touch); |
4987 | |
4988 | if (wayland_seat->tablets && (capabilities & GDK_SEAT_CAPABILITY_TABLET_STYLUS)) |
4989 | { |
4990 | GList *l; |
4991 | |
4992 | for (l = wayland_seat->tablets; l; l = l->next) |
4993 | { |
4994 | GdkWaylandTabletData *tablet = l->data; |
4995 | |
4996 | physical_devices = g_list_prepend (list: physical_devices, data: tablet->stylus_device); |
4997 | } |
4998 | } |
4999 | |
5000 | if (wayland_seat->tablet_pads && (capabilities & GDK_SEAT_CAPABILITY_TABLET_PAD)) |
5001 | { |
5002 | GList *l; |
5003 | |
5004 | for (l = wayland_seat->tablet_pads; l; l = l->next) |
5005 | { |
5006 | GdkWaylandTabletPadData *data = l->data; |
5007 | physical_devices = g_list_prepend (list: physical_devices, data: data->device); |
5008 | } |
5009 | } |
5010 | |
5011 | return physical_devices; |
5012 | } |
5013 | |
5014 | static GList * |
5015 | gdk_wayland_seat_get_tools (GdkSeat *seat) |
5016 | { |
5017 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); |
5018 | GList *tools = NULL, *l; |
5019 | |
5020 | for (l = wayland_seat->tablet_tools; l; l = l->next) |
5021 | { |
5022 | GdkWaylandTabletToolData *tool = l->data; |
5023 | |
5024 | tools = g_list_prepend (list: tools, data: tool->tool); |
5025 | } |
5026 | |
5027 | return tools; |
5028 | } |
5029 | |
5030 | static void |
5031 | gdk_wayland_seat_class_init (GdkWaylandSeatClass *klass) |
5032 | { |
5033 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
5034 | GdkSeatClass *seat_class = GDK_SEAT_CLASS (klass); |
5035 | |
5036 | object_class->finalize = gdk_wayland_seat_finalize; |
5037 | |
5038 | seat_class->get_capabilities = gdk_wayland_seat_get_capabilities; |
5039 | seat_class->grab = gdk_wayland_seat_grab; |
5040 | seat_class->ungrab = gdk_wayland_seat_ungrab; |
5041 | seat_class->get_logical_device = gdk_wayland_seat_get_logical_device; |
5042 | seat_class->get_devices = gdk_wayland_seat_get_devices; |
5043 | seat_class->get_tools = gdk_wayland_seat_get_tools; |
5044 | } |
5045 | |
5046 | static void |
5047 | gdk_wayland_seat_init (GdkWaylandSeat *seat) |
5048 | { |
5049 | } |
5050 | |
5051 | static void |
5052 | init_pointer_data (GdkWaylandPointerData *pointer_data, |
5053 | GdkDisplay *display, |
5054 | GdkDevice *logical_device) |
5055 | { |
5056 | GdkWaylandDisplay *display_wayland; |
5057 | |
5058 | display_wayland = GDK_WAYLAND_DISPLAY (display); |
5059 | |
5060 | pointer_data->current_output_scale = 1; |
5061 | pointer_data->pointer_surface = |
5062 | wl_compositor_create_surface (wl_compositor: display_wayland->compositor); |
5063 | wl_surface_add_listener (wl_surface: pointer_data->pointer_surface, |
5064 | listener: &pointer_surface_listener, |
5065 | data: logical_device); |
5066 | } |
5067 | |
5068 | void |
5069 | _gdk_wayland_display_create_seat (GdkWaylandDisplay *display_wayland, |
5070 | guint32 id, |
5071 | struct wl_seat *wl_seat) |
5072 | { |
5073 | GdkDisplay *display = GDK_DISPLAY (display_wayland); |
5074 | GdkWaylandSeat *seat; |
5075 | |
5076 | seat = g_object_new (GDK_TYPE_WAYLAND_SEAT, |
5077 | first_property_name: "display" , display_wayland, |
5078 | NULL); |
5079 | seat->id = id; |
5080 | seat->keymap = _gdk_wayland_keymap_new (display); |
5081 | seat->display = display; |
5082 | seat->touches = g_hash_table_new_full (NULL, NULL, NULL, value_destroy_func: (GDestroyNotify) g_free); |
5083 | seat->wl_seat = wl_seat; |
5084 | |
5085 | wl_seat_add_listener (wl_seat: seat->wl_seat, listener: &seat_listener, data: seat); |
5086 | wl_seat_set_user_data (wl_seat: seat->wl_seat, user_data: seat); |
5087 | |
5088 | if (display_wayland->primary_selection_manager) |
5089 | { |
5090 | seat->primary_clipboard = gdk_wayland_primary_new (seat); |
5091 | } |
5092 | else |
5093 | { |
5094 | /* If the compositor doesn't support primary clipboard, |
5095 | * just do it local-only */ |
5096 | seat->primary_clipboard = gdk_clipboard_new (display); |
5097 | } |
5098 | |
5099 | seat->data_device = |
5100 | wl_data_device_manager_get_data_device (wl_data_device_manager: display_wayland->data_device_manager, |
5101 | seat: seat->wl_seat); |
5102 | seat->clipboard = gdk_wayland_clipboard_new (display); |
5103 | wl_data_device_add_listener (wl_data_device: seat->data_device, |
5104 | listener: &data_device_listener, data: seat); |
5105 | |
5106 | init_devices (seat); |
5107 | init_pointer_data (pointer_data: &seat->pointer_info, display, logical_device: seat->logical_pointer); |
5108 | |
5109 | if (display_wayland->tablet_manager) |
5110 | { |
5111 | seat->wp_tablet_seat = |
5112 | zwp_tablet_manager_v2_get_tablet_seat (display_wayland->tablet_manager, |
5113 | wl_seat); |
5114 | zwp_tablet_seat_v2_add_listener (seat->wp_tablet_seat, &tablet_seat_listener, |
5115 | seat); |
5116 | } |
5117 | |
5118 | if (display->clipboard == NULL) |
5119 | display->clipboard = g_object_ref (seat->clipboard); |
5120 | if (display->primary_clipboard == NULL) |
5121 | display->primary_clipboard = g_object_ref (seat->primary_clipboard); |
5122 | |
5123 | gdk_display_add_seat (display, GDK_SEAT (seat)); |
5124 | } |
5125 | |
5126 | void |
5127 | _gdk_wayland_display_remove_seat (GdkWaylandDisplay *display_wayland, |
5128 | guint32 id) |
5129 | { |
5130 | GdkDisplay *display = GDK_DISPLAY (display_wayland); |
5131 | GList *l, *seats; |
5132 | |
5133 | seats = gdk_display_list_seats (display); |
5134 | |
5135 | for (l = seats; l != NULL; l = l->next) |
5136 | { |
5137 | GdkWaylandSeat *seat = l->data; |
5138 | |
5139 | if (seat->id != id) |
5140 | continue; |
5141 | |
5142 | gdk_display_remove_seat (display, GDK_SEAT (seat)); |
5143 | break; |
5144 | } |
5145 | |
5146 | g_list_free (list: seats); |
5147 | } |
5148 | |
5149 | uint32_t |
5150 | _gdk_wayland_seat_get_implicit_grab_serial (GdkSeat *seat, |
5151 | GdkEvent *event) |
5152 | { |
5153 | GdkEventSequence *sequence = NULL; |
5154 | GdkWaylandTouchData *touch = NULL; |
5155 | |
5156 | if (event) |
5157 | sequence = gdk_event_get_event_sequence (event); |
5158 | |
5159 | if (sequence) |
5160 | touch = gdk_wayland_seat_get_touch (GDK_WAYLAND_SEAT (seat), |
5161 | GDK_EVENT_SEQUENCE_TO_SLOT (sequence)); |
5162 | |
5163 | if (touch) |
5164 | return touch->touch_down_serial; |
5165 | |
5166 | if (event) |
5167 | { |
5168 | GdkDevice *source = gdk_event_get_device (event); |
5169 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); |
5170 | GList *l; |
5171 | |
5172 | for (l = wayland_seat->tablets; l; l = l->next) |
5173 | { |
5174 | GdkWaylandTabletData *tablet = l->data; |
5175 | |
5176 | if (tablet->stylus_device == source) |
5177 | return tablet->pointer_info.press_serial; |
5178 | } |
5179 | } |
5180 | |
5181 | return GDK_WAYLAND_SEAT (seat)->pointer_info.press_serial; |
5182 | } |
5183 | |
5184 | uint32_t |
5185 | _gdk_wayland_seat_get_last_implicit_grab_serial (GdkWaylandSeat *seat, |
5186 | GdkEventSequence **sequence) |
5187 | { |
5188 | GdkWaylandTouchData *touch; |
5189 | GHashTableIter iter; |
5190 | GList *l; |
5191 | uint32_t serial; |
5192 | |
5193 | g_hash_table_iter_init (iter: &iter, hash_table: seat->touches); |
5194 | |
5195 | if (sequence) |
5196 | *sequence = NULL; |
5197 | |
5198 | serial = seat->keyboard_key_serial; |
5199 | |
5200 | if (seat->pointer_info.press_serial > serial) |
5201 | serial = seat->pointer_info.press_serial; |
5202 | |
5203 | for (l = seat->tablets; l; l = l->next) |
5204 | { |
5205 | GdkWaylandTabletData *tablet = l->data; |
5206 | |
5207 | if (tablet->pointer_info.press_serial > serial) |
5208 | serial = tablet->pointer_info.press_serial; |
5209 | } |
5210 | |
5211 | while (g_hash_table_iter_next (iter: &iter, NULL, value: (gpointer *) &touch)) |
5212 | { |
5213 | if (touch->touch_down_serial > serial) |
5214 | { |
5215 | if (sequence) |
5216 | *sequence = GDK_SLOT_TO_EVENT_SEQUENCE (touch->id); |
5217 | serial = touch->touch_down_serial; |
5218 | } |
5219 | } |
5220 | |
5221 | return serial; |
5222 | } |
5223 | |
5224 | void |
5225 | gdk_wayland_device_unset_touch_grab (GdkDevice *gdk_device, |
5226 | GdkEventSequence *sequence) |
5227 | { |
5228 | GdkWaylandSeat *seat; |
5229 | GdkWaylandTouchData *touch; |
5230 | GdkEvent *event; |
5231 | |
5232 | g_return_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device)); |
5233 | |
5234 | seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device)); |
5235 | touch = gdk_wayland_seat_get_touch (seat, |
5236 | GDK_EVENT_SEQUENCE_TO_SLOT (sequence)); |
5237 | |
5238 | if (GDK_WAYLAND_DEVICE (seat->logical_touch)->emulating_touch == touch) |
5239 | { |
5240 | GDK_WAYLAND_DEVICE (seat->logical_touch)->emulating_touch = NULL; |
5241 | emulate_touch_crossing (surface: touch->surface, NULL, |
5242 | device: seat->logical_touch, source: seat->touch, |
5243 | touch, type: GDK_LEAVE_NOTIFY, mode: GDK_CROSSING_NORMAL, |
5244 | GDK_CURRENT_TIME); |
5245 | } |
5246 | |
5247 | event = gdk_touch_event_new (type: GDK_TOUCH_CANCEL, |
5248 | GDK_SLOT_TO_EVENT_SEQUENCE (touch->id), |
5249 | surface: touch->surface, |
5250 | device: seat->logical_touch, |
5251 | GDK_CURRENT_TIME, |
5252 | state: device_get_modifiers (device: seat->logical_touch), |
5253 | x: touch->x, y: touch->y, |
5254 | NULL, |
5255 | emulating: touch->initial_touch); |
5256 | _gdk_wayland_display_deliver_event (display: seat->display, event); |
5257 | } |
5258 | |
5259 | void |
5260 | gdk_wayland_seat_set_global_cursor (GdkSeat *seat, |
5261 | GdkCursor *cursor) |
5262 | { |
5263 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); |
5264 | GdkDevice *pointer; |
5265 | |
5266 | pointer = gdk_seat_get_pointer (seat); |
5267 | |
5268 | g_set_object (&wayland_seat->grab_cursor, cursor); |
5269 | gdk_wayland_device_set_surface_cursor (device: pointer, |
5270 | surface: gdk_wayland_device_get_focus (device: pointer), |
5271 | NULL); |
5272 | } |
5273 | |
5274 | void |
5275 | gdk_wayland_seat_set_drag (GdkSeat *seat, |
5276 | GdkDrag *drag) |
5277 | { |
5278 | GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); |
5279 | |
5280 | g_set_object (&wayland_seat->drag, drag); |
5281 | } |
5282 | |
5283 | /** |
5284 | * gdk_wayland_device_get_data_device: (skip) |
5285 | * @gdk_device: (type GdkWaylandDevice): a `GdkDevice` |
5286 | * |
5287 | * Returns the Wayland `wl_data_device` of a `GdkDevice`. |
5288 | * |
5289 | * Returns: (transfer none): a Wayland `wl_data_device` |
5290 | */ |
5291 | struct wl_data_device * |
5292 | gdk_wayland_device_get_data_device (GdkDevice *gdk_device) |
5293 | { |
5294 | GdkWaylandSeat *seat; |
5295 | |
5296 | g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), NULL); |
5297 | |
5298 | seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device)); |
5299 | return seat->data_device; |
5300 | } |
5301 | |
5302 | /** |
5303 | * gdk_wayland_device_set_selection: (skip) |
5304 | * @gdk_device: (type GdkWaylandDevice): a `GdkDevice` |
5305 | * @source: the data source for the selection |
5306 | * |
5307 | * Sets the selection of the `GdkDevice. |
5308 | * |
5309 | * This is calling wl_data_device_set_selection() on |
5310 | * the `wl_data_device` of @gdk_device. |
5311 | */ |
5312 | void |
5313 | gdk_wayland_device_set_selection (GdkDevice *gdk_device, |
5314 | struct wl_data_source *source) |
5315 | { |
5316 | GdkWaylandSeat *seat; |
5317 | GdkWaylandDisplay *display_wayland; |
5318 | |
5319 | g_return_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device)); |
5320 | |
5321 | seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device)); |
5322 | display_wayland = GDK_WAYLAND_DISPLAY (seat->display); |
5323 | |
5324 | wl_data_device_set_selection (wl_data_device: seat->data_device, source, |
5325 | serial: _gdk_wayland_display_get_serial (display_wayland)); |
5326 | } |
5327 | |
5328 | /** |
5329 | * gdk_wayland_seat_get_wl_seat: (skip) |
5330 | * @seat: (type GdkWaylandSeat): a `GdkSeat` |
5331 | * |
5332 | * Returns the Wayland `wl_seat` of a `GdkSeat`. |
5333 | * |
5334 | * Returns: (transfer none): a Wayland `wl_seat` |
5335 | */ |
5336 | struct wl_seat * |
5337 | gdk_wayland_seat_get_wl_seat (GdkSeat *seat) |
5338 | { |
5339 | g_return_val_if_fail (GDK_IS_WAYLAND_SEAT (seat), NULL); |
5340 | |
5341 | return GDK_WAYLAND_SEAT (seat)->wl_seat; |
5342 | } |
5343 | |
5344 | /** |
5345 | * gdk_wayland_device_get_node_path: |
5346 | * @device: (type GdkWaylandDevice): a `GdkDevice` |
5347 | * |
5348 | * Returns the `/dev/input/event*` path of this device. |
5349 | * |
5350 | * For `GdkDevice`s that possibly coalesce multiple hardware |
5351 | * devices (eg. mouse, keyboard, touch,...), this function |
5352 | * will return %NULL. |
5353 | * |
5354 | * This is most notably implemented for devices of type |
5355 | * %GDK_SOURCE_PEN, %GDK_SOURCE_TABLET_PAD. |
5356 | * |
5357 | * Returns: (nullable) (transfer none): the `/dev/input/event*` |
5358 | * path of this device |
5359 | */ |
5360 | const char * |
5361 | gdk_wayland_device_get_node_path (GdkDevice *device) |
5362 | { |
5363 | GdkWaylandTabletData *tablet; |
5364 | GdkWaylandTabletPadData *pad; |
5365 | |
5366 | GdkSeat *seat; |
5367 | |
5368 | g_return_val_if_fail (GDK_IS_DEVICE (device), NULL); |
5369 | |
5370 | seat = gdk_device_get_seat (device); |
5371 | tablet = gdk_wayland_seat_find_tablet (GDK_WAYLAND_SEAT (seat), device); |
5372 | if (tablet) |
5373 | return tablet->path; |
5374 | |
5375 | pad = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat), device); |
5376 | if (pad) |
5377 | return pad->path; |
5378 | |
5379 | return NULL; |
5380 | } |
5381 | |
5382 | /*<private> |
5383 | * gdk_wayland_device_pad_set_feedback: |
5384 | * @device: (type GdkWaylandDevice): a %GDK_SOURCE_TABLET_PAD device |
5385 | * @feature: Feature to set the feedback label for |
5386 | * @feature_idx: 0-indexed index of the feature to set the feedback label for |
5387 | * @label: Feedback label |
5388 | * |
5389 | * Sets the feedback label for the given feature/index. |
5390 | * |
5391 | * This may be used by the compositor to provide user feedback |
5392 | * of the actions available/performed. |
5393 | */ |
5394 | void |
5395 | gdk_wayland_device_pad_set_feedback (GdkDevice *device, |
5396 | GdkDevicePadFeature feature, |
5397 | guint feature_idx, |
5398 | const char *label) |
5399 | { |
5400 | GdkWaylandTabletPadData *pad; |
5401 | GdkWaylandTabletPadGroupData *group; |
5402 | GdkSeat *seat; |
5403 | |
5404 | seat = gdk_device_get_seat (device); |
5405 | pad = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat), device); |
5406 | if (!pad) |
5407 | return; |
5408 | |
5409 | if (feature == GDK_DEVICE_PAD_FEATURE_BUTTON) |
5410 | { |
5411 | group = tablet_pad_lookup_button_group (pad, button: feature_idx); |
5412 | if (!group) |
5413 | return; |
5414 | |
5415 | zwp_tablet_pad_v2_set_feedback (pad->wp_tablet_pad, feature_idx, label, |
5416 | group->mode_switch_serial); |
5417 | } |
5418 | else if (feature == GDK_DEVICE_PAD_FEATURE_RING) |
5419 | { |
5420 | struct zwp_tablet_pad_ring_v2 *wp_pad_ring; |
5421 | |
5422 | wp_pad_ring = g_list_nth_data (list: pad->rings, n: feature_idx); |
5423 | if (!wp_pad_ring) |
5424 | return; |
5425 | |
5426 | group = zwp_tablet_pad_ring_v2_get_user_data (wp_pad_ring); |
5427 | zwp_tablet_pad_ring_v2_set_feedback (wp_pad_ring, label, |
5428 | group->mode_switch_serial); |
5429 | |
5430 | } |
5431 | else if (feature == GDK_DEVICE_PAD_FEATURE_STRIP) |
5432 | { |
5433 | struct zwp_tablet_pad_strip_v2 *wp_pad_strip; |
5434 | |
5435 | wp_pad_strip = g_list_nth_data (list: pad->strips, n: feature_idx); |
5436 | if (!wp_pad_strip) |
5437 | return; |
5438 | |
5439 | group = zwp_tablet_pad_strip_v2_get_user_data (wp_pad_strip); |
5440 | zwp_tablet_pad_strip_v2_set_feedback (wp_pad_strip, label, |
5441 | group->mode_switch_serial); |
5442 | } |
5443 | } |
5444 | |