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