0abb4b0f5b8aa2e6d32032e0a224725580b7e01a
[platform/core/uifw/libds-tizen.git] / examples / tinyds-tdm.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 #include <libds-tizen/dpms.h>
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 #include <libds-tizen/launch/effect.h>
30
31 #define USE_TDM_BUFFER_QUEUE
32
33 #ifdef USE_TDM_BUFFER_QUEUE
34 #include "pixman-tbm-helper.h"
35 #include "tinyds-tdm-renderer.h"
36 #else
37 #include <libds/swapchain.h>
38 #endif
39
40 #include "pixman-helper.h"
41
42 #define TINYDS_UNUSED   __attribute__((unused))
43 struct tinyds_keyboard;
44 struct tinyds_pointer;
45
46 struct tinyds_output
47 {
48     struct tinyds_server *server;
49     struct ds_output *ds_output;
50     struct ds_allocator *allocator;
51 #ifdef USE_TDM_BUFFER_QUEUE
52     struct tinyds_renderer renderer;
53     struct ds_tdm_buffer_queue *buffer_queue;
54     struct wl_listener buffer_queue_acquirable;
55 #else
56     struct ds_swapchain *swapchain;
57 #endif
58     struct ds_buffer *front_buffer;
59
60     struct wl_listener output_destroy;
61     struct wl_listener output_frame;
62
63     int width, height;
64
65     bool drawable;
66     bool damaged;
67 };
68
69 struct tinyds_dpms
70 {
71     struct ds_tizen_dpms *ds_dpms;
72     struct tinyds_server *server;
73
74     struct wl_listener destroy;
75     struct wl_listener set_dpms;
76     struct wl_listener get_dpms;
77 };
78
79 struct tinyds_server
80 {
81     struct ds_tbm_server *tbm_server;
82
83     struct wl_display *display;
84
85     struct ds_backend *backend;
86     struct ds_backend *input_backend;
87     struct ds_compositor *compositor;
88     struct ds_xdg_shell *xdg_shell;
89     struct ds_seat *seat;
90     uint32_t seat_caps;
91     double output_x, output_y;
92     struct ds_tizen_input_devicemgr *devicemgr;
93     struct ds_tizen_effect *effect;
94     struct ds_tizen_splash *splash;
95
96     struct tinyds_output *output;
97     struct tinyds_dpms *dpms;
98     struct wl_event_source *stdin_source;
99
100     struct wl_list views;
101
102     struct wl_listener new_output;
103     struct wl_listener new_input;
104     struct wl_listener new_xdg_surface;
105     struct wl_listener devicemgr_destroy;
106     struct wl_listener pointer_warp;
107     struct wl_listener effect_destroy;
108     struct wl_listener effect_type_set;
109     struct wl_listener effect_type_unset;
110     struct wl_listener new_splash;
111     struct wl_listener splash_owner;
112
113     struct wl_list keyboards;
114     struct wl_list pointers;
115 };
116
117 struct tinyds_view
118 {
119     struct tinyds_server *server;
120
121     struct tinyds_texture *texture;
122     struct ds_xdg_surface *xdg_surface;
123
124     struct wl_listener xdg_surface_map;
125     struct wl_listener xdg_surface_unmap;
126     struct wl_listener xdg_surface_destroy;
127     struct wl_listener surface_commit;
128     struct wl_list link; // tinyds_server::views
129
130     int x, y;
131     bool mapped;
132
133     pid_t pid;
134     int effect_type;
135 };
136
137 struct tinyds_pointer
138 {
139     struct ds_input_device *dev;
140     struct tinyds_server *server;
141
142     struct tinyds_view *focused_view;
143
144     struct wl_listener destroy;
145     struct wl_listener motion; //relative
146     struct wl_listener button;
147     struct wl_listener frame;
148     struct wl_list link; //tinyds_server::pointers
149 };
150
151 struct tinyds_keyboard
152 {
153     struct ds_input_device *dev;
154     struct tinyds_server *server;
155
156     struct wl_listener destroy;
157     struct wl_listener key;
158     struct wl_list link; //tinyds_server::keyboards
159 };
160
161 struct tinyds_touch
162 {
163     struct ds_input_device *dev;
164     struct tinyds_server *server;
165
166     struct wl_listener destroy;
167     struct wl_listener down;
168     struct wl_listener up;
169     struct wl_listener motion;
170 };
171
172 struct tinyds_server tinyds;
173
174 static bool init_server(struct tinyds_server *server, struct wl_display *display);
175 static int server_dispatch_stdin(int fd, uint32_t mask, void *data);
176 static void output_handle_destroy(struct wl_listener *listener, void *data);
177 static void output_handle_frame(struct wl_listener *listener, void *data);
178 static void draw_server_with_damage(struct tinyds_server *server);
179 static void draw_output(struct tinyds_output *output);
180 static void output_swap_buffer(struct tinyds_output *output,
181         struct ds_buffer *buffer);
182 static void view_send_frame_done(struct tinyds_view *view);
183 #ifdef USE_TDM_BUFFER_QUEUE
184 static void output_buffer_queue_init(struct tinyds_output *output);
185 static void output_renderer_init(struct tinyds_output *output);
186 static void output_draw_with_renderer(struct tinyds_output *output);
187 #else
188 static void output_swapchain_init(struct tinyds_output *output,
189         int width, int height, uint32_t format);
190 static void output_draw_with_swapchain(struct tinyds_output *output);
191 static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image);
192 #endif
193 static void dpms_handle_destroy(struct wl_listener *listener, void *data);
194 static void dpms_handle_set_dpms(struct wl_listener *listener, void *data);
195 static void dpms_handle_get_dpms(struct wl_listener *listener, void *data);
196 static void server_add_keyboard(struct tinyds_server *server,
197         struct ds_input_device *dev);
198 static void server_add_pointer(struct tinyds_server *server,
199         struct ds_input_device *dev);
200 static void server_add_touch(struct tinyds_server *server,
201         struct ds_input_device *dev);
202
203 static struct tinyds_view *
204 server_view_at(struct tinyds_server *server, double lx, double ly,
205         double *sx, double *sy);
206
207 int
208 main(void)
209 {
210     struct tinyds_server *server = &tinyds;
211     struct wl_display *display;
212     struct wl_event_loop *loop;
213     const char *socket;
214     bool res;
215
216     ds_log_init(DS_INF, NULL);
217
218     display = wl_display_create();
219     assert(display);
220
221     res = init_server(server, display);
222     assert(res);
223
224     socket = wl_display_add_socket_auto(display);
225     assert(socket);
226
227     ds_backend_start(server->backend);
228     ds_backend_start(server->input_backend);
229
230     setenv("WAYLAND_DISPLAY", socket, true);
231
232     ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket);
233
234     loop = wl_display_get_event_loop(display);
235     server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO,
236             WL_EVENT_READABLE, server_dispatch_stdin, server);
237
238     wl_display_run(display);
239
240     wl_display_destroy_clients(display);
241     wl_display_destroy(display);
242
243     return 0;
244 }
245
246 static void
247 view_populate_pid(struct tinyds_view *view)
248 {
249     pid_t pid;
250     struct wl_client *client = NULL;
251     struct ds_surface *surface = ds_xdg_surface_get_surface(view->xdg_surface);
252
253     if (surface)
254         client = wl_resource_get_client(ds_surface_get_wl_resource(surface));
255     wl_client_get_credentials(client, &pid, NULL, NULL);
256
257     ds_inf("view pid(%u)", pid);
258     view->pid = pid;
259
260     view->effect_type = ds_tizen_effect_get_effect_type(view->server->effect, pid);
261     ds_tizen_effect_unset_effect_type(view->server->effect, pid);
262     ds_inf("view effect_type(%d)", view->effect_type);
263 }
264
265 static void
266 view_handle_xdg_surface_map(struct wl_listener *listener,
267         void *data TINYDS_UNUSED)
268 {
269     struct tinyds_view *view;
270     struct ds_keyboard *keyboard;
271     struct tinyds_keyboard *kbd;
272
273     view = wl_container_of(listener, view, xdg_surface_map);
274     view->mapped = true;
275
276     view_populate_pid(view);
277
278     wl_list_for_each(kbd, &view->server->keyboards, link) {
279         keyboard = ds_input_device_get_keyboard(kbd->dev);
280         if (keyboard != NULL) {
281             ds_seat_keyboard_notify_enter(view->server->seat,
282                     ds_xdg_surface_get_surface(view->xdg_surface),
283                     keyboard->keycodes, keyboard->num_keycodes,
284                     &keyboard->modifiers);
285             return;
286         }
287     }
288 }
289
290 static void
291 view_handle_xdg_surface_unmap(struct wl_listener *listener,
292         void *data TINYDS_UNUSED)
293 {
294     struct tinyds_view *view;
295
296     view = wl_container_of(listener, view, xdg_surface_unmap);
297     view->mapped = false;
298 }
299
300 static void
301 view_handle_xdg_surface_destroy(struct wl_listener *listener,
302         void *data TINYDS_UNUSED) 
303 {
304     struct tinyds_view *view;
305     struct tinyds_server *server;
306
307     view = wl_container_of(listener, view, xdg_surface_destroy);
308     server = view->server;
309
310     wl_list_remove(&view->xdg_surface_destroy.link);
311     wl_list_remove(&view->xdg_surface_map.link);
312     wl_list_remove(&view->xdg_surface_unmap.link);
313     wl_list_remove(&view->surface_commit.link);
314     wl_list_remove(&view->link);
315     free(view);
316
317     draw_server_with_damage(server);
318 }
319
320 static void
321 view_handle_surface_commit(struct wl_listener *listener,
322         void *data TINYDS_UNUSED)
323 {
324     struct tinyds_view *view;
325
326     view = wl_container_of(listener, view, surface_commit);
327     draw_server_with_damage(view->server);
328 }
329
330 static void
331 server_new_xdg_surface(struct wl_listener *listener, void *data)
332 {
333     struct tinyds_server *server;
334     struct tinyds_view *view;
335     struct ds_xdg_surface *xdg_surface;
336
337     server = wl_container_of(listener, server, new_xdg_surface);
338     xdg_surface = data;
339
340     ds_inf("New xdg_surface(%p)", (void *)xdg_surface);
341
342     view = calloc(1, sizeof *view);
343     assert(view);
344
345     view->server = server;
346     view->xdg_surface = xdg_surface;
347
348     view->xdg_surface_map.notify = view_handle_xdg_surface_map;
349     ds_xdg_surface_add_map_listener(xdg_surface,
350             &view->xdg_surface_map);
351
352     view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap;
353     ds_xdg_surface_add_unmap_listener(xdg_surface,
354             &view->xdg_surface_unmap);
355
356     view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy;
357     ds_xdg_surface_add_destroy_listener(xdg_surface,
358             &view->xdg_surface_destroy);
359
360     view->surface_commit.notify = view_handle_surface_commit;
361     ds_surface_add_commit_listener(
362             ds_xdg_surface_get_surface(xdg_surface),
363             &view->surface_commit);
364
365     wl_list_insert(server->views.prev, &view->link);
366
367     view->x = rand() % 1000;
368     view->y = rand() % 500;
369
370     view->pid = 0;
371     view->effect_type = -1;
372
373     ds_inf("view at (%d, %d)", view->x, view->y);
374 }
375
376 static void
377 backend_handle_new_output(struct wl_listener *listener, void *data)
378 {
379     struct tinyds_server *server;
380     struct tinyds_output *output;
381     struct ds_output *ds_output;
382     const struct ds_output_mode *mode;
383
384     server = wl_container_of(listener, server, new_output);
385     ds_output = data;
386
387     ds_inf("New output(%p)", ds_output);
388
389     if (server->output)
390         return;
391
392     mode = ds_output_get_preferred_mode(ds_output);
393     ds_output_set_mode(ds_output, mode);
394
395     output = calloc(1, sizeof *output);
396     if (!output)
397         return;
398
399     output->server = server;
400     output->ds_output = ds_output;
401     output->width = mode->width;
402     output->height = mode->height;
403     output->drawable = true;
404     output->damaged = true;
405
406 #ifdef USE_TDM_BUFFER_QUEUE
407     output_buffer_queue_init(output);
408     output_renderer_init(output);
409 #else
410     output_swapchain_init(output, mode->width, mode->height,
411             DRM_FORMAT_XRGB8888);
412 #endif
413
414     output->output_destroy.notify = output_handle_destroy;
415     ds_output_add_destroy_listener(ds_output, &output->output_destroy);
416
417     output->output_frame.notify = output_handle_frame;
418     ds_output_add_frame_listener(ds_output, &output->output_frame);
419
420     ds_tizen_input_devicemgr_set_output_width_height(server->devicemgr, (uint32_t)output->width, (uint32_t)output->height);
421
422     server->output = output;
423
424     draw_output(output);
425 }
426
427 static bool
428 add_new_dpms(struct tinyds_server *server)
429 {
430     struct tinyds_dpms *dpms;
431
432     dpms = calloc(1, sizeof *dpms);
433     if (!dpms)
434         return false;
435
436     dpms->ds_dpms = ds_tizen_dpms_create(server->display);
437     if (!dpms->ds_dpms)
438         return false;
439
440     dpms->destroy.notify = dpms_handle_destroy;
441     ds_tizen_dpms_add_destroy_listener(dpms->ds_dpms, &dpms->destroy);
442
443     dpms->set_dpms.notify = dpms_handle_set_dpms;
444     ds_tizen_dpms_add_set_dpms_listener(dpms->ds_dpms, &dpms->set_dpms);
445
446     dpms->get_dpms.notify = dpms_handle_get_dpms;
447     ds_tizen_dpms_add_get_dpms_listener(dpms->ds_dpms, &dpms->get_dpms);
448
449     server->dpms = dpms;
450
451     ds_inf("Dpms (%p) added", dpms);
452
453     return true;
454 }
455
456 static void
457 backend_handle_new_input(struct wl_listener *listener, void *data)
458 {
459     struct tinyds_server *server;
460     struct ds_input_device *dev = data;
461     enum ds_input_device_type dev_type;
462
463     server = wl_container_of(listener, server, new_input);
464
465     dev_type = ds_input_device_get_type(dev);
466
467     switch (dev_type) {
468         case DS_INPUT_DEVICE_KEYBOARD:
469             server_add_keyboard(server, dev);
470             server->seat_caps |= WL_SEAT_CAPABILITY_KEYBOARD;
471             break;
472         case DS_INPUT_DEVICE_TOUCH:
473             server_add_touch(server, dev);
474             server->seat_caps |= WL_SEAT_CAPABILITY_TOUCH;
475             break;
476         case DS_INPUT_DEVICE_POINTER:
477             server_add_pointer(server, dev);
478             server->seat_caps |= WL_SEAT_CAPABILITY_POINTER;
479             break;
480         default:
481             ds_err("Unknown type(%d) of ds_input_device", dev_type);
482             break;
483     }
484
485     ds_seat_set_capabilities(server->seat, server->seat_caps);
486 }
487
488 static void
489 devicemgr_add_keymap_data(struct wl_list *list, const char *name, int keycode)
490 {
491     struct ds_tizen_input_devicemgr_keymap_data *data;
492
493     data = calloc(1, sizeof *data);
494     if (!data) {
495         ds_err("Failed to alloc memory\n");
496         return;
497     }
498
499     data->name = strdup(name);
500     data->keycode = keycode;
501
502     wl_list_insert(list, &data->link);
503 }
504
505 static void
506 devicemgr_remove_keymap_data(struct wl_list *list, int keycode)
507 {
508     struct ds_tizen_input_devicemgr_keymap_data *data, *tmp;
509
510     wl_list_for_each_safe(data, tmp, list, link) {
511         if (data->keycode == keycode) {
512             wl_list_remove(&data->link);
513             free(data);
514         }
515     }
516 }
517
518 static void
519 devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr)
520 {
521     struct wl_list keymap_list;
522     bool res;
523
524     wl_list_init(&keymap_list);
525
526     devicemgr_add_keymap_data(&keymap_list, "XF86VolumeRaise", 455);
527     devicemgr_add_keymap_data(&keymap_list, "XF86VolumeLower", 456);
528     devicemgr_add_keymap_data(&keymap_list, "XF86LightOn", 457);
529     devicemgr_add_keymap_data(&keymap_list, "XF86LightOff", 458);
530
531     res = ds_tizen_input_devicemgr_set_keymap_list(devicemgr, &keymap_list);
532     if (!res)
533         ds_inf("Failed to set keymap");
534
535     devicemgr_remove_keymap_data(&keymap_list, 455);
536     devicemgr_remove_keymap_data(&keymap_list, 456);
537     devicemgr_remove_keymap_data(&keymap_list, 457);
538     devicemgr_remove_keymap_data(&keymap_list, 458);
539 }
540
541 static void
542 devicemgr_handle_pointer_warp(struct wl_listener *listener, void *data)
543 {
544     struct tinyds_server *server;
545     struct tinyds_pointer *pointer;
546     struct ds_tizen_input_devicemgr_event_pointer_warp *event = data;
547     double sx = 0.f, sy = 0.f;
548     struct tinyds_view *view = NULL;
549
550     server = wl_container_of(listener, server, pointer_warp);
551
552     ds_inf("Pointer warp: surface(%p) x(%.2f) y(%.2f)", event->surface,
553             event->x, event->y);
554
555     wl_list_for_each(pointer, &server->pointers, link){
556         if (!pointer->focused_view) continue;
557         view = pointer->focused_view;
558     }
559     if (!view) return;
560
561     if (event->surface != ds_xdg_surface_get_surface(view->xdg_surface)) {
562         ds_inf("Pointer is not on the requested surface");
563         return;
564     }
565
566     server->output_x = view->x + (event->x * server->output->width);
567     server->output_y = view->y + (event->y * server->output->height);
568
569     server_view_at(server, server->output_x, server->output_y, &sx, &sy);
570
571     ds_inf("notify motion: sx:%.2f sy:%.2f, output_x:%.1f, output_y:%.1f",
572             sx, sy, server->output_x, server->output_y);
573
574     ds_seat_pointer_notify_motion(server->seat,
575             event->time_msec, sx, sy);
576 }
577
578 static void
579 devicemgr_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
580 {
581     struct tinyds_server *server =
582         wl_container_of(listener, server, devicemgr_destroy);
583
584     wl_list_remove(&server->devicemgr_destroy.link);
585     wl_list_remove(&server->pointer_warp.link);
586
587     server->devicemgr = NULL;
588 }
589
590 static void
591 launch_effect_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
592 {
593     struct tinyds_server *server =
594         wl_container_of(listener, server, effect_destroy);
595
596     wl_list_remove(&server->effect_destroy.link);
597     wl_list_remove(&server->effect_type_set.link);
598     wl_list_remove(&server->effect_type_unset.link);
599     wl_list_remove(&server->new_splash.link);
600
601     server->effect = NULL;
602 }
603
604 static void
605 launch_effect_handle_type_set(struct wl_listener *listener, void *data)
606 {
607     struct tinyds_server *server;
608     struct ds_tizen_effect_event_type_set *event = data;
609     struct tinyds_view *view = NULL;
610     bool existing = false;
611
612     server = wl_container_of(listener, server, effect_type_set);
613
614     ds_inf("Launch effect. type_set: pid(%u) type:%s", event->pid, (event->effect_type == 1) ? "depth-in" : "launch");
615
616     wl_list_for_each(view, &server->views, link) {
617         if (view->pid == event->pid) {
618             view->effect_type = event->effect_type;
619             ds_inf("Launch effect. existing pid");
620             existing = true;
621         }
622     }
623     if (existing) {
624         ds_tizen_effect_unset_effect_type(server->effect, event->pid);
625     } else {
626         ds_tizen_effect_set_effect_type(server->effect, event->pid, event->effect_type);
627     }
628 }
629
630 static void
631 launch_effect_handle_type_unset(struct wl_listener *listener, void *data)
632 {
633     struct tinyds_server *server;
634     struct ds_tizen_effect_event_type_unset *event = data;
635     struct tinyds_view *view = NULL;
636
637     server = wl_container_of(listener, server, effect_type_unset);
638
639     ds_inf("Launch effect. type_unset: pid(%u)", event->pid);
640
641     wl_list_for_each(view, &server->views, link) {
642         if (view->pid == event->pid) {
643             view->effect_type = -1;
644             ds_inf("Launch effect. pid found");
645         }
646     }
647     ds_tizen_effect_unset_effect_type(server->effect, event->pid);
648 }
649
650 static void
651 launch_splash_handle_owner(struct wl_listener *listener, void *data)
652 {
653     struct tinyds_server *server;
654     struct ds_tizen_splash_event_owner *event = data;
655     struct tinyds_view *view = NULL;
656
657     server = wl_container_of(listener, server, splash_owner);
658
659     ds_inf("Splash owner. pid(%u)", event->pid);
660
661     wl_list_for_each(view, &server->views, link) {
662         if (view->pid == event->pid) {
663             if (event->pid == ds_tizen_splash_get_pid(server->splash))
664                 ;//
665             else {
666                 ds_tizen_splash_set_pid(server->splash, event->pid);
667             }
668         }
669     }
670 }
671
672 static void
673 launch_effect_handle_new_splash(struct wl_listener *listener, void *data)
674 {
675     struct tinyds_server *server;
676     struct ds_tizen_effect_event_new_splash *event = data;
677     struct tinyds_view *view = NULL;
678
679     server = wl_container_of(listener, server, new_splash);
680
681     ds_inf("Launch new splash. splash(%p)", event->splash);
682     if (!event->splash) return;
683
684     server->splash = event->splash;
685
686     // new view for "Launchscreen"
687     view = calloc(1, sizeof *view);
688     assert(view);
689     wl_list_insert(server->views.prev, &view->link);
690     view->pid = ds_tizen_splash_get_pid(event->splash);
691
692     server->splash_owner.notify = launch_splash_handle_owner;
693     ds_tizen_splash_add_owner_listener(server->splash,
694             &server->splash_owner);
695 }
696
697 static bool
698 init_server(struct tinyds_server *server, struct wl_display *display)
699 {
700     server->display = display;
701
702     wl_list_init(&server->views);
703
704     if (wl_display_init_shm(display) != 0)
705         return false;
706
707     server->backend = ds_tdm_backend_create(display);
708     if (!server->backend)
709         return false;
710
711     server->input_backend = ds_libinput_backend_create(display);
712     if (!server->input_backend) {
713         ds_backend_destroy(server->backend);
714         return false;
715     }
716
717     server->new_output.notify = backend_handle_new_output;
718     ds_backend_add_new_output_listener(server->backend,
719             &server->new_output);
720
721     wl_list_init(&server->keyboards);
722     wl_list_init(&server->pointers);
723     server->new_input.notify = backend_handle_new_input;
724     ds_backend_add_new_input_listener(server->input_backend, &server->new_input);
725
726     server->compositor = ds_compositor_create(display);
727     if (!server->compositor)
728         goto err;
729
730     server->tbm_server = ds_tbm_server_create(display);
731     if (!server->tbm_server)
732         goto err;
733
734     server->xdg_shell = ds_xdg_shell_create(display);
735     if (!server->xdg_shell)
736         goto err;
737
738     server->new_xdg_surface.notify = server_new_xdg_surface;
739     ds_xdg_shell_add_new_surface_listener(server->xdg_shell,
740             &server->new_xdg_surface);
741
742     if (!add_new_dpms(server))
743         goto err;
744
745     server->seat = ds_seat_create(display, "seat0" /* arbitrary name */);
746     if (!server->seat)
747         goto err;
748     server->seat_caps = 0;
749
750     server->devicemgr = ds_tizen_input_devicemgr_create(
751             server->input_backend, server->seat);
752     if (!server->devicemgr) {
753         goto err;
754     }
755
756     devicemgr_set_keymap(server->devicemgr);
757
758     server->devicemgr_destroy.notify = devicemgr_handle_destroy;
759     ds_tizen_input_devicemgr_add_destroy_listener(server->devicemgr,
760             &server->devicemgr_destroy);
761
762     server->pointer_warp.notify = devicemgr_handle_pointer_warp;
763     ds_tizen_input_devicemgr_add_pointer_warp_listener(server->devicemgr,
764             &server->pointer_warp);
765
766     server->effect = ds_tizen_effect_create(display);
767     if (!server->effect) {
768         goto err;
769     }
770
771     server->effect_destroy.notify = launch_effect_handle_destroy;
772     ds_tizen_effect_add_destroy_listener(server->effect,
773             &server->effect_destroy);
774
775     server->effect_type_set.notify = launch_effect_handle_type_set;
776     ds_tizen_effect_add_type_set_listener(server->effect,
777             &server->effect_type_set);
778
779     server->effect_type_unset.notify = launch_effect_handle_type_unset;
780     ds_tizen_effect_add_type_unset_listener(server->effect,
781             &server->effect_type_unset);
782
783     server->new_splash.notify = launch_effect_handle_new_splash;
784     ds_tizen_effect_add_new_splash_listener(server->effect,
785             &server->new_splash);
786
787     return true;
788
789 err:
790     ds_backend_destroy(server->backend);
791     ds_backend_destroy(server->input_backend);
792
793     return false;
794 }
795
796 static void
797 output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
798 {
799     struct tinyds_output *output =
800         wl_container_of(listener, output, output_destroy);
801
802     wl_list_remove(&output->output_destroy.link);
803     wl_list_remove(&output->output_frame.link);
804
805     if (output->front_buffer)
806         ds_buffer_unlock(output->front_buffer);
807
808 #ifdef USE_TDM_BUFFER_QUEUE
809     fini_renderer(&output->renderer);
810 #else
811     if (output->swapchain)
812         ds_swapchain_destroy(output->swapchain);
813
814     if (output->allocator)
815         ds_allocator_destroy(output->allocator);
816 #endif
817
818     wl_display_terminate(output->server->display);
819
820     output->server->output = NULL;
821
822     free(output);
823 }
824
825 static void
826 output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED)
827 {
828     struct tinyds_output *output =
829         wl_container_of(listener, output, output_frame);
830
831     output->drawable = true;
832     draw_output(output);
833 }
834
835 static void
836 draw_server_with_damage(struct tinyds_server *server)
837 {
838     server->output->damaged = true;
839     draw_output(server->output);
840 }
841
842 #ifdef USE_TDM_BUFFER_QUEUE
843 static void
844 output_handle_buffer_queue_acquirable(struct wl_listener *listener,
845         void *data TINYDS_UNUSED)
846 {
847     struct tinyds_output *output;
848     struct ds_buffer *buffer;
849
850     output = wl_container_of(listener, output, buffer_queue_acquirable);
851
852     buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue);
853     assert(buffer);
854
855     output_swap_buffer(output, buffer);
856 }
857
858 static void
859 output_buffer_queue_init(struct tinyds_output *output)
860 {
861     struct ds_tdm_output *tdm_output;
862
863     tdm_output = ds_tdm_output_from_output(output->ds_output);
864     assert(tdm_output);
865
866     output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output);
867     assert(output->buffer_queue);
868
869     output->buffer_queue_acquirable.notify =
870         output_handle_buffer_queue_acquirable;
871     ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue,
872             &output->buffer_queue_acquirable);
873 }
874
875 static void
876 output_renderer_init(struct tinyds_output *output)
877 {
878     init_renderer(&output->renderer);
879
880     renderer_set_surface_queue(&output->renderer,
881             ds_tdm_buffer_queue_get_native_queue(output->buffer_queue));
882
883     renderer_set_bg_color(&output->renderer, 80, 80, 80);
884 }
885
886 static void
887 output_draw_with_renderer(struct tinyds_output *output)
888 {
889     struct tinyds_view *view;
890
891     ds_dbg(">> BEGIN UPDATE TEXTURES");
892
893     wl_list_for_each(view, &output->server->views, link) {
894         struct ds_buffer *ds_buffer;
895         struct ds_tbm_client_buffer *tbm_buffer;
896         tbm_surface_h surface;
897
898         if (!view->mapped)
899             continue;
900
901         ds_buffer = ds_surface_get_buffer(
902                 ds_xdg_surface_get_surface(view->xdg_surface));
903         assert(ds_buffer);
904
905         tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer);
906         assert(tbm_buffer);
907
908         surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer);
909
910         renderer_add_texture(&output->renderer, surface, view->x, view->y);
911
912         view_send_frame_done(view);
913     }
914
915     ds_dbg("<< END UPDATE TEXTURES");
916
917     renderer_draw(&output->renderer);
918
919 }
920 #else
921 static void
922 output_swapchain_init(struct tinyds_output *output,
923         int width, int height, uint32_t format);
924
925 {
926     output->allocator = ds_tbm_allocator_create();
927     assert(output->allocator);
928
929     output->swapchain = ds_swapchain_create(output->allocator,
930             width, height, format);
931     assert(output->swapchain);
932 }
933
934 static void
935 output_draw_with_swapchain(struct tinyds_output *output)
936 {
937     struct tinyds_view *view;
938     struct ds_buffer *output_buffer;
939     pixman_image_t *output_image;
940
941     output_buffer = ds_swapchain_acquire(output->swapchain, NULL);
942     if (!output_buffer)
943         return;
944
945     output_image = pixman_image_from_buffer(output_buffer,
946             DS_BUFFER_DATA_PTR_ACCESS_WRITE);
947     if (!output_image) {
948         ds_buffer_unlock(output_buffer);
949         return;
950     }
951
952     pixman_image_fill_color(output_image, 80, 80, 80);
953
954     wl_list_for_each(view, &output->server->views, link) {
955         if (!view->mapped)
956             continue;
957         draw_view(view, output_image);
958     }
959     pixman_image_unref(output_image);
960
961     output_swap_buffer(output, output_buffer);
962 }
963
964 static void
965 draw_view(struct tinyds_view *view, pixman_image_t *dst_image)
966 {
967     struct ds_buffer *buffer;
968     pixman_image_t *src_image;
969
970     buffer = ds_surface_get_buffer(
971             ds_xdg_surface_get_surface(view->xdg_surface));
972     if (!buffer)
973         return;
974
975     src_image = pixman_image_from_buffer(buffer,
976             DS_BUFFER_DATA_PTR_ACCESS_READ);
977     pixman_image_composite32(PIXMAN_OP_OVER,
978             src_image,
979             NULL,
980             dst_image,
981             0, 0, 0, 0,
982             view->x, view->y,
983             pixman_image_get_width(src_image),
984             pixman_image_get_height(src_image));
985     pixman_image_unref(src_image);
986
987     view_send_frame_done(view);
988 }
989 #endif
990
991 static void
992 draw_output(struct tinyds_output *output)
993 {
994
995     if (!output->drawable || !output->damaged)
996         return;
997
998 #ifdef USE_TDM_BUFFER_QUEUE
999     output_draw_with_renderer(output);
1000 #else
1001     output_draw_with_swapchain(output);
1002 #endif
1003
1004     output->drawable = false;
1005     output->damaged = false;
1006 }
1007
1008 static void
1009 output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer)
1010 {
1011     ds_output_attach_buffer(output->ds_output, buffer);
1012     ds_output_commit(output->ds_output);
1013
1014     if (output->front_buffer)
1015         ds_buffer_unlock(output->front_buffer);
1016     output->front_buffer = buffer;
1017 }
1018
1019 static void
1020 view_send_frame_done(struct tinyds_view *view)
1021 {
1022     struct timespec now;
1023     clock_gettime(CLOCK_MONOTONIC, &now);
1024     ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface),
1025             &now);
1026 }
1027
1028 static int
1029 server_dispatch_stdin(int fd, uint32_t mask, void *data)
1030 {
1031     struct tinyds_server *server = data;
1032
1033     wl_display_terminate(server->display);
1034
1035     return 1;
1036 }
1037
1038 static void
1039 dpms_handle_destroy(struct wl_listener *listener, void *data)
1040 {
1041     struct tinyds_dpms *dpms;
1042
1043     dpms = wl_container_of(listener, dpms, destroy);
1044
1045     ds_inf("Dpms(%p) destroyed", dpms);
1046
1047     wl_list_remove(&dpms->destroy.link);
1048     wl_list_remove(&dpms->set_dpms.link);
1049     wl_list_remove(&dpms->get_dpms.link);
1050
1051     free(dpms);
1052 }
1053
1054 static void
1055 dpms_handle_set_dpms(struct wl_listener *listener, void *data)
1056 {
1057     struct tinyds_dpms *dpms;
1058     struct ds_tizen_dpms_event *event = data;
1059
1060     dpms = wl_container_of(listener, dpms, set_dpms);
1061
1062     ds_inf("Dpms(%p) set dpms : %d", dpms, event->mode);
1063
1064     //To do
1065     //set dpms mode to output
1066     ds_tizen_dpms_send_set_result(dpms->ds_dpms, event->mode,
1067         DS_TIZEN_DPMS_ERROR_NONE);
1068 }
1069
1070 static void
1071 dpms_handle_get_dpms(struct wl_listener *listener, void *data)
1072 {
1073     struct tinyds_dpms *dpms;
1074
1075     dpms = wl_container_of(listener, dpms, get_dpms);
1076
1077     ds_inf("Dpms(%p) get dpms", dpms);
1078
1079     //To do
1080     //get dpms mode from output
1081     ds_tizen_dpms_send_get_result(dpms->ds_dpms, DS_TIZEN_DPMS_MODE_ON,
1082         DS_TIZEN_DPMS_ERROR_NONE);
1083 }
1084
1085 static void
1086 keyboard_handle_device_destroy(struct wl_listener *listener, void *data)
1087 {
1088     struct tinyds_keyboard *kbd;
1089
1090     kbd = wl_container_of(listener, kbd, destroy);
1091
1092     ds_inf("Keyboard(%p) destroyed", kbd);
1093
1094     wl_list_remove(&kbd->destroy.link);
1095     wl_list_remove(&kbd->key.link);
1096     wl_list_remove(&kbd->link);
1097
1098     free(kbd);
1099 }
1100
1101 static bool
1102 server_handle_keybinding(struct tinyds_server *server, xkb_keysym_t sym)
1103 {
1104     switch (sym) {
1105         case XKB_KEY_BackSpace:
1106             wl_display_terminate(server->display);
1107             break;
1108         default:
1109             return false;
1110     }
1111
1112     return true;
1113 }
1114
1115 static void
1116 keyboard_handle_key(struct wl_listener *listener, void *data)
1117 {
1118     struct tinyds_keyboard *kbd;
1119     struct ds_event_keyboard_key *event = data;
1120     struct ds_keyboard *ds_keyboard;
1121     struct xkb_state *xkb_state;
1122     const xkb_keysym_t *syms;
1123     int nsyms;
1124     bool handled = false;
1125
1126     kbd = wl_container_of(listener, kbd, key);
1127
1128     ds_inf("Keyboard(%p) event key: keycode(%d), state(%d), time_msec(%d), "
1129             "update_state(%d)", kbd->dev,
1130             event->keycode, event->state, event->time_msec,
1131             event->update_state);
1132
1133     ds_keyboard = ds_input_device_get_keyboard(kbd->dev);
1134
1135     if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1136         xkb_state = ds_keyboard_get_xkb_state(ds_keyboard);
1137         if (xkb_state) {
1138             nsyms = xkb_state_key_get_syms(xkb_state, event->keycode + 8,
1139                     &syms);
1140             for (int i = 0; i < nsyms; i++) {
1141                 handled = server_handle_keybinding(kbd->server, syms[i]);
1142             }
1143         }
1144     }
1145
1146     if (!handled) {
1147         ds_seat_keyboard_notify_key(kbd->server->seat, event->time_msec,
1148                 event->keycode, event->state);
1149     }
1150 }
1151
1152 static void
1153 server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev)
1154 {
1155     struct tinyds_keyboard *kbd;
1156     struct xkb_context *context;
1157     struct xkb_keymap *keymap;
1158
1159     kbd = calloc(1, sizeof *kbd);
1160     assert(kbd);
1161
1162     kbd->dev = dev;
1163     kbd->server = server;
1164
1165     context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
1166     keymap = xkb_keymap_new_from_names(context, NULL,
1167             XKB_KEYMAP_COMPILE_NO_FLAGS);
1168
1169     if (!keymap) {
1170         ds_err("Failed to compile keymap");
1171         xkb_context_unref(context);
1172     }
1173
1174     ds_keyboard_set_keymap(ds_input_device_get_keyboard(dev), keymap);
1175
1176     xkb_keymap_unref(keymap);
1177     xkb_context_unref(context);
1178
1179     kbd->destroy.notify = keyboard_handle_device_destroy;
1180     ds_input_device_add_destroy_listener(dev, &kbd->destroy);
1181
1182     kbd->key.notify = keyboard_handle_key;
1183     ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key);
1184
1185     wl_list_insert(&server->keyboards, &kbd->link);
1186
1187     ds_inf("Keyboard(%p) added", kbd);
1188 }
1189
1190 static struct tinyds_view *
1191 server_view_at(struct tinyds_server *server, double lx, double ly,
1192         double *sx, double *sy)
1193 {
1194     struct tinyds_view *view;
1195     struct ds_surface *surface;
1196     struct ds_buffer *buffer;
1197     int x, y, w = 0, h = 0;
1198
1199     wl_list_for_each(view, &server->views, link) {
1200         surface = ds_xdg_surface_get_surface(view->xdg_surface);
1201         buffer = ds_surface_get_buffer(surface);
1202         ds_buffer_get_size(buffer, &w, &h);
1203
1204         x = view->x;
1205         y = view->y;
1206
1207         if (lx >= x && lx <= x + w && ly >= y && ly <= y + h) {
1208             *sx = lx - x;
1209             *sy = ly - y;
1210
1211             return view;
1212         }
1213     }
1214
1215     return NULL;
1216 }
1217
1218 static void
1219 touch_handle_device_destroy(struct wl_listener *listener, void *data)
1220 {
1221     struct tinyds_touch *touch;
1222
1223     touch = wl_container_of(listener, touch, destroy);
1224
1225     ds_inf("Touch(%p) destroyed", touch);
1226
1227     wl_list_remove(&touch->destroy.link);
1228     wl_list_remove(&touch->down.link);
1229     wl_list_remove(&touch->up.link);
1230     wl_list_remove(&touch->motion.link);
1231
1232     free(touch);
1233 }
1234
1235 static void
1236 touch_handle_down(struct wl_listener *listener, void *data)
1237 {
1238     struct ds_event_touch_down *event = data;
1239     struct tinyds_touch *touch;
1240     struct tinyds_view *view;
1241     struct tinyds_server *server;
1242     double sx = 0.f, sy = 0.f;
1243
1244     touch = wl_container_of(listener, touch, down);
1245
1246     server = touch->server;
1247     server->output_x = event->x * server->output->width;
1248     server->output_y = event->y * server->output->height;
1249
1250     ds_inf("Touch(%p) event down: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1251             touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1252
1253     view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1254
1255     if (view) {
1256         ds_seat_touch_notify_down(touch->server->seat, ds_xdg_surface_get_surface(view->xdg_surface),
1257                 event->time_msec, event->id, sx, sy);
1258     }
1259 }
1260
1261 static void
1262 touch_handle_up(struct wl_listener *listener, void *data)
1263 {
1264     struct ds_event_touch_up *event = data;
1265     struct tinyds_touch *touch;
1266
1267     touch = wl_container_of(listener, touch, up);
1268
1269     ds_inf("Touch(%p) event up: id(%d) time_msec(%d)",
1270             touch->dev, event->id, event->time_msec);
1271
1272     ds_seat_touch_notify_up(touch->server->seat, event->time_msec, event->id);
1273 }
1274
1275 static void
1276 touch_handle_motion(struct wl_listener *listener, void *data)
1277 {
1278     struct ds_event_touch_motion *event = data;
1279     struct tinyds_touch *touch;
1280     struct tinyds_view *view;
1281     struct tinyds_server *server;
1282     double sx = 0.f, sy = 0.f;
1283
1284     touch = wl_container_of(listener, touch, motion);
1285
1286     server = touch->server;
1287     server->output_x = event->x * server->output->width;
1288     server->output_y = event->y * server->output->height;
1289
1290     ds_inf("Touch(%p) event motion: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1291             touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1292
1293     view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1294
1295     if (view) {
1296         ds_seat_touch_notify_motion(server->seat, event->time_msec,
1297                 event->id, sx, sy);
1298     }
1299 }
1300
1301 static void
1302 server_add_touch(struct tinyds_server *server, struct ds_input_device *dev)
1303 {
1304     struct tinyds_touch *touch;
1305
1306     touch = calloc(1, sizeof *touch);
1307     assert(touch);
1308
1309     touch->dev = dev;
1310     touch->server = server;
1311
1312     touch->destroy.notify = touch_handle_device_destroy;
1313     ds_input_device_add_destroy_listener(dev, &touch->destroy);
1314
1315     touch->down.notify = touch_handle_down;
1316     ds_touch_add_down_listener(ds_input_device_get_touch(dev), &touch->down);
1317
1318     touch->up.notify = touch_handle_up;
1319     ds_touch_add_up_listener(ds_input_device_get_touch(dev), &touch->up);
1320
1321     touch->motion.notify = touch_handle_motion;
1322     ds_touch_add_motion_listener(ds_input_device_get_touch(dev), &touch->motion);
1323
1324     ds_inf("Touch(%p) added", touch);
1325 }
1326
1327 static void
1328 pointer_handle_device_destroy(struct wl_listener *listener, void *data)
1329 {
1330     struct tinyds_pointer *pointer;
1331
1332     pointer = wl_container_of(listener, pointer, destroy);
1333
1334     ds_inf("Pointer(%p) destroyed", pointer);
1335
1336     wl_list_remove(&pointer->destroy.link);
1337     wl_list_remove(&pointer->motion.link);
1338     wl_list_remove(&pointer->button.link);
1339     wl_list_remove(&pointer->frame.link);
1340     wl_list_remove(&pointer->link);
1341
1342     free(pointer);
1343 }
1344
1345 static void
1346 pointer_handle_motion(struct wl_listener *listener, void *data)
1347 {
1348     struct tinyds_pointer *pointer;
1349     struct ds_event_pointer_motion *event = data;
1350     struct tinyds_view *view;
1351     struct tinyds_server *server;
1352     int ow = 0, oh = 0;
1353     double sx, sy;
1354
1355     pointer = wl_container_of(listener, pointer, motion);
1356
1357     server = pointer->server;
1358     if (server->output) {
1359         ow = server->output->width;
1360         oh = server->output->height;
1361     }
1362
1363     if (server->output_x + event->delta_x >= ow)
1364         server->output_x = ow;
1365     else if(server->output_x + event->delta_x <= 0.f)
1366         server->output_x = 0.f;
1367     else
1368         server->output_x = server->output_x + event->delta_x ;
1369     if (server->output_y + event->delta_y >= oh)
1370         server->output_y = oh;
1371     else if(server->output_y + event->delta_y <= 0.f)
1372         server->output_y = 0.f;
1373     else
1374         server->output_y = server->output_y + event->delta_y ;
1375
1376     ds_inf("Pointer(%p) motion: (delta_x %.1f delta_y %.1f) output_x %.1f output_y %.1f",
1377             pointer, event->delta_x, event->delta_y, server->output_x, server->output_y);
1378
1379     view = server_view_at(pointer->server, server->output_x, server->output_y, &sx, &sy);
1380
1381     if (pointer->focused_view != view) {
1382         if (pointer->focused_view) {
1383             ds_inf("Clear pointer focus from view(%p)", pointer->focused_view);
1384             ds_seat_pointer_notify_clear_focus(pointer->server->seat);
1385             pointer->focused_view = NULL;
1386         }
1387
1388         if (view) {
1389             ds_inf("Set pointer focus to view(%p)", view);
1390             ds_seat_pointer_notify_enter(pointer->server->seat,
1391                     ds_xdg_surface_get_surface(view->xdg_surface), sx, sy);
1392             pointer->focused_view = view;
1393         }
1394     }
1395
1396     if (view) {
1397         ds_seat_pointer_notify_motion(pointer->server->seat,
1398                 event->time_msec, sx, sy);
1399     }
1400 }
1401
1402 static void
1403 pointer_handle_button(struct wl_listener *listener, void *data)
1404 {
1405     struct tinyds_pointer *pointer;
1406     struct ds_event_pointer_button *event = data;
1407
1408     pointer = wl_container_of(listener, pointer, button);
1409
1410     ds_inf("Pointer(%p) button(%d): state(%s) time(%d)",
1411             pointer, event->button,
1412             (event->state == DS_BUTTON_PRESSED) ? "Pressed" : "Released",
1413             event->time_msec);
1414
1415     ds_seat_pointer_notify_button(pointer->server->seat, event->time_msec, event->button, event->state);
1416 }
1417
1418 static void
1419 pointer_handle_frame(struct wl_listener *listener, void *data)
1420 {
1421     struct tinyds_pointer *pointer;
1422
1423     pointer = wl_container_of(listener, pointer, frame);
1424
1425     ds_inf("Pointer(%p) frame", pointer);
1426     ds_seat_pointer_notify_frame(pointer->server->seat);
1427 }
1428
1429 static void
1430 server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev)
1431 {
1432     struct tinyds_pointer *pointer;
1433
1434     pointer = calloc(1, sizeof *pointer);
1435     assert(pointer);
1436
1437     pointer->dev = dev;
1438     pointer->server = server;
1439     server->output_x = 200;
1440     server->output_y = 200;
1441
1442     pointer->destroy.notify = pointer_handle_device_destroy;
1443     ds_input_device_add_destroy_listener(dev, &pointer->destroy);
1444
1445     pointer->motion.notify = pointer_handle_motion;
1446     ds_pointer_add_motion_listener(ds_input_device_get_pointer(dev),
1447             &pointer->motion);
1448
1449     pointer->button.notify = pointer_handle_button;
1450     ds_pointer_add_button_listener(ds_input_device_get_pointer(dev),
1451             &pointer->button);
1452
1453     pointer->frame.notify = pointer_handle_frame;
1454     ds_pointer_add_frame_listener(ds_input_device_get_pointer(dev),
1455             &pointer->frame);
1456
1457     pointer->focused_view = NULL;
1458
1459     wl_list_insert(&server->pointers, &pointer->link);
1460
1461     ds_inf("Pointer(%p) added", pointer);
1462 }