FreeRDP
Loading...
Searching...
No Matches
uwac-input.c
1/*
2 * Copyright © 2014-2015 David FORT <contact@hardening-consulting.com>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22#include "uwac-priv.h"
23#include "uwac-utils.h"
24
25#include <stdio.h>
26#include <inttypes.h>
27#include <stdlib.h>
28#include <stdint.h>
29#include <string.h>
30#include <assert.h>
31#include <errno.h>
32#include <time.h>
33#include <unistd.h>
34#include <sys/mman.h>
35#include <sys/timerfd.h>
36#include <sys/epoll.h>
37
38#include <winpr/cast.h>
39
40#include "uwac-os.h"
41#include "wayland-cursor.h"
42#include "wayland-client-protocol.h"
43
44static struct wl_buffer* create_pointer_buffer(UwacSeat* seat, const void* src, size_t size)
45{
46 struct wl_buffer* buffer = nullptr;
47 struct wl_shm_pool* pool = nullptr;
48
49 assert(seat);
50
51 const int fd = uwac_create_anonymous_file(WINPR_ASSERTING_INT_CAST(off_t, size));
52
53 if (fd < 0)
54 return buffer;
55
56 void* data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
57
58 if (data == MAP_FAILED)
59 {
60 goto error_mmap;
61 }
62 memcpy(data, src, size);
63
64 pool = wl_shm_create_pool(seat->display->shm, fd, WINPR_ASSERTING_INT_CAST(int32_t, size));
65
66 if (!pool)
67 {
68 munmap(data, size);
69 goto error_mmap;
70 }
71
72 buffer = wl_shm_pool_create_buffer(
73 pool, 0, WINPR_ASSERTING_INT_CAST(int32_t, seat->pointer_image->width),
74 WINPR_ASSERTING_INT_CAST(int32_t, seat->pointer_image->height),
75 WINPR_ASSERTING_INT_CAST(int32_t, seat->pointer_image->width * 4), WL_SHM_FORMAT_ARGB8888);
76 wl_shm_pool_destroy(pool);
77
78 if (munmap(data, size) < 0)
79 {
80 char buffer[256] = WINPR_C_ARRAY_INIT;
81 (void)fprintf(stderr, "%s: munmap(%p, %zu) failed with [%d] %s\n", __func__, data, size,
82 errno, uwac_strerror(errno, buffer, sizeof(buffer)));
83 }
84
85error_mmap:
86 close(fd);
87 return buffer;
88}
89
90static void on_buffer_release(void* data, struct wl_buffer* wl_buffer)
91{
92 (void)data;
93 wl_buffer_destroy(wl_buffer);
94}
95
96static const struct wl_buffer_listener buffer_release_listener = { on_buffer_release };
97
98static UwacReturnCode set_cursor_image(UwacSeat* seat, uint32_t serial)
99{
100 struct wl_buffer* buffer = nullptr;
101 struct wl_cursor* cursor = nullptr;
102 struct wl_cursor_image* image = nullptr;
103 struct wl_surface* surface = nullptr;
104 int32_t x = 0;
105 int32_t y = 0;
106
107 if (!seat || !seat->display || !seat->default_cursor || !seat->default_cursor->images)
108 return UWAC_ERROR_INTERNAL;
109
110 int scale = 1;
111 if (seat->pointer_focus)
112 scale = seat->pointer_focus->display->actual_scale;
113
114 switch (seat->pointer_type)
115 {
116 case 2: /* Custom pointer */
117 image = seat->pointer_image;
118 buffer = create_pointer_buffer(seat, seat->pointer_data, seat->pointer_size);
119 if (!buffer)
120 return UWAC_ERROR_INTERNAL;
121 if (wl_buffer_add_listener(buffer, &buffer_release_listener, seat) < 0)
122 return UWAC_ERROR_INTERNAL;
123
124 surface = seat->pointer_surface;
125 x = WINPR_ASSERTING_INT_CAST(int32_t, image->hotspot_x / scale);
126 y = WINPR_ASSERTING_INT_CAST(int32_t, image->hotspot_y / scale);
127 break;
128 case 1: /* nullptr pointer */
129 break;
130 default: /* Default system pointer */
131 cursor = seat->default_cursor;
132 if (!cursor)
133 return UWAC_ERROR_INTERNAL;
134 image = cursor->images[0];
135 if (!image)
136 return UWAC_ERROR_INTERNAL;
137 x = WINPR_ASSERTING_INT_CAST(int32_t, image->hotspot_x);
138 y = WINPR_ASSERTING_INT_CAST(int32_t, image->hotspot_y);
139 buffer = wl_cursor_image_get_buffer(image);
140 if (!buffer)
141 return UWAC_ERROR_INTERNAL;
142 surface = seat->pointer_surface;
143 break;
144 }
145
146 if (surface && buffer)
147 {
148 wl_surface_set_buffer_scale(surface, scale);
149 wl_surface_attach(surface, buffer, 0, 0);
150 wl_surface_damage(surface, 0, 0, WINPR_ASSERTING_INT_CAST(int32_t, image->width),
151 WINPR_ASSERTING_INT_CAST(int32_t, image->height));
152 wl_surface_commit(surface);
153 }
154
155 wl_pointer_set_cursor(seat->pointer, serial, surface, x, y);
156
157 return UWAC_SUCCESS;
158}
159
160static void keyboard_repeat_func(UwacTask* task, uint32_t events)
161{
162 UwacSeat* input = container_of(task, UwacSeat, repeat_task);
163 assert(input);
164 UwacWindow* window = input->keyboard_focus;
165 uint64_t exp = 0;
166
167 if (read(input->repeat_timer_fd, &exp, sizeof exp) != sizeof exp)
168 /* If we change the timer between the fd becoming
169 * readable and getting here, there'll be nothing to
170 * read and we get EAGAIN. */
171 return;
172
173 if (window)
174 {
175 UwacKeyEvent* key = nullptr;
176
177 key = (UwacKeyEvent*)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEY);
178 if (!key)
179 return;
180
181 key->window = window;
182 key->sym = input->repeat_sym;
183 key->raw_key = input->repeat_key;
184 key->pressed = true;
185 key->repeated = true;
186 }
187}
188
189static void keyboard_handle_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format,
190 int fd, uint32_t size)
191{
192 UwacSeat* input = data;
193 struct xkb_keymap* keymap = nullptr;
194 struct xkb_state* state = nullptr;
195 char* map_str = nullptr;
196 int mapFlags = MAP_SHARED;
197
198 if (!data)
199 {
200 close(fd);
201 return;
202 }
203
204 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
205 {
206 close(fd);
207 return;
208 }
209
210 if (input->seat_version >= 7)
211 mapFlags = MAP_PRIVATE;
212
213 map_str = mmap(nullptr, size, PROT_READ, mapFlags, fd, 0);
214 if (map_str == MAP_FAILED)
215 {
216 close(fd);
217 return;
218 }
219
220 keymap = xkb_keymap_new_from_string(input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
221 munmap(map_str, size);
222 close(fd);
223
224 if (!keymap)
225 {
226 assert(uwacErrorHandler(input->display, UWAC_ERROR_INTERNAL, "failed to compile keymap\n"));
227 return;
228 }
229
230 state = xkb_state_new(keymap);
231 if (!state)
232 {
233 assert(
234 uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY, "failed to create XKB state\n"));
235 xkb_keymap_unref(keymap);
236 return;
237 }
238
239 xkb_keymap_unref(input->xkb.keymap);
240 xkb_state_unref(input->xkb.state);
241 input->xkb.keymap = keymap;
242 input->xkb.state = state;
243
244 input->xkb.control_mask = 1u << xkb_keymap_mod_get_index(input->xkb.keymap, "Control");
245 input->xkb.alt_mask = 1u << xkb_keymap_mod_get_index(input->xkb.keymap, "Mod1");
246 input->xkb.shift_mask = 1u << xkb_keymap_mod_get_index(input->xkb.keymap, "Shift");
247 input->xkb.caps_mask = 1u << xkb_keymap_mod_get_index(input->xkb.keymap, "Lock");
248 input->xkb.num_mask = 1u << xkb_keymap_mod_get_index(input->xkb.keymap, "Mod2");
249}
250
251static void keyboard_handle_key(void* data, struct wl_keyboard* keyboard, uint32_t serial,
252 uint32_t time, uint32_t key, uint32_t state_w);
253
254static void keyboard_handle_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial,
255 struct wl_surface* surface, struct wl_array* keys)
256{
257 UwacSeat* input = (UwacSeat*)data;
258 assert(input);
259
260 UwacKeyboardEnterLeaveEvent* event = (UwacKeyboardEnterLeaveEvent*)UwacDisplayNewEvent(
261 input->display, UWAC_EVENT_KEYBOARD_ENTER);
262 if (!event)
263 return;
264
265 event->window = input->keyboard_focus = (UwacWindow*)wl_surface_get_user_data(surface);
266 event->seat = input;
267
268 /* we may have the keys in the `keys` array, but as this function is called only
269 * when the window gets focus, so there may be keys from other unrelated windows, eg.
270 * this was leading to problems like passing CTRL+D to freerdp from closing terminal window
271 * if it was closing very fast and the keys was still pressed by the user while the freerdp
272 * gets focus
273 *
274 * currently just ignore this, as further key presses will be handled correctly anyway
275 */
276}
277
278static void keyboard_handle_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial,
279 struct wl_surface* surface)
280{
281 struct itimerspec its = WINPR_C_ARRAY_INIT;
282 uint32_t* pressedKey = nullptr;
283 size_t i = 0;
284
285 UwacSeat* input = (UwacSeat*)data;
286 assert(input);
287
288 its.it_interval.tv_sec = 0;
289 its.it_interval.tv_nsec = 0;
290 its.it_value.tv_sec = 0;
291 its.it_value.tv_nsec = 0;
292 (void)timerfd_settime(input->repeat_timer_fd, 0, &its, nullptr);
293
294 UwacPointerEnterLeaveEvent* event =
295 (UwacPointerEnterLeaveEvent*)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_LEAVE);
296 if (!event)
297 return;
298
299 event->window = input->keyboard_focus;
300
301 /* we are currently losing input focus of the main window:
302 * check if we currently have some keys pressed and release them as if we enter the window again
303 * it will be still "virtually" pressed in remote even if in reality the key has been released
304 */
305 for (pressedKey = input->pressed_keys.data, i = 0; i < input->pressed_keys.size;
306 i += sizeof(uint32_t))
307 {
308 keyboard_handle_key(data, keyboard, serial, 0, *pressedKey, WL_KEYBOARD_KEY_STATE_RELEASED);
309 pressedKey++;
310 }
311}
312
313static int update_key_pressed(UwacSeat* seat, uint32_t key)
314{
315 uint32_t* keyPtr = nullptr;
316 assert(seat);
317
318 /* check if the key is not already pressed */
319 wl_array_for_each(keyPtr, &seat->pressed_keys)
320 {
321 if (*keyPtr == key)
322 return 1;
323 }
324
325 keyPtr = wl_array_add(&seat->pressed_keys, sizeof(uint32_t));
326 if (!keyPtr)
327 return -1;
328
329 *keyPtr = key;
330 return 0;
331}
332
333static int update_key_released(UwacSeat* seat, uint32_t key)
334{
335 size_t toMove = 0;
336 bool found = false;
337
338 assert(seat);
339
340 size_t i = 0;
341 uint32_t* keyPtr = seat->pressed_keys.data;
342 for (; i < seat->pressed_keys.size; i++, keyPtr++)
343 {
344 if (*keyPtr == key)
345 {
346 found = true;
347 break;
348 }
349 }
350
351 if (found)
352 {
353 toMove = seat->pressed_keys.size - ((i + 1) * sizeof(uint32_t));
354 if (toMove)
355 memmove(keyPtr, keyPtr + 1, toMove);
356
357 seat->pressed_keys.size -= sizeof(uint32_t);
358 }
359 return 1;
360}
361
362static void keyboard_handle_key(void* data, struct wl_keyboard* keyboard, uint32_t serial,
363 uint32_t time, uint32_t key, uint32_t state_w)
364{
365 UwacSeat* input = (UwacSeat*)data;
366 assert(input);
367
368 UwacWindow* window = input->keyboard_focus;
369 UwacKeyEvent* keyEvent = nullptr;
370
371 uint32_t code = 0;
372 uint32_t num_syms = 0;
373 enum wl_keyboard_key_state state = state_w;
374 const xkb_keysym_t* syms = nullptr;
375 xkb_keysym_t sym = 0;
376 struct itimerspec its;
377
378 if (state_w == WL_KEYBOARD_KEY_STATE_PRESSED)
379 update_key_pressed(input, key);
380 else
381 update_key_released(input, key);
382
383 input->display->serial = serial;
384 code = key + 8;
385 if (!window || !input->xkb.state)
386 return;
387
388 /* We only use input grabs for pointer events for now, so just
389 * ignore key presses if a grab is active. We expand the key
390 * event delivery mechanism to route events to widgets to
391 * properly handle key grabs. In the meantime, this prevents
392 * key event delivery while a grab is active. */
393 /*if (input->grab && input->grab_button == 0)
394 return;*/
395
396 num_syms = xkb_state_key_get_syms(input->xkb.state, code, &syms);
397
398 sym = XKB_KEY_NoSymbol;
399 if (num_syms == 1)
400 sym = syms[0];
401
402 if (state == WL_KEYBOARD_KEY_STATE_RELEASED && key == input->repeat_key)
403 {
404 its.it_interval.tv_sec = 0;
405 its.it_interval.tv_nsec = 0;
406 its.it_value.tv_sec = 0;
407 its.it_value.tv_nsec = 0;
408 (void)timerfd_settime(input->repeat_timer_fd, 0, &its, nullptr);
409 }
410 else if (state == WL_KEYBOARD_KEY_STATE_PRESSED &&
411 xkb_keymap_key_repeats(input->xkb.keymap, code))
412 {
413 input->repeat_sym = sym;
414 input->repeat_key = key;
415 input->repeat_time = time;
416 its.it_interval.tv_sec = input->repeat_rate_sec;
417 its.it_interval.tv_nsec = input->repeat_rate_nsec;
418 its.it_value.tv_sec = input->repeat_delay_sec;
419 its.it_value.tv_nsec = input->repeat_delay_nsec;
420 (void)timerfd_settime(input->repeat_timer_fd, 0, &its, nullptr);
421 }
422
423 keyEvent = (UwacKeyEvent*)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEY);
424 if (!keyEvent)
425 return;
426
427 keyEvent->window = window;
428 keyEvent->sym = sym;
429 keyEvent->raw_key = key;
430 keyEvent->pressed = (state == WL_KEYBOARD_KEY_STATE_PRESSED);
431 keyEvent->repeated = false;
432}
433
434static void keyboard_handle_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial,
435 uint32_t mods_depressed, uint32_t mods_latched,
436 uint32_t mods_locked, uint32_t group)
437{
438 UwacSeat* input = data;
439 assert(input);
440
441 UwacKeyboardModifiersEvent* event = nullptr;
442 xkb_mod_mask_t mask = 0;
443
444 /* If we're not using a keymap, then we don't handle PC-style modifiers */
445 if (!input->xkb.keymap)
446 return;
447
448 xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
449
450 // NOLINTBEGIN(clang-analyzer-optin.core.EnumCastOutOfRange)
451 enum xkb_state_component components =
452 XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED;
453 // NOLINTEND(clang-analyzer-optin.core.EnumCastOutOfRange)
454 mask = xkb_state_serialize_mods(input->xkb.state, components);
455 input->modifiers = 0;
456 if (mask & input->xkb.control_mask)
457 input->modifiers |= UWAC_MOD_CONTROL_MASK;
458 if (mask & input->xkb.alt_mask)
459 input->modifiers |= UWAC_MOD_ALT_MASK;
460 if (mask & input->xkb.shift_mask)
461 input->modifiers |= UWAC_MOD_SHIFT_MASK;
462 if (mask & input->xkb.caps_mask)
463 input->modifiers |= UWAC_MOD_CAPS_MASK;
464 if (mask & input->xkb.num_mask)
465 input->modifiers |= UWAC_MOD_NUM_MASK;
466
467 event = (UwacKeyboardModifiersEvent*)UwacDisplayNewEvent(input->display,
468 UWAC_EVENT_KEYBOARD_MODIFIERS);
469 if (!event)
470 return;
471
472 event->modifiers = input->modifiers;
473}
474
475static void set_repeat_info(UwacSeat* input, int32_t rate, int32_t delay)
476{
477 assert(input);
478
479 input->repeat_rate_sec = input->repeat_rate_nsec = 0;
480 input->repeat_delay_sec = input->repeat_delay_nsec = 0;
481
482 /* a rate of zero disables any repeating, regardless of the delay's
483 * value */
484 if (rate == 0)
485 return;
486
487 if (rate == 1)
488 input->repeat_rate_sec = 1;
489 else
490 input->repeat_rate_nsec = 1000000000 / rate;
491
492 input->repeat_delay_sec = delay / 1000;
493 delay -= (input->repeat_delay_sec * 1000);
494 input->repeat_delay_nsec = delay * 1000 * 1000;
495}
496
497static void keyboard_handle_repeat_info(void* data, struct wl_keyboard* keyboard, int32_t rate,
498 int32_t delay)
499{
500 UwacSeat* input = data;
501 assert(input);
502
503 set_repeat_info(input, rate, delay);
504}
505
506static const struct wl_keyboard_listener keyboard_listener = {
507 keyboard_handle_keymap, keyboard_handle_enter, keyboard_handle_leave,
508 keyboard_handle_key, keyboard_handle_modifiers, keyboard_handle_repeat_info
509};
510
511static bool touch_send_start_frame(UwacSeat* seat)
512{
513 assert(seat);
514
515 UwacTouchFrameBegin* ev =
516 (UwacTouchFrameBegin*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_BEGIN);
517 if (!ev)
518 return false;
519
520 seat->touch_frame_started = true;
521 return true;
522}
523
524static void touch_handle_down(void* data, struct wl_touch* wl_touch, uint32_t serial, uint32_t time,
525 struct wl_surface* surface, int32_t id, wl_fixed_t x_w,
526 wl_fixed_t y_w)
527{
528 UwacSeat* seat = data;
529 UwacTouchDown* tdata = nullptr;
530
531 assert(seat);
532 assert(seat->display);
533
534 seat->display->serial = serial;
535 if (!seat->touch_frame_started && !touch_send_start_frame(seat))
536 return;
537
538 tdata = (UwacTouchDown*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_DOWN);
539 if (!tdata)
540 return;
541
542 tdata->seat = seat;
543 tdata->id = id;
544
545 double sx = wl_fixed_to_double(x_w);
546 double sy = wl_fixed_to_double(y_w);
547
548 tdata->x = (wl_fixed_t)lround(sx);
549 tdata->y = (wl_fixed_t)lround(sy);
550
551#if 0
552 struct widget *widget;
553 float sx = wl_fixed_to_double(x);
554 float sy = wl_fixed_to_double(y);
555
556
557 input->touch_focus = wl_surface_get_user_data(surface);
558 if (!input->touch_focus) {
559 DBG("Failed to find to touch focus for surface %p\n", (void*) surface);
560 return;
561 }
562
563 if (surface != input->touch_focus->main_surface->surface) {
564 DBG("Ignoring input event from subsurface %p\n", (void*) surface);
565 input->touch_focus = nullptr;
566 return;
567 }
568
569 if (input->grab)
570 widget = input->grab;
571 else
572 widget = window_find_widget(input->touch_focus,
573 wl_fixed_to_double(x),
574 wl_fixed_to_double(y));
575 if (widget) {
576 struct touch_point *tp = xmalloc(sizeof *tp);
577 if (tp) {
578 tp->id = id;
579 tp->widget = widget;
580 tp->x = sx;
581 tp->y = sy;
582 wl_list_insert(&input->touch_point_list, &tp->link);
583
584 if (widget->touch_down_handler)
585 (*widget->touch_down_handler)(widget, input,
586 serial, time, id,
587 sx, sy,
588 widget->user_data);
589 }
590 }
591#endif
592}
593
594static void touch_handle_up(void* data, struct wl_touch* wl_touch, uint32_t serial, uint32_t time,
595 int32_t id)
596{
597 UwacSeat* seat = data;
598 UwacTouchUp* tdata = nullptr;
599
600 assert(seat);
601
602 if (!seat->touch_frame_started && !touch_send_start_frame(seat))
603 return;
604
605 tdata = (UwacTouchUp*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_UP);
606 if (!tdata)
607 return;
608
609 tdata->seat = seat;
610 tdata->id = id;
611
612#if 0
613 struct touch_point *tp, *tmp;
614
615 if (!input->touch_focus) {
616 DBG("No touch focus found for touch up event!\n");
617 return;
618 }
619
620 wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) {
621 if (tp->id != id)
622 continue;
623
624 if (tp->widget->touch_up_handler)
625 (*tp->widget->touch_up_handler)(tp->widget, input, serial,
626 time, id,
627 tp->widget->user_data);
628
629 wl_list_remove(&tp->link);
630 free(tp);
631
632 return;
633 }
634#endif
635}
636
637static void touch_handle_motion(void* data, struct wl_touch* wl_touch, uint32_t time, int32_t id,
638 wl_fixed_t x_w, wl_fixed_t y_w)
639{
640 UwacSeat* seat = data;
641 assert(seat);
642
643 UwacTouchMotion* tdata = nullptr;
644
645 if (!seat->touch_frame_started && !touch_send_start_frame(seat))
646 return;
647
648 tdata = (UwacTouchMotion*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_MOTION);
649 if (!tdata)
650 return;
651
652 tdata->seat = seat;
653 tdata->id = id;
654
655 double sx = wl_fixed_to_double(x_w);
656 double sy = wl_fixed_to_double(y_w);
657
658 tdata->x = (wl_fixed_t)lround(sx);
659 tdata->y = (wl_fixed_t)lround(sy);
660
661#if 0
662 struct touch_point *tp;
663 float sx = wl_fixed_to_double(x);
664 float sy = wl_fixed_to_double(y);
665
666 DBG("touch_handle_motion: %i %i\n", id, wl_list_length(&seat->touch_point_list));
667
668 if (!seat->touch_focus) {
669 DBG("No touch focus found for touch motion event!\n");
670 return;
671 }
672
673 wl_list_for_each(tp, &seat->touch_point_list, link) {
674 if (tp->id != id)
675 continue;
676
677 tp->x = sx;
678 tp->y = sy;
679 if (tp->widget->touch_motion_handler)
680 (*tp->widget->touch_motion_handler)(tp->widget, seat, time,
681 id, sx, sy,
682 tp->widget->user_data);
683 return;
684 }
685#endif
686}
687
688static void touch_handle_frame(void* data, struct wl_touch* wl_touch)
689{
690 UwacSeat* seat = data;
691 assert(seat);
692
693 UwacTouchFrameEnd* ev =
694 (UwacTouchFrameEnd*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_END);
695 if (!ev)
696 return;
697
698 ev->seat = seat;
699 seat->touch_frame_started = false;
700}
701
702static void touch_handle_cancel(void* data, struct wl_touch* wl_touch)
703{
704 UwacSeat* seat = data;
705 assert(seat);
706
707 UwacTouchCancel* ev =
708 (UwacTouchCancel*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_CANCEL);
709 if (!ev)
710 return;
711
712 ev->seat = seat;
713 seat->touch_frame_started = false;
714
715#if 0
716 struct touch_point *tp, *tmp;
717
718 DBG("touch_handle_cancel\n");
719
720 if (!input->touch_focus) {
721 DBG("No touch focus found for touch cancel event!\n");
722 return;
723 }
724
725 wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) {
726 if (tp->widget->touch_cancel_handler)
727 (*tp->widget->touch_cancel_handler)(tp->widget, input,
728 tp->widget->user_data);
729
730 wl_list_remove(&tp->link);
731 free(tp);
732 }
733#endif
734}
735
736static void touch_handle_shape(void* data, struct wl_touch* wl_touch, int32_t id, wl_fixed_t major,
737 wl_fixed_t minor)
738{
739 UwacSeat* seat = data;
740 assert(seat);
741
742 // TODO
743}
744
745static void touch_handle_orientation(void* data, struct wl_touch* wl_touch, int32_t id,
746 wl_fixed_t orientation)
747{
748 UwacSeat* seat = data;
749 assert(seat);
750
751 // TODO
752}
753
754static const struct wl_touch_listener touch_listener = {
755 touch_handle_down, touch_handle_up, touch_handle_motion, touch_handle_frame,
756 touch_handle_cancel, touch_handle_shape, touch_handle_orientation
757};
758
759static void pointer_handle_enter(void* data, struct wl_pointer* pointer, uint32_t serial,
760 struct wl_surface* surface, wl_fixed_t sx_w, wl_fixed_t sy_w)
761{
762 UwacSeat* input = data;
763 UwacWindow* window = nullptr;
764 UwacPointerEnterLeaveEvent* event = nullptr;
765
766 assert(input);
767
768 double sx = wl_fixed_to_double(sx_w);
769 double sy = wl_fixed_to_double(sy_w);
770
771 if (!surface)
772 {
773 /* enter event for a window we've just destroyed */
774 return;
775 }
776
777 input->display->serial = serial;
778 input->display->pointer_focus_serial = serial;
779 window = wl_surface_get_user_data(surface);
780 if (window)
781 window->pointer_enter_serial = serial;
782 input->pointer_focus = window;
783 input->sx = sx;
784 input->sy = sy;
785
786 event =
787 (UwacPointerEnterLeaveEvent*)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_ENTER);
788 if (!event)
789 return;
790
791 event->seat = input;
792 event->window = window;
793 event->x = (uint32_t)lround(sx);
794 event->y = (uint32_t)lround(sy);
795
796 /* Apply cursor theme */
797 set_cursor_image(input, serial);
798}
799
800static void pointer_handle_leave(void* data, struct wl_pointer* pointer, uint32_t serial,
801 struct wl_surface* surface)
802{
803 UwacPointerEnterLeaveEvent* event = nullptr;
804 UwacWindow* window = nullptr;
805 UwacSeat* input = data;
806 assert(input);
807
808 input->display->serial = serial;
809
810 event =
811 (UwacPointerEnterLeaveEvent*)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_LEAVE);
812 if (!event)
813 return;
814
815 window = wl_surface_get_user_data(surface);
816
817 event->seat = input;
818 event->window = window;
819}
820
821static void pointer_handle_motion(void* data, struct wl_pointer* pointer, uint32_t time,
822 wl_fixed_t sx_w, wl_fixed_t sy_w)
823{
824 UwacPointerMotionEvent* motion_event = nullptr;
825 UwacSeat* input = data;
826 assert(input);
827
828 UwacWindow* window = input->pointer_focus;
829 if (!window || !window->display)
830 return;
831
832 int scale = window->display->actual_scale;
833 int sx_i = wl_fixed_to_int(sx_w) * scale;
834 int sy_i = wl_fixed_to_int(sy_w) * scale;
835 double sx_d = wl_fixed_to_double(sx_w) * scale;
836 double sy_d = wl_fixed_to_double(sy_w) * scale;
837
838 if ((sx_i < 0) || (sy_i < 0))
839 return;
840
841 input->sx = sx_d;
842 input->sy = sy_d;
843
844 motion_event =
845 (UwacPointerMotionEvent*)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_MOTION);
846 if (!motion_event)
847 return;
848
849 motion_event->seat = input;
850 motion_event->window = window;
851 motion_event->x = sx_i;
852 motion_event->y = sy_i;
853}
854
855static void pointer_handle_button(void* data, struct wl_pointer* pointer, uint32_t serial,
856 uint32_t time, uint32_t button, uint32_t state_w)
857{
858 UwacPointerButtonEvent* event = nullptr;
859 UwacSeat* seat = data;
860 assert(seat);
861
862 UwacWindow* window = seat->pointer_focus;
863
864 seat->display->serial = serial;
865
866 event = (UwacPointerButtonEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_BUTTONS);
867 if (!event)
868 return;
869
870 event->seat = seat;
871 event->window = window;
872 event->x = (uint32_t)lround(seat->sx);
873 event->y = (uint32_t)lround(seat->sy);
874 event->button = button;
875 event->state = (enum wl_pointer_button_state)state_w;
876}
877
878static void pointer_handle_axis(void* data, struct wl_pointer* pointer, uint32_t time,
879 uint32_t axis, wl_fixed_t value)
880{
881 UwacPointerAxisEvent* event = nullptr;
882 UwacSeat* seat = data;
883 assert(seat);
884
885 UwacWindow* window = seat->pointer_focus;
886
887 if (!window)
888 return;
889
890 event = (UwacPointerAxisEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS);
891 if (!event)
892 return;
893
894 event->seat = seat;
895 event->window = window;
896 event->x = (uint32_t)lround(seat->sx);
897 event->y = (uint32_t)lround(seat->sy);
898 event->axis = axis;
899 event->value = value;
900}
901
902static void pointer_frame(void* data, struct wl_pointer* wl_pointer)
903{
904 UwacPointerFrameEvent* event = nullptr;
905 UwacSeat* seat = data;
906 assert(seat);
907
908 UwacWindow* window = seat->pointer_focus;
909
910 if (!window)
911 return;
912
913 event = (UwacPointerFrameEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_FRAME);
914 if (!event)
915 return;
916
917 event->seat = seat;
918 event->window = window;
919}
920
921static void pointer_axis_source(void* data, struct wl_pointer* wl_pointer, uint32_t axis_source)
922{
923 UwacPointerSourceEvent* event = nullptr;
924 UwacSeat* seat = data;
925 assert(seat);
926
927 UwacWindow* window = seat->pointer_focus;
928
929 if (!window)
930 return;
931
932 event = (UwacPointerSourceEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_SOURCE);
933 if (!event)
934 return;
935
936 event->seat = seat;
937 event->window = window;
938 event->axis_source = axis_source;
939}
940
941static void pointer_axis_stop(void* data, struct wl_pointer* wl_pointer, uint32_t time,
942 uint32_t axis)
943{
944 UwacSeat* seat = data;
945 assert(seat);
946}
947
948static void pointer_axis_discrete(void* data, struct wl_pointer* wl_pointer, uint32_t axis,
949 int32_t discrete)
950{
951 /*UwacSeat *seat = data;*/
952 UwacPointerAxisEvent* event = nullptr;
953 UwacSeat* seat = data;
954 assert(seat);
955
956 UwacWindow* window = seat->pointer_focus;
957
958 if (!window)
959 return;
960
961 event =
962 (UwacPointerAxisEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS_DISCRETE);
963 if (!event)
964 return;
965
966 event->seat = seat;
967 event->window = window;
968 event->x = (uint32_t)lround(seat->sx);
969 event->y = (uint32_t)lround(seat->sy);
970 event->axis = axis;
971 event->value = discrete;
972}
973
974static void pointer_axis_value120(void* data, struct wl_pointer* wl_pointer, uint32_t axis,
975 int32_t value120)
976{
977 /*UwacSeat *seat = data;*/
978 UwacPointerAxisEvent* event = nullptr;
979 UwacSeat* seat = data;
980 assert(seat);
981
982 UwacWindow* window = seat->pointer_focus;
983
984 if (!window)
985 return;
986
987 event =
988 (UwacPointerAxisEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS_DISCRETE);
989 if (!event)
990 return;
991
992 event->seat = seat;
993 event->window = window;
994 event->x = (uint32_t)lround(seat->sx);
995 event->y = (uint32_t)lround(seat->sy);
996 event->axis = axis;
997 event->value = value120 / 120;
998}
999
1000static const struct wl_pointer_listener pointer_listener = {
1001 pointer_handle_enter, pointer_handle_leave, pointer_handle_motion, pointer_handle_button,
1002 pointer_handle_axis, pointer_frame, pointer_axis_source, pointer_axis_stop,
1003 pointer_axis_discrete, pointer_axis_value120
1004};
1005
1006static void seat_handle_capabilities(void* data, struct wl_seat* seat, uint32_t caps)
1007{
1008 UwacSeat* input = data;
1009 assert(input);
1010
1011 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer)
1012 {
1013 input->pointer = wl_seat_get_pointer(seat);
1014 wl_pointer_set_user_data(input->pointer, input);
1015 wl_pointer_add_listener(input->pointer, &pointer_listener, input);
1016
1017 input->cursor_theme = wl_cursor_theme_load(nullptr, 32, input->display->shm);
1018 if (!input->cursor_theme)
1019 {
1020 assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY,
1021 "unable to get wayland cursor theme\n"));
1022 return;
1023 }
1024
1025 input->default_cursor = wl_cursor_theme_get_cursor(input->cursor_theme, "left_ptr");
1026 if (!input->default_cursor)
1027 {
1028 assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY,
1029 "unable to get wayland cursor left_ptr\n"));
1030 return;
1031 }
1032 }
1033 else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer)
1034 {
1035#ifdef WL_POINTER_RELEASE_SINCE_VERSION
1036 if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION)
1037 wl_pointer_release(input->pointer);
1038 else
1039#endif
1040 wl_pointer_destroy(input->pointer);
1041 if (input->cursor_theme)
1042 wl_cursor_theme_destroy(input->cursor_theme);
1043
1044 input->default_cursor = nullptr;
1045 input->cursor_theme = nullptr;
1046 input->pointer = nullptr;
1047 }
1048
1049 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard)
1050 {
1051 input->keyboard = wl_seat_get_keyboard(seat);
1052 wl_keyboard_set_user_data(input->keyboard, input);
1053 wl_keyboard_add_listener(input->keyboard, &keyboard_listener, input);
1054 }
1055 else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard)
1056 {
1057#ifdef WL_KEYBOARD_RELEASE_SINCE_VERSION
1058 if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
1059 wl_keyboard_release(input->keyboard);
1060 else
1061#endif
1062 wl_keyboard_destroy(input->keyboard);
1063 input->keyboard = nullptr;
1064 }
1065
1066 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch)
1067 {
1068 input->touch = wl_seat_get_touch(seat);
1069 wl_touch_set_user_data(input->touch, input);
1070 wl_touch_add_listener(input->touch, &touch_listener, input);
1071 }
1072 else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch)
1073 {
1074#ifdef WL_TOUCH_RELEASE_SINCE_VERSION
1075 if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
1076 wl_touch_release(input->touch);
1077 else
1078#endif
1079 wl_touch_destroy(input->touch);
1080 input->touch = nullptr;
1081 }
1082}
1083
1084static void seat_handle_name(void* data, struct wl_seat* seat, const char* name)
1085{
1086 UwacSeat* input = data;
1087 assert(input);
1088
1089 if (input->name)
1090 free(input->name);
1091
1092 input->name = strdup(name);
1093 if (!input->name)
1094 assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY,
1095 "unable to strdup seat's name\n"));
1096}
1097
1098static const struct wl_seat_listener seat_listener = { seat_handle_capabilities, seat_handle_name };
1099
1100UwacSeat* UwacSeatNew(UwacDisplay* d, uint32_t id, uint32_t version)
1101{
1102 UwacSeat* ret = xzalloc(sizeof(UwacSeat));
1103 if (!ret)
1104 return nullptr;
1105
1106 ret->display = d;
1107 ret->seat_id = id;
1108 ret->seat_version = version;
1109
1110 wl_array_init(&ret->pressed_keys);
1111 ret->xkb_context = xkb_context_new(0);
1112 if (!ret->xkb_context)
1113 {
1114 (void)fprintf(stderr, "%s: unable to allocate a xkb_context\n", __func__);
1115 goto fail;
1116 }
1117
1118 ret->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, version);
1119 wl_seat_add_listener(ret->seat, &seat_listener, ret);
1120 wl_seat_set_user_data(ret->seat, ret);
1121
1122 ret->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
1123 if (ret->repeat_timer_fd < 0)
1124 {
1125 (void)fprintf(stderr, "%s: error creating repeat timer\n", __func__);
1126 goto fail;
1127 }
1128 ret->repeat_task.run = keyboard_repeat_func;
1129 if (UwacDisplayWatchFd(d, ret->repeat_timer_fd, EPOLLIN, &ret->repeat_task) < 0)
1130 {
1131 (void)fprintf(stderr, "%s: error polling repeat timer\n", __func__);
1132 goto fail;
1133 }
1134
1135 wl_list_insert(d->seats.prev, &ret->link);
1136 return ret;
1137
1138fail:
1139 UwacSeatDestroy(ret);
1140 return nullptr;
1141}
1142
1143void UwacSeatDestroy(UwacSeat* s)
1144{
1145 if (!s)
1146 return;
1147
1148 UwacSeatInhibitShortcuts(s, false);
1149 if (s->seat)
1150 {
1151#ifdef WL_SEAT_RELEASE_SINCE_VERSION
1152 if (s->seat_version >= WL_SEAT_RELEASE_SINCE_VERSION)
1153 wl_seat_release(s->seat);
1154 else
1155#endif
1156 wl_seat_destroy(s->seat);
1157 }
1158 s->seat = nullptr;
1159
1160 free(s->name);
1161 wl_array_release(&s->pressed_keys);
1162
1163 xkb_state_unref(s->xkb.state);
1164 xkb_context_unref(s->xkb_context);
1165
1166 if (s->pointer)
1167 {
1168#ifdef WL_POINTER_RELEASE_SINCE_VERSION
1169 if (s->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION)
1170 wl_pointer_release(s->pointer);
1171 else
1172#endif
1173 wl_pointer_destroy(s->pointer);
1174 }
1175
1176 if (s->touch)
1177 {
1178#ifdef WL_TOUCH_RELEASE_SINCE_VERSION
1179 if (s->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
1180 wl_touch_release(s->touch);
1181 else
1182#endif
1183 wl_touch_destroy(s->touch);
1184 }
1185
1186 if (s->keyboard)
1187 {
1188#ifdef WL_KEYBOARD_RELEASE_SINCE_VERSION
1189 if (s->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
1190 wl_keyboard_release(s->keyboard);
1191 else
1192#endif
1193 wl_keyboard_destroy(s->keyboard);
1194 }
1195
1196 if (s->data_device)
1197 wl_data_device_destroy(s->data_device);
1198
1199 if (s->data_source)
1200 wl_data_source_destroy(s->data_source);
1201
1202 if (s->pointer_surface)
1203 wl_surface_destroy(s->pointer_surface);
1204
1205 free(s->pointer_image);
1206 free(s->pointer_data);
1207
1208 wl_list_remove(&s->link);
1209 free(s);
1210}
1211
1212const char* UwacSeatGetName(const UwacSeat* seat)
1213{
1214 assert(seat);
1215 return seat->name;
1216}
1217
1218UwacSeatId UwacSeatGetId(const UwacSeat* seat)
1219{
1220 assert(seat);
1221 return seat->seat_id;
1222}
1223
1224UwacReturnCode UwacSeatInhibitShortcuts(UwacSeat* s, bool inhibit)
1225{
1226 if (!s)
1227 return UWAC_ERROR_CLOSED;
1228
1229 if (s->keyboard_inhibitor)
1230 {
1231 zwp_keyboard_shortcuts_inhibitor_v1_destroy(s->keyboard_inhibitor);
1232 s->keyboard_inhibitor = nullptr;
1233 }
1234 if (inhibit && s->display && s->display->keyboard_inhibit_manager)
1235 s->keyboard_inhibitor = zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(
1236 s->display->keyboard_inhibit_manager, s->keyboard_focus->surface, s->seat);
1237
1238 if (inhibit && !s->keyboard_inhibitor)
1239 return UWAC_ERROR_INTERNAL;
1240 return UWAC_SUCCESS;
1241}
1242
1243UwacReturnCode UwacSeatSetMouseCursor(UwacSeat* seat, const void* data, size_t length, size_t width,
1244 size_t height, size_t hot_x, size_t hot_y)
1245{
1246 if (!seat)
1247 return UWAC_ERROR_CLOSED;
1248
1249 free(seat->pointer_image);
1250 seat->pointer_image = nullptr;
1251
1252 free(seat->pointer_data);
1253 seat->pointer_data = nullptr;
1254 seat->pointer_size = 0;
1255
1256 /* There is a cursor provided */
1257 if ((data != nullptr) && (length != 0))
1258 {
1259 seat->pointer_image = xzalloc(sizeof(struct wl_cursor_image));
1260 if (!seat->pointer_image)
1261 return UWAC_ERROR_NOMEMORY;
1262 seat->pointer_image->width = width;
1263 seat->pointer_image->height = height;
1264 seat->pointer_image->hotspot_x = hot_x;
1265 seat->pointer_image->hotspot_y = hot_y;
1266
1267 free(seat->pointer_data);
1268 seat->pointer_data = xmalloc(length);
1269 memcpy(seat->pointer_data, data, length);
1270 seat->pointer_size = length;
1271
1272 seat->pointer_type = 2;
1273 }
1274 /* We want to use the system cursor */
1275 else if (length != 0)
1276 {
1277 seat->pointer_type = 0;
1278 }
1279 /* Hide the cursor */
1280 else
1281 {
1282 seat->pointer_type = 1;
1283 }
1284 if (seat && !seat->default_cursor)
1285 return UWAC_SUCCESS;
1286 return set_cursor_image(seat, seat->display->pointer_focus_serial);
1287}