56347071d2c093e1dd11b662ecbe8424dcd61c50
[platform/core/uifw/libds-tizen.git] / src / examples / tinyds-tdm-libinput.c
1 #include <assert.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <signal.h>
6 #include <time.h>
7
8 #include <drm_fourcc.h>
9 #include <pixman.h>
10 #include <wayland-server.h>
11 #include <libds/log.h>
12 #include <libds/backend.h>
13 #include <libds/output.h>
14 #include <libds/compositor.h>
15 #include <libds/xdg_shell.h>
16 #include <libds-tizen/allocator/tbm.h>
17 #include <libds-tizen/backend/tdm.h>
18 #include <libds/backend/libinput.h>
19 #include <libds-tizen/tbm_server.h>
20
21 #include <libds/input_device.h>
22 #include <libds/keyboard.h>
23 #include <libds/touch.h>
24 #include <libds/pointer.h>
25 #include <libds/seat.h>
26 #include <libds-tizen/input-devicemgr.h>
27 #include <xkbcommon/xkbcommon.h>
28 #include <libds/interfaces/keyboard.h>
29
30 #define USE_TDM_BUFFER_QUEUE
31
32 #ifdef USE_TDM_BUFFER_QUEUE
33 #include "pixman-tbm-helper.h"
34 #include "tinyds-tdm-renderer.h"
35 #else
36 #include <libds/swapchain.h>
37 #endif
38
39 #include "pixman-helper.h"
40
41 #define TINYDS_UNUSED   __attribute__((unused))
42 struct tinyds_keyboard;
43
44 struct tinyds_output
45 {
46     struct tinyds_server *server;
47     struct ds_output *ds_output;
48     struct ds_allocator *allocator;
49 #ifdef USE_TDM_BUFFER_QUEUE
50     struct tinyds_renderer renderer;
51     struct ds_tdm_buffer_queue *buffer_queue;
52     struct wl_listener buffer_queue_acquirable;
53 #else
54     struct ds_swapchain *swapchain;
55 #endif
56     struct ds_buffer *front_buffer;
57
58     struct wl_listener output_destroy;
59     struct wl_listener output_frame;
60
61     int width, height;
62
63     bool drawable;
64     bool damaged;
65 };
66
67 struct tinyds_server
68 {
69     struct ds_tbm_server *tbm_server;
70
71     struct wl_display *display;
72
73     struct ds_backend *backend;
74     struct ds_backend *input_backend;
75     struct ds_compositor *compositor;
76     struct ds_xdg_shell *xdg_shell;
77     struct ds_seat *seat;
78     uint32_t seat_caps;
79     double output_x, output_y;
80     struct ds_tizen_input_devicemgr *devicemgr;
81
82     struct tinyds_output *output;
83     struct wl_event_source *stdin_source;
84
85     struct wl_list views;
86
87     struct wl_listener new_output;
88     struct wl_listener new_input;
89     struct wl_listener new_xdg_surface;
90
91     struct tinyds_keyboard *keyboard;
92 };
93
94 struct tinyds_view
95 {
96     struct tinyds_server *server;
97
98     struct tinyds_texture *texture;
99     struct ds_xdg_surface *xdg_surface;
100
101     struct wl_listener xdg_surface_map;
102     struct wl_listener xdg_surface_unmap;
103     struct wl_listener xdg_surface_destroy;
104     struct wl_listener surface_commit;
105     struct wl_list link; // tinyds_server::views
106
107     int x, y;
108     bool mapped;
109 };
110
111 struct tinyds_pointer
112 {
113     struct ds_input_device *dev;
114     struct tinyds_server *server;
115
116     struct tinyds_view *focused_view;
117
118     struct wl_listener destroy;
119     struct wl_listener motion; //relative
120     struct wl_listener button;
121     struct wl_listener frame;
122 };
123
124 struct tinyds_keyboard
125 {
126     struct ds_input_device *dev;
127     struct tinyds_server *server;
128
129     struct wl_listener destroy;
130     struct wl_listener key;
131 };
132
133 struct tinyds_touch
134 {
135     struct ds_input_device *dev;
136     struct tinyds_server *server;
137
138     struct wl_listener destroy;
139     struct wl_listener down;
140     struct wl_listener up;
141     struct wl_listener motion;
142 };
143
144 struct tinyds_server tinyds;
145
146 static bool init_server(struct tinyds_server *server, struct wl_display *display);
147 static int server_dispatch_stdin(int fd, uint32_t mask, void *data);
148 static void output_handle_destroy(struct wl_listener *listener, void *data);
149 static void output_handle_frame(struct wl_listener *listener, void *data);
150 static void draw_server_with_damage(struct tinyds_server *server);
151 static void draw_output(struct tinyds_output *output);
152 static void output_swap_buffer(struct tinyds_output *output,
153         struct ds_buffer *buffer);
154 static void view_send_frame_done(struct tinyds_view *view);
155 #ifdef USE_TDM_BUFFER_QUEUE
156 static void output_buffer_queue_init(struct tinyds_output *output);
157 static void output_renderer_init(struct tinyds_output *output);
158 static void output_draw_with_renderer(struct tinyds_output *output);
159 #else
160 static void output_swapchain_init(struct tinyds_output *output,
161         int width, int height, uint32_t format);
162 static void output_draw_with_swapchain(struct tinyds_output *output);
163 static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image);
164 #endif
165 static void server_add_keyboard(struct tinyds_server *server,
166         struct ds_input_device *dev);
167 static void server_add_pointer(struct tinyds_server *server,
168         struct ds_input_device *dev);
169 static void server_add_touch(struct tinyds_server *server,
170         struct ds_input_device *dev);
171
172 int
173 main(void)
174 {
175     struct tinyds_server *server = &tinyds;
176     struct wl_display *display;
177     struct wl_event_loop *loop;
178     const char *socket;
179     bool res;
180
181     ds_log_init(DS_INF, NULL);
182
183     display = wl_display_create();
184     assert(display);
185
186     res = init_server(server, display);
187     assert(res);
188
189     socket = wl_display_add_socket_auto(display);
190     assert(socket);
191
192     ds_backend_start(server->backend);
193     ds_backend_start(server->input_backend);
194
195     setenv("WAYLAND_DISPLAY", socket, true);
196
197     ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket);
198
199     loop = wl_display_get_event_loop(display);
200     server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO,
201             WL_EVENT_READABLE, server_dispatch_stdin, server);
202
203     wl_display_run(display);
204
205     wl_display_destroy_clients(display);
206     wl_display_destroy(display);
207
208     return 0;
209 }
210
211 static void
212 view_handle_xdg_surface_map(struct wl_listener *listener,
213         void *data TINYDS_UNUSED)
214 {
215     struct tinyds_view *view;
216     struct ds_keyboard *keyboard;
217     view = wl_container_of(listener, view, xdg_surface_map);
218     view->mapped = true;
219
220     if (!view->server->keyboard) return;
221     keyboard = ds_input_device_get_keyboard(view->server->keyboard->dev);
222     if (keyboard != NULL) {
223         ds_seat_keyboard_notify_enter(view->server->seat,
224                 ds_xdg_surface_get_surface(view->xdg_surface),
225                 keyboard->keycodes, keyboard->num_keycodes,
226                 &keyboard->modifiers);
227     }
228 }
229
230 static void
231 view_handle_xdg_surface_unmap(struct wl_listener *listener,
232         void *data TINYDS_UNUSED)
233 {
234     struct tinyds_view *view;
235
236     view = wl_container_of(listener, view, xdg_surface_unmap);
237     view->mapped = false;
238 }
239
240 static void
241 view_handle_xdg_surface_destroy(struct wl_listener *listener,
242         void *data TINYDS_UNUSED) 
243 {
244     struct tinyds_view *view;
245     struct tinyds_server *server;
246
247     view = wl_container_of(listener, view, xdg_surface_destroy);
248     server = view->server;
249
250     wl_list_remove(&view->xdg_surface_destroy.link);
251     wl_list_remove(&view->xdg_surface_map.link);
252     wl_list_remove(&view->xdg_surface_unmap.link);
253     wl_list_remove(&view->surface_commit.link);
254     wl_list_remove(&view->link);
255     free(view);
256
257     draw_server_with_damage(server);
258 }
259
260 static void
261 view_handle_surface_commit(struct wl_listener *listener,
262         void *data TINYDS_UNUSED)
263 {
264     struct tinyds_view *view;
265
266     view = wl_container_of(listener, view, surface_commit);
267     draw_server_with_damage(view->server);
268 }
269
270 static void
271 server_new_xdg_surface(struct wl_listener *listener, void *data)
272 {
273     struct tinyds_server *server;
274     struct tinyds_view *view;
275     struct ds_xdg_surface *xdg_surface;
276
277     server = wl_container_of(listener, server, new_xdg_surface);
278     xdg_surface = data;
279
280     ds_inf("New xdg_surface(%p)", (void *)xdg_surface);
281
282     view = calloc(1, sizeof *view);
283     assert(view);
284
285     view->server = server;
286     view->xdg_surface = xdg_surface;
287
288     view->xdg_surface_map.notify = view_handle_xdg_surface_map;
289     ds_xdg_surface_add_map_listener(xdg_surface,
290             &view->xdg_surface_map);
291
292     view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap;
293     ds_xdg_surface_add_unmap_listener(xdg_surface,
294             &view->xdg_surface_unmap);
295
296     view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy;
297     ds_xdg_surface_add_destroy_listener(xdg_surface,
298             &view->xdg_surface_destroy);
299
300     view->surface_commit.notify = view_handle_surface_commit;
301     ds_surface_add_commit_listener(
302             ds_xdg_surface_get_surface(xdg_surface),
303             &view->surface_commit);
304
305     wl_list_insert(server->views.prev, &view->link);
306
307     view->x = rand() % 1000;
308     view->y = rand() % 500;
309 }
310
311 static void
312 backend_handle_new_output(struct wl_listener *listener, void *data)
313 {
314     struct tinyds_server *server;
315     struct tinyds_output *output;
316     struct ds_output *ds_output;
317     const struct ds_output_mode *mode;
318
319     server = wl_container_of(listener, server, new_output);
320     ds_output = data;
321
322     ds_inf("New output(%p)", ds_output);
323
324     if (server->output)
325         return;
326
327     mode = ds_output_get_preferred_mode(ds_output);
328     ds_output_set_mode(ds_output, mode);
329
330     output = calloc(1, sizeof *output);
331     if (!output)
332         return;
333
334     output->server = server;
335     output->ds_output = ds_output;
336     output->width = mode->width;
337     output->height = mode->height;
338     output->drawable = true;
339     output->damaged = true;
340
341 #ifdef USE_TDM_BUFFER_QUEUE
342     output_buffer_queue_init(output);
343     output_renderer_init(output);
344 #else
345     output_swapchain_init(output, mode->width, mode->height,
346             DRM_FORMAT_XRGB8888);
347 #endif
348
349     output->output_destroy.notify = output_handle_destroy;
350     ds_output_add_destroy_listener(ds_output, &output->output_destroy);
351
352     output->output_frame.notify = output_handle_frame;
353     ds_output_add_frame_listener(ds_output, &output->output_frame);
354
355     server->output = output;
356
357     draw_output(output);
358 }
359
360 static void
361 backend_handle_new_input(struct wl_listener *listener, void *data)
362 {
363     struct tinyds_server *server;
364     struct ds_input_device *dev = data;
365     enum ds_input_device_type dev_type;
366
367     server = wl_container_of(listener, server, new_input);
368
369     dev_type = ds_input_device_get_type(dev);
370
371     switch (dev_type) {
372         case DS_INPUT_DEVICE_KEYBOARD:
373             server_add_keyboard(server, dev);
374             server->seat_caps |= WL_SEAT_CAPABILITY_KEYBOARD;
375             break;
376         case DS_INPUT_DEVICE_TOUCH:
377             server_add_touch(server, dev);
378             server->seat_caps |= WL_SEAT_CAPABILITY_TOUCH;
379             break;
380         case DS_INPUT_DEVICE_POINTER:
381             server_add_pointer(server, dev);
382             server->seat_caps |= WL_SEAT_CAPABILITY_POINTER;
383             break;
384         default:
385             ds_err("Unknown type(%d) of ds_input_device", dev_type);
386             break;
387     }
388
389     ds_seat_set_capabilities(server->seat, server->seat_caps);
390 }
391
392 static void
393 devicemgr_add_keymap_data(struct wl_list *list, const char *name, int keycode)
394 {
395     struct ds_tizen_input_devicemgr_keymap_data *data;
396
397     data = calloc(1, sizeof *data);
398     if (!data) {
399         ds_err("Failed to alloc memory\n");
400         return;
401     }
402
403     data->name = strdup(name);
404     data->keycode = keycode;
405
406     wl_list_insert(list, &data->link);
407 }
408
409 static void
410 devicemgr_remove_keymap_data(struct wl_list *list, int keycode)
411 {
412     struct ds_tizen_input_devicemgr_keymap_data *data, *tmp;
413
414     wl_list_for_each_safe(data, tmp, list, link) {
415         if (data->keycode == keycode) {
416             wl_list_remove(&data->link);
417             free(data);
418         }
419     }
420 }
421
422 static void
423 devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr)
424 {
425     struct wl_list keymap_list;
426     bool res;
427
428     wl_list_init(&keymap_list);
429
430     devicemgr_add_keymap_data(&keymap_list, "XF86VolumeRaise", 455);
431     devicemgr_add_keymap_data(&keymap_list, "XF86VolumeLower", 456);
432     devicemgr_add_keymap_data(&keymap_list, "XF86LightOn", 457);
433     devicemgr_add_keymap_data(&keymap_list, "XF86LightOff", 458);
434
435     res = ds_tizen_input_devicemgr_set_keymap_list(devicemgr, &keymap_list);
436     if (!res)
437         ds_inf("Failed to set keymap");
438
439     devicemgr_remove_keymap_data(&keymap_list, 455);
440     devicemgr_remove_keymap_data(&keymap_list, 456);
441     devicemgr_remove_keymap_data(&keymap_list, 457);
442     devicemgr_remove_keymap_data(&keymap_list, 458);
443 }
444
445 static bool
446 init_server(struct tinyds_server *server, struct wl_display *display)
447 {
448     server->display = display;
449
450     wl_list_init(&server->views);
451
452     if (wl_display_init_shm(display) != 0)
453         return false;
454
455     server->backend = ds_tdm_backend_create(display);
456     if (!server->backend)
457         return false;
458
459     server->input_backend = ds_libinput_backend_create(display);
460     if (!server->input_backend) {
461         ds_backend_destroy(server->backend);
462         return false;
463     }
464
465     server->new_output.notify = backend_handle_new_output;
466     ds_backend_add_new_output_listener(server->backend,
467             &server->new_output);
468
469     server->new_input.notify = backend_handle_new_input;
470     ds_backend_add_new_input_listener(server->input_backend, &server->new_input);
471
472     server->compositor = ds_compositor_create(display);
473     if (!server->compositor)
474         goto err;
475
476     server->tbm_server = ds_tbm_server_create(display);
477     if (!server->tbm_server)
478         goto err;
479
480     server->xdg_shell = ds_xdg_shell_create(display);
481     if (!server->xdg_shell)
482         goto err;
483
484     server->new_xdg_surface.notify = server_new_xdg_surface;
485     ds_xdg_shell_add_new_surface_listener(server->xdg_shell,
486             &server->new_xdg_surface);
487
488     server->seat = ds_seat_create(display, "seat0" /* arbitrary name */);
489     if (!server->seat)
490         goto err;
491     server->seat_caps = 0;
492
493     server->devicemgr = ds_tizen_input_devicemgr_create(
494             server->input_backend, server->seat);
495     if (!server->devicemgr) {
496         goto err;
497     }
498
499     devicemgr_set_keymap(server->devicemgr);
500     return true;
501
502 err:
503     ds_backend_destroy(server->backend);
504     ds_backend_destroy(server->input_backend);
505
506     return false;
507 }
508
509 static void
510 output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
511 {
512     struct tinyds_output *output =
513         wl_container_of(listener, output, output_destroy);
514
515     wl_list_remove(&output->output_destroy.link);
516     wl_list_remove(&output->output_frame.link);
517
518     if (output->front_buffer)
519         ds_buffer_unlock(output->front_buffer);
520
521 #ifdef USE_TDM_BUFFER_QUEUE
522     fini_renderer(&output->renderer);
523 #else
524     if (output->swapchain)
525         ds_swapchain_destroy(output->swapchain);
526
527     if (output->allocator)
528         ds_allocator_destroy(output->allocator);
529 #endif
530
531     wl_display_terminate(output->server->display);
532
533     output->server->output = NULL;
534
535     free(output);
536 }
537
538 static void
539 output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED)
540 {
541     struct tinyds_output *output =
542         wl_container_of(listener, output, output_frame);
543
544     output->drawable = true;
545     draw_output(output);
546 }
547
548 static void
549 draw_server_with_damage(struct tinyds_server *server)
550 {
551     server->output->damaged = true;
552     draw_output(server->output);
553 }
554
555 #ifdef USE_TDM_BUFFER_QUEUE
556 static void
557 output_handle_buffer_queue_acquirable(struct wl_listener *listener,
558         void *data TINYDS_UNUSED)
559 {
560     struct tinyds_output *output;
561     struct ds_buffer *buffer;
562
563     output = wl_container_of(listener, output, buffer_queue_acquirable);
564
565     buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue);
566     assert(buffer);
567
568     output_swap_buffer(output, buffer);
569 }
570
571 static void
572 output_buffer_queue_init(struct tinyds_output *output)
573 {
574     struct ds_tdm_output *tdm_output;
575
576     tdm_output = ds_tdm_output_from_output(output->ds_output);
577     assert(tdm_output);
578
579     output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output);
580     assert(output->buffer_queue);
581
582     output->buffer_queue_acquirable.notify =
583         output_handle_buffer_queue_acquirable;
584     ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue,
585             &output->buffer_queue_acquirable);
586 }
587
588 static void
589 output_renderer_init(struct tinyds_output *output)
590 {
591     init_renderer(&output->renderer);
592
593     renderer_set_surface_queue(&output->renderer,
594             ds_tdm_buffer_queue_get_native_queue(output->buffer_queue));
595
596     renderer_set_bg_color(&output->renderer, 80, 80, 80);
597 }
598
599 static void
600 output_draw_with_renderer(struct tinyds_output *output)
601 {
602     struct tinyds_view *view;
603
604     ds_dbg(">> BEGIN UPDATE TEXTURES");
605
606     wl_list_for_each(view, &output->server->views, link) {
607         struct ds_buffer *ds_buffer;
608         struct ds_tbm_client_buffer *tbm_buffer;
609         tbm_surface_h surface;
610
611         if (!view->mapped)
612             continue;
613
614         ds_buffer = ds_surface_get_buffer(
615                 ds_xdg_surface_get_surface(view->xdg_surface));
616         assert(ds_buffer);
617
618         tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer);
619         assert(tbm_buffer);
620
621         surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer);
622
623         renderer_add_texture(&output->renderer, surface, view->x, view->y);
624
625         view_send_frame_done(view);
626     }
627
628     ds_dbg("<< END UPDATE TEXTURES");
629
630     renderer_draw(&output->renderer);
631
632 }
633 #else
634 static void
635 output_swapchain_init(struct tinyds_output *output,
636         int width, int height, uint32_t format);
637
638 {
639     output->allocator = ds_tbm_allocator_create();
640     assert(output->allocator);
641
642     output->swapchain = ds_swapchain_create(output->allocator,
643             width, height, format);
644     assert(output->swapchain);
645 }
646
647 static void
648 output_draw_with_swapchain(struct tinyds_output *output)
649 {
650     struct tinyds_view *view;
651     struct ds_buffer *output_buffer;
652     pixman_image_t *output_image;
653
654     output_buffer = ds_swapchain_acquire(output->swapchain, NULL);
655     if (!output_buffer)
656         return;
657
658     output_image = pixman_image_from_buffer(output_buffer,
659             DS_BUFFER_DATA_PTR_ACCESS_WRITE);
660     if (!output_image) {
661         ds_buffer_unlock(output_buffer);
662         return;
663     }
664
665     pixman_image_fill_color(output_image, 80, 80, 80);
666
667     wl_list_for_each(view, &output->server->views, link) {
668         if (!view->mapped)
669             continue;
670         draw_view(view, output_image);
671     }
672     pixman_image_unref(output_image);
673
674     output_swap_buffer(output, output_buffer);
675 }
676
677 static void
678 draw_view(struct tinyds_view *view, pixman_image_t *dst_image)
679 {
680     struct ds_buffer *buffer;
681     pixman_image_t *src_image;
682
683     buffer = ds_surface_get_buffer(
684             ds_xdg_surface_get_surface(view->xdg_surface));
685     if (!buffer)
686         return;
687
688     src_image = pixman_image_from_buffer(buffer,
689             DS_BUFFER_DATA_PTR_ACCESS_READ);
690     pixman_image_composite32(PIXMAN_OP_OVER,
691             src_image,
692             NULL,
693             dst_image,
694             0, 0, 0, 0,
695             view->x, view->y,
696             pixman_image_get_width(src_image),
697             pixman_image_get_height(src_image));
698     pixman_image_unref(src_image);
699
700     view_send_frame_done(view);
701 }
702 #endif
703
704 static void
705 draw_output(struct tinyds_output *output)
706 {
707
708     if (!output->drawable || !output->damaged)
709         return;
710
711 #ifdef USE_TDM_BUFFER_QUEUE
712     output_draw_with_renderer(output);
713 #else
714     output_draw_with_swapchain(output);
715 #endif
716
717     output->drawable = false;
718     output->damaged = false;
719 }
720
721 static void
722 output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer)
723 {
724     ds_output_attach_buffer(output->ds_output, buffer);
725     ds_output_commit(output->ds_output);
726
727     if (output->front_buffer)
728         ds_buffer_unlock(output->front_buffer);
729     output->front_buffer = buffer;
730 }
731
732 static void
733 view_send_frame_done(struct tinyds_view *view)
734 {
735     struct timespec now;
736     clock_gettime(CLOCK_MONOTONIC, &now);
737     ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface),
738             &now);
739 }
740
741 static int
742 server_dispatch_stdin(int fd, uint32_t mask, void *data)
743 {
744     struct tinyds_server *server = data;
745
746     wl_display_terminate(server->display);
747
748     return 1;
749 }
750
751
752 static void
753 keyboard_handle_device_destroy(struct wl_listener *listener, void *data)
754 {
755     struct tinyds_keyboard *kbd;
756
757     kbd = wl_container_of(listener, kbd, destroy);
758
759     ds_inf("Keyboard(%p) destroyed", kbd);
760
761     wl_list_remove(&kbd->destroy.link);
762     wl_list_remove(&kbd->key.link);
763
764     kbd->server->keyboard = NULL;
765
766     free(kbd);
767 }
768
769 static bool
770 server_handle_keybinding(struct tinyds_server *server, xkb_keysym_t sym)
771 {
772     switch (sym) {
773         case XKB_KEY_BackSpace:
774             wl_display_terminate(server->display);
775             break;
776         default:
777             return false;
778     }
779
780     return true;
781 }
782
783 static void
784 keyboard_handle_key(struct wl_listener *listener, void *data)
785 {
786     struct tinyds_keyboard *kbd;
787     struct ds_event_keyboard_key *event = data;
788     struct ds_keyboard *ds_keyboard;
789     struct xkb_state *xkb_state;
790     const xkb_keysym_t *syms;
791     int nsyms;
792     bool handled = false;
793
794     kbd = wl_container_of(listener, kbd, key);
795
796     ds_inf("Keyboard(%p) event key: keycode(%d), state(%d), time_msec(%d), "
797             "update_state(%d)", kbd->dev,
798             event->keycode, event->state, event->time_msec,
799             event->update_state);
800
801     ds_keyboard = ds_input_device_get_keyboard(kbd->dev);
802
803     if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
804         xkb_state = ds_keyboard_get_xkb_state(ds_keyboard);
805         if (xkb_state) {
806             nsyms = xkb_state_key_get_syms(xkb_state, event->keycode + 8,
807                     &syms);
808             for (int i = 0; i < nsyms; i++) {
809                 handled = server_handle_keybinding(kbd->server, syms[i]);
810             }
811         }
812     }
813
814     if (!handled) {
815         ds_seat_keyboard_notify_key(kbd->server->seat, event->time_msec,
816                 event->keycode, event->state);
817     }
818 }
819
820 static void
821 server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev)
822 {
823     struct tinyds_keyboard *kbd;
824     struct xkb_context *context;
825     struct xkb_keymap *keymap;
826
827     kbd = calloc(1, sizeof *kbd);
828     assert(kbd);
829
830     kbd->dev = dev;
831     kbd->server = server;
832
833     context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
834     keymap = xkb_keymap_new_from_names(context, NULL,
835             XKB_KEYMAP_COMPILE_NO_FLAGS);
836
837     if (!keymap) {
838         ds_err("Failed to compile keymap");
839         xkb_context_unref(context);
840     }
841
842     ds_keyboard_set_keymap(ds_input_device_get_keyboard(dev), keymap);
843
844     xkb_keymap_unref(keymap);
845     xkb_context_unref(context);
846
847     kbd->destroy.notify = keyboard_handle_device_destroy;
848     ds_input_device_add_destroy_listener(dev, &kbd->destroy);
849
850     kbd->key.notify = keyboard_handle_key;
851     ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key);
852
853     server->keyboard = kbd;
854
855     ds_inf("Keyboard(%p) added", kbd);
856 }
857
858 static struct tinyds_view *
859 server_view_at(struct tinyds_server *server, double lx, double ly,
860         double *sx, double *sy)
861 {
862     struct tinyds_view *view;
863     struct ds_surface *surface;
864     struct ds_buffer *buffer;
865     int x, y, w = 0, h = 0;
866
867     wl_list_for_each(view, &server->views, link) {
868         surface = ds_xdg_surface_get_surface(view->xdg_surface);
869         buffer = ds_surface_get_buffer(surface);
870         ds_buffer_get_size(buffer, &w, &h);
871
872         x = view->x;
873         y = view->y;
874
875         if (lx >= x && lx <= x + w && ly >= y && ly <= y + h) {
876             *sx = lx - x;
877             *sy = ly - y;
878
879             return view;
880         }
881     }
882
883     return NULL;
884 }
885
886 static void
887 touch_handle_device_destroy(struct wl_listener *listener, void *data)
888 {
889     struct tinyds_touch *touch;
890
891     touch = wl_container_of(listener, touch, destroy);
892
893     ds_inf("Touch(%p) destroyed", touch);
894
895     wl_list_remove(&touch->destroy.link);
896     wl_list_remove(&touch->down.link);
897     wl_list_remove(&touch->up.link);
898     wl_list_remove(&touch->motion.link);
899
900     free(touch);
901 }
902
903 static void
904 touch_handle_down(struct wl_listener *listener, void *data)
905 {
906     struct ds_event_touch_down *event = data;
907     struct tinyds_touch *touch;
908     struct tinyds_view *view;
909     struct tinyds_server *server;
910     double sx = 0.f, sy = 0.f;
911
912     touch = wl_container_of(listener, touch, down);
913
914     server = touch->server;
915     server->output_x = event->x * server->output->width;
916     server->output_y = event->y * server->output->height;
917
918     ds_inf("Touch(%p) event down: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
919             touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
920
921     view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
922
923     if (view) {
924         ds_seat_touch_notify_down(touch->server->seat, ds_xdg_surface_get_surface(view->xdg_surface),
925                 event->time_msec, event->id, sx, sy);
926     }
927 }
928
929 static void
930 touch_handle_up(struct wl_listener *listener, void *data)
931 {
932     struct ds_event_touch_up *event = data;
933     struct tinyds_touch *touch;
934
935     touch = wl_container_of(listener, touch, up);
936
937     ds_inf("Touch(%p) event up: id(%d) time_msec(%d)",
938             touch->dev, event->id, event->time_msec);
939
940     ds_seat_touch_notify_up(touch->server->seat, event->time_msec, event->id);
941 }
942
943 static void
944 touch_handle_motion(struct wl_listener *listener, void *data)
945 {
946     struct ds_event_touch_motion *event = data;
947     struct tinyds_touch *touch;
948     struct tinyds_view *view;
949     struct tinyds_server *server;
950     double sx = 0.f, sy = 0.f;
951
952     touch = wl_container_of(listener, touch, motion);
953
954     server = touch->server;
955     server->output_x = event->x * server->output->width;
956     server->output_y = event->y * server->output->height;
957
958     ds_inf("Touch(%p) event motion: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
959             touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
960
961     view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
962
963     if (view) {
964         ds_seat_touch_notify_motion(server->seat, event->time_msec,
965                 event->id, sx, sy);
966     }
967 }
968
969 static void
970 server_add_touch(struct tinyds_server *server, struct ds_input_device *dev)
971 {
972     struct tinyds_touch *touch;
973
974     touch = calloc(1, sizeof *touch);
975     assert(touch);
976
977     touch->dev = dev;
978     touch->server = server;
979
980     touch->destroy.notify = touch_handle_device_destroy;
981     ds_input_device_add_destroy_listener(dev, &touch->destroy);
982
983     touch->down.notify = touch_handle_down;
984     ds_touch_add_down_listener(ds_input_device_get_touch(dev), &touch->down);
985
986     touch->up.notify = touch_handle_up;
987     ds_touch_add_up_listener(ds_input_device_get_touch(dev), &touch->up);
988
989     touch->motion.notify = touch_handle_motion;
990     ds_touch_add_motion_listener(ds_input_device_get_touch(dev), &touch->motion);
991
992     ds_inf("Touch(%p) added", touch);
993 }
994
995 static void
996 pointer_handle_device_destroy(struct wl_listener *listener, void *data)
997 {
998     struct tinyds_pointer *pointer;
999
1000     pointer = wl_container_of(listener, pointer, destroy);
1001
1002     ds_inf("Pointer(%p) destroyed", pointer);
1003
1004     wl_list_remove(&pointer->destroy.link);
1005     wl_list_remove(&pointer->motion.link);
1006     wl_list_remove(&pointer->button.link);
1007     wl_list_remove(&pointer->frame.link);
1008
1009     free(pointer);
1010 }
1011
1012 static void
1013 pointer_handle_motion(struct wl_listener *listener, void *data)
1014 {
1015     struct tinyds_pointer *pointer;
1016     struct ds_event_pointer_motion *event = data;
1017     struct tinyds_view *view;
1018     struct tinyds_server *server;
1019     int ow = 0, oh = 0;
1020     double sx, sy;
1021
1022     pointer = wl_container_of(listener, pointer, motion);
1023
1024     server = pointer->server;
1025     if (server->output) {
1026         ow = server->output->width;
1027         oh = server->output->height;
1028     }
1029
1030     if (server->output_x + event->delta_x >= ow)
1031         server->output_x = ow;
1032     else if(server->output_x + event->delta_x <= 0.f)
1033         server->output_x = 0.f;
1034     else
1035         server->output_x = server->output_x + event->delta_x ;
1036     if (server->output_y + event->delta_y >= oh)
1037         server->output_y = oh;
1038     else if(server->output_y + event->delta_y <= 0.f)
1039         server->output_y = 0.f;
1040     else
1041         server->output_y = server->output_y + event->delta_y ;
1042
1043     ds_inf("Pointer(%p) motion: (delta_x %.1f delta_y %.1f) output_x %.1f output_y %.1f",
1044             pointer, event->delta_x, event->delta_y, server->output_x, server->output_y);
1045
1046     view = server_view_at(pointer->server, server->output_x, server->output_y, &sx, &sy);
1047
1048     if (pointer->focused_view != view) {
1049         if (pointer->focused_view) {
1050             ds_inf("Clear pointer focus from view(%p)", pointer->focused_view);
1051             ds_seat_pointer_notify_clear_focus(pointer->server->seat);
1052             pointer->focused_view = NULL;
1053         }
1054
1055         if (view) {
1056             ds_inf("Set pointer focus to view(%p)", view);
1057             ds_seat_pointer_notify_enter(pointer->server->seat,
1058                     ds_xdg_surface_get_surface(view->xdg_surface), sx, sy);
1059             pointer->focused_view = view;
1060         }
1061     }
1062
1063     if (view) {
1064         ds_seat_pointer_notify_motion(pointer->server->seat,
1065                 event->time_msec, sx, sy);
1066     }
1067 }
1068
1069 static void
1070 pointer_handle_button(struct wl_listener *listener, void *data)
1071 {
1072     struct tinyds_pointer *pointer;
1073     struct ds_event_pointer_button *event = data;
1074
1075     pointer = wl_container_of(listener, pointer, button);
1076
1077     ds_inf("Pointer(%p) button(%d): state(%s) time(%d)",
1078             pointer, event->button,
1079             (event->state == DS_BUTTON_PRESSED) ? "Pressed" : "Released",
1080             event->time_msec);
1081
1082     ds_seat_pointer_notify_button(pointer->server->seat, event->time_msec, event->button, event->state);
1083 }
1084
1085 static void
1086 pointer_handle_frame(struct wl_listener *listener, void *data)
1087 {
1088     struct tinyds_pointer *pointer;
1089
1090     pointer = wl_container_of(listener, pointer, frame);
1091
1092     ds_inf("Pointer(%p) frame", pointer);
1093     ds_seat_pointer_notify_frame(pointer->server->seat);
1094 }
1095
1096 static void
1097 server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev)
1098 {
1099     struct tinyds_pointer *pointer;
1100
1101     pointer = calloc(1, sizeof *pointer);
1102     assert(pointer);
1103
1104     pointer->dev = dev;
1105     pointer->server = server;
1106     server->output_x = 200;
1107     server->output_y = 200;
1108
1109     pointer->destroy.notify = pointer_handle_device_destroy;
1110     ds_input_device_add_destroy_listener(dev, &pointer->destroy);
1111
1112     pointer->motion.notify = pointer_handle_motion;
1113     ds_pointer_add_motion_listener(ds_input_device_get_pointer(dev),
1114             &pointer->motion);
1115
1116     pointer->button.notify = pointer_handle_button;
1117     ds_pointer_add_button_listener(ds_input_device_get_pointer(dev),
1118             &pointer->button);
1119
1120     pointer->frame.notify = pointer_handle_frame;
1121     ds_pointer_add_frame_listener(ds_input_device_get_pointer(dev),
1122             &pointer->frame);
1123
1124     ds_inf("Pointer(%p) added", pointer);
1125 }