FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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 = NULL;
47 struct wl_shm_pool* pool = NULL;
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(NULL, 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] = { 0 };
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 = NULL;
101 struct wl_cursor* cursor = NULL;
102 struct wl_cursor_image* image = NULL;
103 struct wl_surface* surface = NULL;
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: /* NULL 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 = NULL;
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 = NULL;
194 struct xkb_state* state = NULL;
195 char* map_str = NULL;
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(NULL, 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 = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Control");
245 input->xkb.alt_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Mod1");
246 input->xkb.shift_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Shift");
247 input->xkb.caps_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Lock");
248 input->xkb.num_mask = 1 << 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 = { 0 };
282 uint32_t* pressedKey = NULL;
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, NULL);
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 = NULL;
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 = NULL;
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 = NULL;
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, NULL);
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, NULL);
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 = NULL;
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 mask = xkb_state_serialize_mods(input->xkb.state, XKB_STATE_MODS_DEPRESSED |
450 XKB_STATE_MODS_LATCHED |
451 XKB_STATE_MODS_LOCKED);
452 input->modifiers = 0;
453 if (mask & input->xkb.control_mask)
454 input->modifiers |= UWAC_MOD_CONTROL_MASK;
455 if (mask & input->xkb.alt_mask)
456 input->modifiers |= UWAC_MOD_ALT_MASK;
457 if (mask & input->xkb.shift_mask)
458 input->modifiers |= UWAC_MOD_SHIFT_MASK;
459 if (mask & input->xkb.caps_mask)
460 input->modifiers |= UWAC_MOD_CAPS_MASK;
461 if (mask & input->xkb.num_mask)
462 input->modifiers |= UWAC_MOD_NUM_MASK;
463
464 event = (UwacKeyboardModifiersEvent*)UwacDisplayNewEvent(input->display,
465 UWAC_EVENT_KEYBOARD_MODIFIERS);
466 if (!event)
467 return;
468
469 event->modifiers = input->modifiers;
470}
471
472static void set_repeat_info(UwacSeat* input, int32_t rate, int32_t delay)
473{
474 assert(input);
475
476 input->repeat_rate_sec = input->repeat_rate_nsec = 0;
477 input->repeat_delay_sec = input->repeat_delay_nsec = 0;
478
479 /* a rate of zero disables any repeating, regardless of the delay's
480 * value */
481 if (rate == 0)
482 return;
483
484 if (rate == 1)
485 input->repeat_rate_sec = 1;
486 else
487 input->repeat_rate_nsec = 1000000000 / rate;
488
489 input->repeat_delay_sec = delay / 1000;
490 delay -= (input->repeat_delay_sec * 1000);
491 input->repeat_delay_nsec = delay * 1000 * 1000;
492}
493
494static void keyboard_handle_repeat_info(void* data, struct wl_keyboard* keyboard, int32_t rate,
495 int32_t delay)
496{
497 UwacSeat* input = data;
498 assert(input);
499
500 set_repeat_info(input, rate, delay);
501}
502
503static const struct wl_keyboard_listener keyboard_listener = {
504 keyboard_handle_keymap, keyboard_handle_enter, keyboard_handle_leave,
505 keyboard_handle_key, keyboard_handle_modifiers, keyboard_handle_repeat_info
506};
507
508static bool touch_send_start_frame(UwacSeat* seat)
509{
510 assert(seat);
511
512 UwacTouchFrameBegin* ev =
513 (UwacTouchFrameBegin*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_BEGIN);
514 if (!ev)
515 return false;
516
517 seat->touch_frame_started = true;
518 return true;
519}
520
521static void touch_handle_down(void* data, struct wl_touch* wl_touch, uint32_t serial, uint32_t time,
522 struct wl_surface* surface, int32_t id, wl_fixed_t x_w,
523 wl_fixed_t y_w)
524{
525 UwacSeat* seat = data;
526 UwacTouchDown* tdata = NULL;
527
528 assert(seat);
529 assert(seat->display);
530
531 seat->display->serial = serial;
532 if (!seat->touch_frame_started && !touch_send_start_frame(seat))
533 return;
534
535 tdata = (UwacTouchDown*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_DOWN);
536 if (!tdata)
537 return;
538
539 tdata->seat = seat;
540 tdata->id = id;
541
542 double sx = wl_fixed_to_double(x_w);
543 double sy = wl_fixed_to_double(y_w);
544
545 tdata->x = (wl_fixed_t)lround(sx);
546 tdata->y = (wl_fixed_t)lround(sy);
547
548#if 0
549 struct widget *widget;
550 float sx = wl_fixed_to_double(x);
551 float sy = wl_fixed_to_double(y);
552
553
554 input->touch_focus = wl_surface_get_user_data(surface);
555 if (!input->touch_focus) {
556 DBG("Failed to find to touch focus for surface %p\n", (void*) surface);
557 return;
558 }
559
560 if (surface != input->touch_focus->main_surface->surface) {
561 DBG("Ignoring input event from subsurface %p\n", (void*) surface);
562 input->touch_focus = NULL;
563 return;
564 }
565
566 if (input->grab)
567 widget = input->grab;
568 else
569 widget = window_find_widget(input->touch_focus,
570 wl_fixed_to_double(x),
571 wl_fixed_to_double(y));
572 if (widget) {
573 struct touch_point *tp = xmalloc(sizeof *tp);
574 if (tp) {
575 tp->id = id;
576 tp->widget = widget;
577 tp->x = sx;
578 tp->y = sy;
579 wl_list_insert(&input->touch_point_list, &tp->link);
580
581 if (widget->touch_down_handler)
582 (*widget->touch_down_handler)(widget, input,
583 serial, time, id,
584 sx, sy,
585 widget->user_data);
586 }
587 }
588#endif
589}
590
591static void touch_handle_up(void* data, struct wl_touch* wl_touch, uint32_t serial, uint32_t time,
592 int32_t id)
593{
594 UwacSeat* seat = data;
595 UwacTouchUp* tdata = NULL;
596
597 assert(seat);
598
599 if (!seat->touch_frame_started && !touch_send_start_frame(seat))
600 return;
601
602 tdata = (UwacTouchUp*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_UP);
603 if (!tdata)
604 return;
605
606 tdata->seat = seat;
607 tdata->id = id;
608
609#if 0
610 struct touch_point *tp, *tmp;
611
612 if (!input->touch_focus) {
613 DBG("No touch focus found for touch up event!\n");
614 return;
615 }
616
617 wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) {
618 if (tp->id != id)
619 continue;
620
621 if (tp->widget->touch_up_handler)
622 (*tp->widget->touch_up_handler)(tp->widget, input, serial,
623 time, id,
624 tp->widget->user_data);
625
626 wl_list_remove(&tp->link);
627 free(tp);
628
629 return;
630 }
631#endif
632}
633
634static void touch_handle_motion(void* data, struct wl_touch* wl_touch, uint32_t time, int32_t id,
635 wl_fixed_t x_w, wl_fixed_t y_w)
636{
637 UwacSeat* seat = data;
638 assert(seat);
639
640 UwacTouchMotion* tdata = NULL;
641
642 if (!seat->touch_frame_started && !touch_send_start_frame(seat))
643 return;
644
645 tdata = (UwacTouchMotion*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_MOTION);
646 if (!tdata)
647 return;
648
649 tdata->seat = seat;
650 tdata->id = id;
651
652 double sx = wl_fixed_to_double(x_w);
653 double sy = wl_fixed_to_double(y_w);
654
655 tdata->x = (wl_fixed_t)lround(sx);
656 tdata->y = (wl_fixed_t)lround(sy);
657
658#if 0
659 struct touch_point *tp;
660 float sx = wl_fixed_to_double(x);
661 float sy = wl_fixed_to_double(y);
662
663 DBG("touch_handle_motion: %i %i\n", id, wl_list_length(&seat->touch_point_list));
664
665 if (!seat->touch_focus) {
666 DBG("No touch focus found for touch motion event!\n");
667 return;
668 }
669
670 wl_list_for_each(tp, &seat->touch_point_list, link) {
671 if (tp->id != id)
672 continue;
673
674 tp->x = sx;
675 tp->y = sy;
676 if (tp->widget->touch_motion_handler)
677 (*tp->widget->touch_motion_handler)(tp->widget, seat, time,
678 id, sx, sy,
679 tp->widget->user_data);
680 return;
681 }
682#endif
683}
684
685static void touch_handle_frame(void* data, struct wl_touch* wl_touch)
686{
687 UwacSeat* seat = data;
688 assert(seat);
689
690 UwacTouchFrameEnd* ev =
691 (UwacTouchFrameEnd*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_END);
692 if (!ev)
693 return;
694
695 ev->seat = seat;
696 seat->touch_frame_started = false;
697}
698
699static void touch_handle_cancel(void* data, struct wl_touch* wl_touch)
700{
701 UwacSeat* seat = data;
702 assert(seat);
703
704 UwacTouchCancel* ev =
705 (UwacTouchCancel*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_CANCEL);
706 if (!ev)
707 return;
708
709 ev->seat = seat;
710 seat->touch_frame_started = false;
711
712#if 0
713 struct touch_point *tp, *tmp;
714
715 DBG("touch_handle_cancel\n");
716
717 if (!input->touch_focus) {
718 DBG("No touch focus found for touch cancel event!\n");
719 return;
720 }
721
722 wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) {
723 if (tp->widget->touch_cancel_handler)
724 (*tp->widget->touch_cancel_handler)(tp->widget, input,
725 tp->widget->user_data);
726
727 wl_list_remove(&tp->link);
728 free(tp);
729 }
730#endif
731}
732
733static void touch_handle_shape(void* data, struct wl_touch* wl_touch, int32_t id, wl_fixed_t major,
734 wl_fixed_t minor)
735{
736 UwacSeat* seat = data;
737 assert(seat);
738
739 // TODO
740}
741
742static void touch_handle_orientation(void* data, struct wl_touch* wl_touch, int32_t id,
743 wl_fixed_t orientation)
744{
745 UwacSeat* seat = data;
746 assert(seat);
747
748 // TODO
749}
750
751static const struct wl_touch_listener touch_listener = {
752 touch_handle_down, touch_handle_up, touch_handle_motion, touch_handle_frame,
753 touch_handle_cancel, touch_handle_shape, touch_handle_orientation
754};
755
756static void pointer_handle_enter(void* data, struct wl_pointer* pointer, uint32_t serial,
757 struct wl_surface* surface, wl_fixed_t sx_w, wl_fixed_t sy_w)
758{
759 UwacSeat* input = data;
760 UwacWindow* window = NULL;
761 UwacPointerEnterLeaveEvent* event = NULL;
762
763 assert(input);
764
765 double sx = wl_fixed_to_double(sx_w);
766 double sy = wl_fixed_to_double(sy_w);
767
768 if (!surface)
769 {
770 /* enter event for a window we've just destroyed */
771 return;
772 }
773
774 input->display->serial = serial;
775 input->display->pointer_focus_serial = serial;
776 window = wl_surface_get_user_data(surface);
777 if (window)
778 window->pointer_enter_serial = serial;
779 input->pointer_focus = window;
780 input->sx = sx;
781 input->sy = sy;
782
783 event =
784 (UwacPointerEnterLeaveEvent*)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_ENTER);
785 if (!event)
786 return;
787
788 event->seat = input;
789 event->window = window;
790 event->x = (uint32_t)lround(sx);
791 event->y = (uint32_t)lround(sy);
792
793 /* Apply cursor theme */
794 set_cursor_image(input, serial);
795}
796
797static void pointer_handle_leave(void* data, struct wl_pointer* pointer, uint32_t serial,
798 struct wl_surface* surface)
799{
800 UwacPointerEnterLeaveEvent* event = NULL;
801 UwacWindow* window = NULL;
802 UwacSeat* input = data;
803 assert(input);
804
805 input->display->serial = serial;
806
807 event =
808 (UwacPointerEnterLeaveEvent*)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_LEAVE);
809 if (!event)
810 return;
811
812 window = wl_surface_get_user_data(surface);
813
814 event->seat = input;
815 event->window = window;
816}
817
818static void pointer_handle_motion(void* data, struct wl_pointer* pointer, uint32_t time,
819 wl_fixed_t sx_w, wl_fixed_t sy_w)
820{
821 UwacPointerMotionEvent* motion_event = NULL;
822 UwacSeat* input = data;
823 assert(input);
824
825 UwacWindow* window = input->pointer_focus;
826 if (!window || !window->display)
827 return;
828
829 int scale = window->display->actual_scale;
830 int sx_i = wl_fixed_to_int(sx_w) * scale;
831 int sy_i = wl_fixed_to_int(sy_w) * scale;
832 double sx_d = wl_fixed_to_double(sx_w) * scale;
833 double sy_d = wl_fixed_to_double(sy_w) * scale;
834
835 if ((sx_i < 0) || (sy_i < 0))
836 return;
837
838 input->sx = sx_d;
839 input->sy = sy_d;
840
841 motion_event =
842 (UwacPointerMotionEvent*)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_MOTION);
843 if (!motion_event)
844 return;
845
846 motion_event->seat = input;
847 motion_event->window = window;
848 motion_event->x = sx_i;
849 motion_event->y = sy_i;
850}
851
852static void pointer_handle_button(void* data, struct wl_pointer* pointer, uint32_t serial,
853 uint32_t time, uint32_t button, uint32_t state_w)
854{
855 UwacPointerButtonEvent* event = NULL;
856 UwacSeat* seat = data;
857 assert(seat);
858
859 UwacWindow* window = seat->pointer_focus;
860
861 seat->display->serial = serial;
862
863 event = (UwacPointerButtonEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_BUTTONS);
864 if (!event)
865 return;
866
867 event->seat = seat;
868 event->window = window;
869 event->x = (uint32_t)lround(seat->sx);
870 event->y = (uint32_t)lround(seat->sy);
871 event->button = button;
872 event->state = (enum wl_pointer_button_state)state_w;
873}
874
875static void pointer_handle_axis(void* data, struct wl_pointer* pointer, uint32_t time,
876 uint32_t axis, wl_fixed_t value)
877{
878 UwacPointerAxisEvent* event = NULL;
879 UwacSeat* seat = data;
880 assert(seat);
881
882 UwacWindow* window = seat->pointer_focus;
883
884 if (!window)
885 return;
886
887 event = (UwacPointerAxisEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS);
888 if (!event)
889 return;
890
891 event->seat = seat;
892 event->window = window;
893 event->x = (uint32_t)lround(seat->sx);
894 event->y = (uint32_t)lround(seat->sy);
895 event->axis = axis;
896 event->value = value;
897}
898
899static void pointer_frame(void* data, struct wl_pointer* wl_pointer)
900{
901 UwacPointerFrameEvent* event = NULL;
902 UwacSeat* seat = data;
903 assert(seat);
904
905 UwacWindow* window = seat->pointer_focus;
906
907 if (!window)
908 return;
909
910 event = (UwacPointerFrameEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_FRAME);
911 if (!event)
912 return;
913
914 event->seat = seat;
915 event->window = window;
916}
917
918static void pointer_axis_source(void* data, struct wl_pointer* wl_pointer, uint32_t axis_source)
919{
920 UwacPointerSourceEvent* event = NULL;
921 UwacSeat* seat = data;
922 assert(seat);
923
924 UwacWindow* window = seat->pointer_focus;
925
926 if (!window)
927 return;
928
929 event = (UwacPointerSourceEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_SOURCE);
930 if (!event)
931 return;
932
933 event->seat = seat;
934 event->window = window;
935 event->axis_source = axis_source;
936}
937
938static void pointer_axis_stop(void* data, struct wl_pointer* wl_pointer, uint32_t time,
939 uint32_t axis)
940{
941 UwacSeat* seat = data;
942 assert(seat);
943}
944
945static void pointer_axis_discrete(void* data, struct wl_pointer* wl_pointer, uint32_t axis,
946 int32_t discrete)
947{
948 /*UwacSeat *seat = data;*/
949 UwacPointerAxisEvent* event = NULL;
950 UwacSeat* seat = data;
951 assert(seat);
952
953 UwacWindow* window = seat->pointer_focus;
954
955 if (!window)
956 return;
957
958 event =
959 (UwacPointerAxisEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS_DISCRETE);
960 if (!event)
961 return;
962
963 event->seat = seat;
964 event->window = window;
965 event->x = (uint32_t)lround(seat->sx);
966 event->y = (uint32_t)lround(seat->sy);
967 event->axis = axis;
968 event->value = discrete;
969}
970
971static void pointer_axis_value120(void* data, struct wl_pointer* wl_pointer, uint32_t axis,
972 int32_t value120)
973{
974 /*UwacSeat *seat = data;*/
975 UwacPointerAxisEvent* event = NULL;
976 UwacSeat* seat = data;
977 assert(seat);
978
979 UwacWindow* window = seat->pointer_focus;
980
981 if (!window)
982 return;
983
984 event =
985 (UwacPointerAxisEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS_DISCRETE);
986 if (!event)
987 return;
988
989 event->seat = seat;
990 event->window = window;
991 event->x = (uint32_t)lround(seat->sx);
992 event->y = (uint32_t)lround(seat->sy);
993 event->axis = axis;
994 event->value = value120 / 120;
995}
996
997static const struct wl_pointer_listener pointer_listener = {
998 pointer_handle_enter, pointer_handle_leave, pointer_handle_motion, pointer_handle_button,
999 pointer_handle_axis, pointer_frame, pointer_axis_source, pointer_axis_stop,
1000 pointer_axis_discrete, pointer_axis_value120
1001};
1002
1003static void seat_handle_capabilities(void* data, struct wl_seat* seat, uint32_t caps)
1004{
1005 UwacSeat* input = data;
1006 assert(input);
1007
1008 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer)
1009 {
1010 input->pointer = wl_seat_get_pointer(seat);
1011 wl_pointer_set_user_data(input->pointer, input);
1012 wl_pointer_add_listener(input->pointer, &pointer_listener, input);
1013
1014 input->cursor_theme = wl_cursor_theme_load(NULL, 32, input->display->shm);
1015 if (!input->cursor_theme)
1016 {
1017 assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY,
1018 "unable to get wayland cursor theme\n"));
1019 return;
1020 }
1021
1022 input->default_cursor = wl_cursor_theme_get_cursor(input->cursor_theme, "left_ptr");
1023 if (!input->default_cursor)
1024 {
1025 assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY,
1026 "unable to get wayland cursor left_ptr\n"));
1027 return;
1028 }
1029 }
1030 else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer)
1031 {
1032#ifdef WL_POINTER_RELEASE_SINCE_VERSION
1033 if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION)
1034 wl_pointer_release(input->pointer);
1035 else
1036#endif
1037 wl_pointer_destroy(input->pointer);
1038 if (input->cursor_theme)
1039 wl_cursor_theme_destroy(input->cursor_theme);
1040
1041 input->default_cursor = NULL;
1042 input->cursor_theme = NULL;
1043 input->pointer = NULL;
1044 }
1045
1046 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard)
1047 {
1048 input->keyboard = wl_seat_get_keyboard(seat);
1049 wl_keyboard_set_user_data(input->keyboard, input);
1050 wl_keyboard_add_listener(input->keyboard, &keyboard_listener, input);
1051 }
1052 else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard)
1053 {
1054#ifdef WL_KEYBOARD_RELEASE_SINCE_VERSION
1055 if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
1056 wl_keyboard_release(input->keyboard);
1057 else
1058#endif
1059 wl_keyboard_destroy(input->keyboard);
1060 input->keyboard = NULL;
1061 }
1062
1063 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch)
1064 {
1065 input->touch = wl_seat_get_touch(seat);
1066 wl_touch_set_user_data(input->touch, input);
1067 wl_touch_add_listener(input->touch, &touch_listener, input);
1068 }
1069 else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch)
1070 {
1071#ifdef WL_TOUCH_RELEASE_SINCE_VERSION
1072 if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
1073 wl_touch_release(input->touch);
1074 else
1075#endif
1076 wl_touch_destroy(input->touch);
1077 input->touch = NULL;
1078 }
1079}
1080
1081static void seat_handle_name(void* data, struct wl_seat* seat, const char* name)
1082{
1083 UwacSeat* input = data;
1084 assert(input);
1085
1086 if (input->name)
1087 free(input->name);
1088
1089 input->name = strdup(name);
1090 if (!input->name)
1091 assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY,
1092 "unable to strdup seat's name\n"));
1093}
1094
1095static const struct wl_seat_listener seat_listener = { seat_handle_capabilities, seat_handle_name };
1096
1097UwacSeat* UwacSeatNew(UwacDisplay* d, uint32_t id, uint32_t version)
1098{
1099 UwacSeat* ret = xzalloc(sizeof(UwacSeat));
1100 if (!ret)
1101 return NULL;
1102
1103 ret->display = d;
1104 ret->seat_id = id;
1105 ret->seat_version = version;
1106
1107 wl_array_init(&ret->pressed_keys);
1108 ret->xkb_context = xkb_context_new(0);
1109 if (!ret->xkb_context)
1110 {
1111 (void)fprintf(stderr, "%s: unable to allocate a xkb_context\n", __func__);
1112 goto fail;
1113 }
1114
1115 ret->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, version);
1116 wl_seat_add_listener(ret->seat, &seat_listener, ret);
1117 wl_seat_set_user_data(ret->seat, ret);
1118
1119 ret->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
1120 if (ret->repeat_timer_fd < 0)
1121 {
1122 (void)fprintf(stderr, "%s: error creating repeat timer\n", __func__);
1123 goto fail;
1124 }
1125 ret->repeat_task.run = keyboard_repeat_func;
1126 if (UwacDisplayWatchFd(d, ret->repeat_timer_fd, EPOLLIN, &ret->repeat_task) < 0)
1127 {
1128 (void)fprintf(stderr, "%s: error polling repeat timer\n", __func__);
1129 goto fail;
1130 }
1131
1132 wl_list_insert(d->seats.prev, &ret->link);
1133 return ret;
1134
1135fail:
1136 UwacSeatDestroy(ret);
1137 return NULL;
1138}
1139
1140void UwacSeatDestroy(UwacSeat* s)
1141{
1142 if (!s)
1143 return;
1144
1145 UwacSeatInhibitShortcuts(s, false);
1146 if (s->seat)
1147 {
1148#ifdef WL_SEAT_RELEASE_SINCE_VERSION
1149 if (s->seat_version >= WL_SEAT_RELEASE_SINCE_VERSION)
1150 wl_seat_release(s->seat);
1151 else
1152#endif
1153 wl_seat_destroy(s->seat);
1154 }
1155 s->seat = NULL;
1156
1157 free(s->name);
1158 wl_array_release(&s->pressed_keys);
1159
1160 xkb_state_unref(s->xkb.state);
1161 xkb_context_unref(s->xkb_context);
1162
1163 if (s->pointer)
1164 {
1165#ifdef WL_POINTER_RELEASE_SINCE_VERSION
1166 if (s->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION)
1167 wl_pointer_release(s->pointer);
1168 else
1169#endif
1170 wl_pointer_destroy(s->pointer);
1171 }
1172
1173 if (s->touch)
1174 {
1175#ifdef WL_TOUCH_RELEASE_SINCE_VERSION
1176 if (s->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
1177 wl_touch_release(s->touch);
1178 else
1179#endif
1180 wl_touch_destroy(s->touch);
1181 }
1182
1183 if (s->keyboard)
1184 {
1185#ifdef WL_KEYBOARD_RELEASE_SINCE_VERSION
1186 if (s->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
1187 wl_keyboard_release(s->keyboard);
1188 else
1189#endif
1190 wl_keyboard_destroy(s->keyboard);
1191 }
1192
1193 if (s->data_device)
1194 wl_data_device_destroy(s->data_device);
1195
1196 if (s->data_source)
1197 wl_data_source_destroy(s->data_source);
1198
1199 if (s->pointer_surface)
1200 wl_surface_destroy(s->pointer_surface);
1201
1202 free(s->pointer_image);
1203 free(s->pointer_data);
1204
1205 wl_list_remove(&s->link);
1206 free(s);
1207}
1208
1209const char* UwacSeatGetName(const UwacSeat* seat)
1210{
1211 assert(seat);
1212 return seat->name;
1213}
1214
1215UwacSeatId UwacSeatGetId(const UwacSeat* seat)
1216{
1217 assert(seat);
1218 return seat->seat_id;
1219}
1220
1221UwacReturnCode UwacSeatInhibitShortcuts(UwacSeat* s, bool inhibit)
1222{
1223 if (!s)
1224 return UWAC_ERROR_CLOSED;
1225
1226 if (s->keyboard_inhibitor)
1227 {
1228 zwp_keyboard_shortcuts_inhibitor_v1_destroy(s->keyboard_inhibitor);
1229 s->keyboard_inhibitor = NULL;
1230 }
1231 if (inhibit && s->display && s->display->keyboard_inhibit_manager)
1232 s->keyboard_inhibitor = zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(
1233 s->display->keyboard_inhibit_manager, s->keyboard_focus->surface, s->seat);
1234
1235 if (inhibit && !s->keyboard_inhibitor)
1236 return UWAC_ERROR_INTERNAL;
1237 return UWAC_SUCCESS;
1238}
1239
1240UwacReturnCode UwacSeatSetMouseCursor(UwacSeat* seat, const void* data, size_t length, size_t width,
1241 size_t height, size_t hot_x, size_t hot_y)
1242{
1243 if (!seat)
1244 return UWAC_ERROR_CLOSED;
1245
1246 free(seat->pointer_image);
1247 seat->pointer_image = NULL;
1248
1249 free(seat->pointer_data);
1250 seat->pointer_data = NULL;
1251 seat->pointer_size = 0;
1252
1253 /* There is a cursor provided */
1254 if ((data != NULL) && (length != 0))
1255 {
1256 seat->pointer_image = xzalloc(sizeof(struct wl_cursor_image));
1257 if (!seat->pointer_image)
1258 return UWAC_ERROR_NOMEMORY;
1259 seat->pointer_image->width = width;
1260 seat->pointer_image->height = height;
1261 seat->pointer_image->hotspot_x = hot_x;
1262 seat->pointer_image->hotspot_y = hot_y;
1263
1264 free(seat->pointer_data);
1265 seat->pointer_data = xmalloc(length);
1266 memcpy(seat->pointer_data, data, length);
1267 seat->pointer_size = length;
1268
1269 seat->pointer_type = 2;
1270 }
1271 /* We want to use the system cursor */
1272 else if (length != 0)
1273 {
1274 seat->pointer_type = 0;
1275 }
1276 /* Hide the cursor */
1277 else
1278 {
1279 seat->pointer_type = 1;
1280 }
1281 if (seat && !seat->default_cursor)
1282 return UWAC_SUCCESS;
1283 return set_cursor_image(seat, seat->display->pointer_focus_serial);
1284}