6948efc7076be53eaf4cbf2121d067cb5ec3d7e4
[platform/core/uifw/libds-tizen.git] / src / libds / backend / wayland / seat.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <alloca.h>
6 #include <sys/mman.h>
7 #include <wayland-client.h>
8 #include <xkbcommon/xkbcommon.h>
9
10 #include "libds/log.h"
11 #include "libds/pointer.h"
12 #include "libds/touch.h"
13
14 #include "util.h"
15 #include "backend.h"
16
17 #ifdef MIN
18 # undef MIN
19 #endif
20
21 #define MIN(a, b)   ((a) < (b) ? (a) : (b))
22
23 static const struct wl_seat_listener seat_listener;
24 static const struct wl_callback_listener seat_callback_listener;
25
26 static void seat_update_capabilities(struct ds_wl_seat *seat,
27         enum wl_seat_capability caps);
28 static struct ds_input_device *
29 create_wl_input_device(struct ds_wl_seat *seat,
30         enum ds_input_device_type type);
31 static struct ds_pointer *create_wl_pointer(struct ds_wl_seat *seat);
32 static struct ds_keyboard *create_wl_keyboard(struct ds_wl_seat *seat);
33 static struct ds_touch *create_wl_touch(struct ds_wl_seat *seat);
34
35 struct ds_wl_seat *
36 create_wl_seat(struct ds_wl_backend *backend, uint32_t id,
37         uint32_t available_version)
38 {
39     struct ds_wl_seat *seat;
40
41     seat = calloc(1, sizeof *seat);
42     if (!seat)
43         return NULL;
44
45     seat->backend = backend;
46     seat->version = MIN(available_version, 5);
47     seat->wl_seat = wl_registry_bind(backend->server.registry, id,
48             &wl_seat_interface, seat->version);
49
50     wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
51
52     seat->initial_info_cb = wl_display_sync(backend->server.display);
53     wl_callback_add_listener(seat->initial_info_cb, &seat_callback_listener,
54             seat);
55
56     ds_dbg("wl_backend: Seat(%p) created", seat);
57
58     return seat;
59 }
60
61 void
62 destroy_wl_seat(struct ds_wl_seat *seat)
63 {
64     ds_dbg("wl_backend: Seat(%p) destroy", seat);
65
66     if (seat->pointer_dev)
67         ds_input_device_destroy(seat->pointer_dev);
68
69     if (seat->keyboard_dev)
70         ds_input_device_destroy(seat->keyboard_dev);
71
72     if (seat->touch_dev)
73         ds_input_device_destroy(seat->touch_dev);
74
75     if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION)
76         wl_seat_release(seat->wl_seat);
77     else
78         wl_seat_destroy(seat->wl_seat);
79
80     wl_list_remove(&seat->link);
81
82     free(seat->name);
83     free(seat);
84 }
85
86 static void
87 seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
88         enum wl_seat_capability caps)
89 {
90     struct ds_wl_seat *seat = data;
91
92     if (seat->initialized)
93         seat_update_capabilities(seat, caps);
94     else
95         seat->caps = caps;
96
97     ds_dbg("wl_backend: Seat(%p) capabilities(%d)", seat, caps);
98 }
99
100 static void
101 seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name)
102 {
103     struct ds_wl_seat *seat = data;
104
105     if (seat->name)
106         free(seat->name);
107
108     ds_dbg("wl_backend: Seat(%p) name(%s)", seat, name);
109
110     seat->name = strdup(name);
111 }
112
113 static const struct wl_seat_listener seat_listener = {
114     .capabilities = seat_handle_capabilities,
115     .name = seat_handle_name,
116 };
117
118 static void
119 seat_add_callback_handle_done(void *data, struct wl_callback *callback,
120         uint32_t callback_data)
121 {
122     struct ds_wl_seat *seat = data;
123
124     wl_callback_destroy(seat->initial_info_cb);
125     seat->initial_info_cb = NULL;
126     seat->initialized = true;
127
128     seat_update_capabilities(seat, seat->caps);
129 }
130
131 static const struct wl_callback_listener seat_callback_listener = {
132     .done = seat_add_callback_handle_done,
133 };
134
135 static void
136 seat_update_capabilities(struct ds_wl_seat *seat, enum wl_seat_capability caps)
137 {
138     if ((caps & WL_SEAT_CAPABILITY_POINTER) && seat->pointer_dev == NULL) {
139         ds_dbg("wl_backend: Seat(%p) offered pointer", seat);
140
141         seat->pointer_dev = create_wl_input_device(seat,
142                 DS_INPUT_DEVICE_POINTER);
143         seat->pointer_dev->pointer = create_wl_pointer(seat);
144
145         wl_signal_emit(&seat->backend->base.events.new_input,
146                 seat->pointer_dev);
147     }
148     else if (!(caps & WL_SEAT_CAPABILITY_POINTER) &&
149             seat->pointer_dev != NULL) {
150         ds_dbg("wl_backend: Seat(%p) dropped pointer", seat);
151         ds_input_device_destroy(seat->pointer_dev);
152         seat->pointer_dev = NULL;
153     }
154
155     if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->keyboard_dev == NULL) {
156         ds_dbg("wl_backend: Seat(%p) offered keyboard", seat);
157
158         seat->keyboard_dev = create_wl_input_device(seat,
159                 DS_INPUT_DEVICE_KEYBOARD);
160         seat->keyboard_dev->keyboard = create_wl_keyboard(seat);
161
162         wl_signal_emit(&seat->backend->base.events.new_input,
163                 seat->keyboard_dev);
164     }
165     else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) &&
166             seat->keyboard_dev != NULL) {
167         ds_dbg("wl_backend: Seat(%p) dropped keyboard", seat);
168         ds_input_device_destroy(seat->keyboard_dev);
169         seat->keyboard_dev = NULL;
170     }
171
172     if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch_dev == NULL) {
173         ds_dbg("wl_backend: Seat(%p) offered touch", seat);
174         seat->touch_dev = create_wl_input_device(seat,
175                 DS_INPUT_DEVICE_TOUCH);
176         seat->touch_dev->touch = create_wl_touch(seat);
177         wl_signal_emit(&seat->backend->base.events.new_input,
178                 seat->touch_dev);
179     }
180     else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) &&
181             seat->touch_dev != NULL) {
182         ds_dbg("wl_backend: Seat(%p) dropped touch", seat);
183         ds_input_device_destroy(seat->touch_dev);
184         seat->touch_dev = NULL;
185     }
186 }
187
188 static const struct ds_input_device_interface input_device_iface;
189
190 static bool
191 ds_input_device_is_wl(struct ds_input_device *ds_dev)
192 {
193     return ds_dev->iface == &input_device_iface;
194 }
195
196 static struct ds_wl_input_device *
197 get_wl_input_device_from_input_device(struct ds_input_device *ds_dev)
198 {
199     assert(ds_input_device_is_wl(ds_dev));
200     return (struct ds_wl_input_device *)ds_dev;
201 }
202
203 static void
204 input_device_iface_destroy(struct ds_input_device *ds_dev)
205 {
206     struct ds_wl_input_device *dev;
207
208     dev = get_wl_input_device_from_input_device(ds_dev);
209
210     free(dev);
211 }
212
213 static const struct ds_input_device_interface input_device_iface =
214 {
215     .destroy = input_device_iface_destroy,
216 };
217
218 static struct ds_input_device *
219 create_wl_input_device(struct ds_wl_seat *seat,
220         enum ds_input_device_type type)
221 {
222     struct ds_wl_input_device *dev;
223     unsigned int vendor = 0, product = 0;
224     size_t name_size;
225     char *name;
226
227     dev = calloc(1, sizeof *dev);
228     if (!dev)
229         return NULL;
230
231     dev->backend = seat->backend;
232     dev->seat = seat;
233
234     name_size = 8 + strlen(seat->name) + 1;
235     name = alloca(name_size);
236     (void) snprintf(name, name_size, "wayland-%s", seat->name);
237
238     ds_input_device_init(&dev->base, type, &input_device_iface, name, vendor,
239             product);
240
241     return &dev->base;
242 }
243
244 static const struct ds_pointer_interface pointer_iface;
245
246 static struct ds_wl_pointer *
247 get_wl_pointer_from_pointer(struct ds_pointer *ds_pointer)
248 {
249     assert(ds_pointer->iface == &pointer_iface);
250     return (struct ds_wl_pointer *)ds_pointer;
251 }
252
253 static void
254 pointer_iface_destroy(struct ds_pointer *ds_pointer)
255 {
256     struct ds_wl_pointer *pointer;
257
258     pointer = get_wl_pointer_from_pointer(ds_pointer);
259
260     wl_pointer_release(pointer->wl_pointer);
261
262     free(pointer);
263 }
264
265 static const struct ds_pointer_interface pointer_iface = {
266     .destroy = pointer_iface_destroy,
267 };
268
269 static void
270 pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
271         uint32_t serial, struct wl_surface *surface,
272         wl_fixed_t sx, wl_fixed_t sy)
273 {
274     struct ds_wl_seat *seat = data;
275     struct ds_wl_pointer *pointer;
276
277     if (!surface)
278         return;
279
280     ds_dbg("Enter pointer");
281
282     seat->output = wl_surface_get_user_data(surface);
283     seat->enter_serial = serial;
284
285     pointer = get_wl_pointer_from_pointer(seat->pointer_dev->pointer);
286     output_enter_pointer(seat->output, pointer, seat->enter_serial);
287 }
288
289 static void
290 pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
291         uint32_t serial, struct wl_surface *surface)
292 {
293     struct ds_wl_seat *seat = data;
294     struct ds_wl_output *output;
295
296     if (!seat->output)
297         return;
298
299     output = wl_surface_get_user_data(surface);
300     if (seat->output != output)
301         return;
302
303     ds_dbg("Leave pointer");
304
305     output_leave_pointer(seat->output);
306
307     seat->output = NULL;
308     seat->enter_serial = 0;
309 }
310
311 static void
312 pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
313         uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
314 {
315     struct ds_wl_seat *seat = data;
316
317     if (!seat->output)
318         return;
319
320     // FIXME take size size of a output into account
321     struct ds_event_pointer_motion_absolute event = {
322         .device = seat->pointer_dev,
323         .time_msec = time,
324         .x = wl_fixed_to_double(sx) / 700,
325         .y = wl_fixed_to_double(sy) / 400,
326     };
327
328     wl_signal_emit(&seat->pointer_dev->pointer->events.motion_absolute,
329             &event);
330 }
331
332 static void
333 pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
334         uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
335 {
336     struct ds_wl_seat *seat = data;
337
338     if (!seat->output)
339         return;
340
341     struct ds_event_pointer_button event = {
342         .device = seat->pointer_dev,
343         .button = button,
344         .state = state,
345         .time_msec = time,
346     };
347
348     wl_signal_emit(&seat->pointer_dev->pointer->events.button, &event);
349 }
350
351 static void
352 pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
353         uint32_t time, uint32_t axis, wl_fixed_t value)
354 {
355     // TODO
356 }
357
358 static void
359 pointer_handle_frame(void *data, struct wl_pointer *wl_pointer)
360 {
361     struct ds_wl_seat *seat = data;
362
363     if (!seat->output)
364         return;
365
366     wl_signal_emit(&seat->pointer_dev->pointer->events.frame,
367             seat->pointer_dev);
368 }
369
370 static void
371 pointer_handle_axis_source(void *data, struct wl_pointer *wl_pointer,
372         uint32_t axis_source)
373 {
374     // TODO
375 }
376
377 static void
378 pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer,
379         uint32_t time, uint32_t axis)
380 {
381     // TODO
382 }
383
384 static void
385 pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer,
386         uint32_t axis, int32_t discrete)
387 {
388     // TODO
389 }
390
391 static const struct wl_pointer_listener wl_pointer_listener = {
392     .enter = pointer_handle_enter,
393     .leave = pointer_handle_leave,
394     .motion = pointer_handle_motion,
395     .button = pointer_handle_button,
396     .axis = pointer_handle_axis,
397     .frame = pointer_handle_frame,
398     .axis_source = pointer_handle_axis_source,
399     .axis_stop = pointer_handle_axis_stop,
400     .axis_discrete = pointer_handle_axis_discrete,
401 };
402
403 static struct ds_pointer *
404 create_wl_pointer(struct ds_wl_seat *seat)
405 {
406     struct ds_wl_pointer *pointer;
407
408     pointer = calloc(1, sizeof *pointer);
409     if (!pointer) {
410         ds_err("Could not allocate memory");
411         return NULL;
412     }
413
414     ds_pointer_init(&pointer->base, &pointer_iface);
415
416     pointer->wl_pointer = wl_seat_get_pointer(seat->wl_seat);
417     wl_pointer_add_listener(pointer->wl_pointer, &wl_pointer_listener, seat);
418
419     return &pointer->base;
420 }
421
422 static const struct ds_keyboard_interface keyboard_iface;
423
424 static struct ds_wl_keyboard *
425 get_wl_keyboard_from_keyboard(struct ds_keyboard *ds_keyboard)
426 {
427     assert(ds_keyboard->iface == &keyboard_iface);
428     return (struct ds_wl_keyboard *)ds_keyboard;
429 }
430
431 static void
432 keyboard_iface_destroy(struct ds_keyboard *ds_keyboard)
433 {
434     struct ds_wl_keyboard *keyboard;
435
436     keyboard = get_wl_keyboard_from_keyboard(ds_keyboard);
437
438     wl_keyboard_release(keyboard->wl_keyboard);
439
440     free(keyboard);
441 }
442
443 static const struct ds_keyboard_interface keyboard_iface = {
444     .destroy = keyboard_iface_destroy,
445 };
446
447 static void
448 keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
449         uint32_t format, int fd, uint32_t size)
450 {
451     struct ds_wl_seat *seat = data;
452     struct xkb_context *context;
453     struct xkb_keymap *keymap;
454     char *map_str;
455
456     ds_dbg("wl_keyboard: keymap");
457
458     if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
459         map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
460         if (map_str == MAP_FAILED) {
461             ds_log_errno(DS_ERR, "mmap failed");
462             goto end;
463         }
464
465         context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
466         keymap = xkb_keymap_new_from_string(context, map_str,
467                 XKB_KEYMAP_FORMAT_TEXT_V1, 0);
468         munmap(map_str, size);
469
470         if (!keymap) {
471             ds_err("Failed to compile keymap");
472             goto end;
473         }
474
475         ds_keyboard_set_keymap(seat->keyboard_dev->keyboard, keymap);
476
477         xkb_keymap_unref(keymap);
478         xkb_context_unref(context);
479     }
480
481     // TODO More case?
482
483 end:
484     close(fd);
485 }
486
487 static void
488 keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
489         uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
490 {
491     struct ds_wl_seat *seat = data;
492     uint32_t *keycode_ptr;
493     uint32_t time;
494
495     ds_dbg("wl_keyboard: enter");
496
497     time = get_current_time_msec();
498
499     wl_array_for_each(keycode_ptr, keys) {
500         struct ds_event_keyboard_key event = {
501             .keycode = *keycode_ptr,
502             .state = WL_KEYBOARD_KEY_STATE_PRESSED,
503             .time_msec = time,
504             .update_state = false,
505         };
506
507         ds_keyboard_notify_key(seat->keyboard_dev->keyboard, &event);
508     }
509 }
510
511 static void
512 keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
513         uint32_t serial, struct wl_surface *surface)
514 {
515     struct ds_wl_seat *seat = data;
516     struct ds_keyboard *keyboard = seat->keyboard_dev->keyboard;
517     uint32_t *pressed;
518     uint32_t time, keycode;
519     size_t num_keycodes;
520
521     ds_dbg("wl_keyboard: leave");
522
523     time = get_current_time_msec();
524
525     num_keycodes = keyboard->num_keycodes;
526     pressed = alloca(num_keycodes + 1);
527     memcpy(pressed, keyboard->keycodes, num_keycodes * sizeof(uint32_t));
528
529     for (size_t i = 0; i < num_keycodes; i++) {
530         keycode = pressed[i];
531
532         struct ds_event_keyboard_key event = {
533             .keycode = keycode,
534             .state = WL_KEYBOARD_KEY_STATE_RELEASED,
535             .time_msec = time,
536             .update_state = false,
537         };
538
539         ds_keyboard_notify_key(keyboard, &event);
540     }
541 }
542
543 static void
544 keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
545         uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
546 {
547     struct ds_wl_seat *seat = data;
548
549     ds_dbg("wl_keyboard: key");
550
551     struct ds_event_keyboard_key event = {
552         .keycode = key,
553         .state = state,
554         .time_msec = time,
555         .update_state = false,
556     };
557
558     ds_keyboard_notify_key(seat->keyboard_dev->keyboard, &event);
559 }
560
561 static void
562 keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
563         uint32_t serial_in, uint32_t mods_depressed, uint32_t mods_latched,
564         uint32_t mods_locked, uint32_t group)
565 {
566     struct ds_wl_seat *seat = data;
567
568     ds_dbg("wl_keyboard: modifiers");
569
570     ds_keyboard_notify_modifiers(seat->keyboard_dev->keyboard,
571             mods_depressed, mods_latched, mods_locked, group);
572 }
573
574 static void
575 keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
576         int32_t rate, int32_t delay)
577 {
578     ds_dbg("wl_keyboard: repeat_info");
579
580     // This space is intentionally left blank
581 }
582
583 static const struct wl_keyboard_listener wl_keyboard_listener = {
584     .keymap = keyboard_handle_keymap,
585     .enter = keyboard_handle_enter,
586     .leave = keyboard_handle_leave,
587     .key = keyboard_handle_key,
588     .modifiers = keyboard_handle_modifiers,
589     .repeat_info = keyboard_handle_repeat_info,
590 };
591
592 static struct ds_keyboard *
593 create_wl_keyboard(struct ds_wl_seat *seat)
594 {
595     struct ds_wl_keyboard *keyboard;
596
597     keyboard = calloc(1, sizeof *keyboard);
598     if (!keyboard)
599         return NULL;
600
601     ds_keyboard_init(&keyboard->base, &keyboard_iface);
602
603     keyboard->wl_keyboard = wl_seat_get_keyboard(seat->wl_seat);
604     wl_keyboard_add_listener(keyboard->wl_keyboard,
605             &wl_keyboard_listener, seat);
606
607     return &keyboard->base;
608 }
609
610 static const struct ds_touch_interface touch_iface;
611
612 static struct ds_wl_touch *
613 get_wl_touch_from_touch(struct ds_touch *ds_touch)
614 {
615     assert(ds_touch->iface == &touch_iface);
616     return (struct ds_wl_touch *)ds_touch;
617 }
618
619 static void
620 touch_iface_destroy(struct ds_touch *ds_touch)
621 {
622     struct ds_wl_touch *touch;
623
624     touch = get_wl_touch_from_touch(ds_touch);
625
626     wl_touch_release(touch->wl_touch);
627
628     free(touch);
629 }
630
631 static const struct ds_touch_interface touch_iface = {
632     .destroy = touch_iface_destroy,
633 };
634
635 static void
636 touch_handle_down(void *data, struct wl_touch *wl_touch,
637         uint32_t serial, uint32_t time,
638         struct wl_surface *surface, int32_t id,
639         wl_fixed_t fixed_x, wl_fixed_t fixed_y)
640 {
641     struct ds_wl_seat *seat = data;
642
643     ds_dbg("wl_touch: down");
644
645     struct ds_event_touch_down event = {
646         .device = seat->touch_dev,
647         .id = id,
648         .x = fixed_x,
649         .y = fixed_y,
650     };
651
652     wl_signal_emit(&seat->touch_dev->touch->events.down, &event);
653 }
654
655 static void
656 touch_handle_up(void *data, struct wl_touch *wl_touch,
657         uint32_t serial, uint32_t time, int32_t id)
658 {
659     struct ds_wl_seat *seat = data;
660
661     ds_dbg("wl_touch: up");
662
663     struct ds_event_touch_up event = {
664         .device = seat->touch_dev,
665         .id = id,
666     };
667
668     wl_signal_emit(&seat->touch_dev->touch->events.up, &event);
669 }
670
671 static void
672 touch_handle_motion(void *data, struct wl_touch *wl_touch,
673         uint32_t time, int32_t id,
674         wl_fixed_t fixed_x, wl_fixed_t fixed_y)
675 {
676     ds_dbg("wl_touch: motion");
677 }
678
679 static void
680 touch_handle_frame(void *data, struct wl_touch *wl_touch)
681 {
682     ds_dbg("wl_touch: frame");
683 }
684
685 static void
686 touch_handle_cancel(void *data, struct wl_touch *wl_touch)
687 {
688     ds_dbg("wl_touch: cancel");
689 }
690
691 static const struct wl_touch_listener wl_touch_listener = {
692     .down = touch_handle_down,
693     .up = touch_handle_up,
694     .motion = touch_handle_motion,
695     .frame = touch_handle_frame,
696     .cancel = touch_handle_cancel,
697 };
698
699 static struct ds_touch *
700 create_wl_touch(struct ds_wl_seat *seat)
701 {
702     struct ds_wl_touch *touch;
703
704     touch = calloc(1, sizeof *touch);
705     if (!touch) {
706         ds_err("Could not allocate memory");
707         return NULL;
708     }
709
710     ds_touch_init(&touch->base, &touch_iface);
711
712     touch->wl_touch = wl_seat_get_touch(seat->wl_seat);
713     wl_touch_add_listener(touch->wl_touch, &wl_touch_listener, seat);
714
715     return &touch->base;
716 }