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