examples: make tinyds-policy files
[platform/core/uifw/libds-tizen.git] / examples / tinyds-tdm.c
1 #include "tinyds-tdm.h"
2
3 struct tinyds_output
4 {
5     struct tinyds_server *server;
6     struct ds_output *ds_output;
7     struct ds_allocator *allocator;
8 #ifdef USE_TDM_BUFFER_QUEUE
9     struct tinyds_renderer renderer;
10     struct ds_tdm_buffer_queue *buffer_queue;
11     struct wl_listener buffer_queue_acquirable;
12 #else
13     struct ds_swapchain *swapchain;
14 #endif
15     struct ds_buffer *front_buffer;
16
17     struct wl_listener output_destroy;
18     struct wl_listener output_frame;
19
20     int width, height;
21
22     struct wl_event_source *idle_commit;
23     bool committable;
24     bool damaged;
25     bool target_updated;
26
27     struct ds_tdm_output_hwc *hwc;
28     struct ds_tdm_output_hwc_window *bg_hwc_window;
29
30 #ifdef USE_CURSOR
31     bool cursor_enabled;
32     struct ds_tdm_output_hwc_window *cursor_hwc_window;
33 #endif
34 };
35
36 struct tinyds_dpms
37 {
38     struct ds_tizen_dpms *ds_dpms;
39     struct tinyds_server *server;
40
41     struct wl_listener destroy;
42     struct wl_listener set_dpms;
43     struct wl_listener get_dpms;
44 };
45
46 struct tinyds_view
47 {
48     struct tinyds_server *server;
49
50     struct tinyds_texture *texture;
51     struct ds_xdg_surface *xdg_surface;
52
53     struct wl_listener xdg_surface_map;
54     struct wl_listener xdg_surface_unmap;
55     struct wl_listener xdg_surface_destroy;
56     struct wl_listener surface_commit;
57     struct wl_list link; // tinyds_server::views
58
59     struct ds_tdm_output_hwc_window *hwc_window;
60
61     int x, y;
62     bool mapped;
63
64     pid_t pid;
65     int effect_type;
66 };
67
68 struct tinyds_pointer
69 {
70     struct ds_input_device *dev;
71     struct tinyds_server *server;
72
73     struct tinyds_view *focused_view;
74
75     struct wl_listener destroy;
76     struct wl_listener motion; //relative
77     struct wl_listener button;
78     struct wl_listener frame;
79     struct wl_list link; //tinyds_server::pointers
80 };
81
82 struct tinyds_keyboard
83 {
84     struct ds_input_device *dev;
85     struct tinyds_server *server;
86
87     struct wl_listener destroy;
88     struct wl_listener key;
89     struct wl_list link; //tinyds_server::keyboards
90 };
91
92 struct tinyds_touch
93 {
94     struct ds_input_device *dev;
95     struct tinyds_server *server;
96
97     struct wl_listener destroy;
98     struct wl_listener down;
99     struct wl_listener up;
100     struct wl_listener motion;
101 };
102
103 struct tinyds_text_input {
104     struct ds_tizen_text_input *input;
105     struct ds_tizen_text_input_manager *text_input_mgr;
106
107     struct tinyds_server *server;
108     struct ds_surface *surface;
109
110     struct wl_list input_methods;
111
112     struct wl_listener mgr_destroy;
113     struct wl_listener new_text_input;
114
115     struct wl_listener destroy;
116     struct wl_listener text_input_activate;
117     struct wl_listener text_input_deactivate;
118     struct wl_listener text_input_reset;
119     struct wl_listener text_input_set_content_type;
120     struct wl_listener text_input_invoke_action;
121     struct wl_listener text_input_commit_state;
122     struct wl_listener text_input_set_preferred_language;
123 };
124
125 struct tinyds_input_method {
126     struct ds_tizen_input_method *input_method;
127     struct ds_tizen_input_method_manager *input_method_mgr;
128
129     struct tinyds_server *server;
130     struct tinyds_text_input *input;
131     struct tinyds_input_method_context *context;
132
133     struct wl_list link;
134
135     struct wl_listener destroy;
136     struct wl_listener mgr_destroy;
137 };
138
139 struct tinyds_input_method_context {
140     struct ds_tizen_input_method_context *context;
141
142     struct tinyds_server *server;
143     struct tinyds_text_input *input;
144     struct tinyds_input_method *input_method;
145
146     struct wl_listener destroy;
147
148     struct wl_listener im_context_commit_string;
149     struct wl_listener im_context_preedit_string;
150     struct wl_listener im_context_preedit_styling;
151     struct wl_listener im_context_preedit_cursor;
152     struct wl_listener im_context_delete_surrounding_text;
153     struct wl_listener im_context_cursor_position;
154     struct wl_listener im_context_modifiers_map;
155     struct wl_listener im_context_keysym;
156     struct wl_listener im_context_grab_keyboard;
157     struct wl_listener im_context_key;
158     struct wl_listener im_context_modifiers;
159     struct wl_listener im_context_language;
160     struct wl_listener im_context_text_direction;
161 };
162
163 struct tinyds_server tinyds;
164
165 static bool init_server(struct tinyds_server *server, struct wl_display *display);
166 static int server_dispatch_stdin(int fd, uint32_t mask, void *data);
167 static void output_handle_destroy(struct wl_listener *listener, void *data);
168 static void output_handle_frame(struct wl_listener *listener, void *data);
169 static void draw_server_with_damage(struct tinyds_server *server);
170 static void draw_output(struct tinyds_output *output);
171 static void output_swap_buffer(struct tinyds_output *output,
172         struct ds_buffer *buffer);
173 static void view_send_frame_done(struct tinyds_view *view);
174 static void output_hwc_init(struct tinyds_output *output);
175 static void output_schedule_commit(struct tinyds_output *output);
176 static void output_commit(struct tinyds_output *output);
177 #ifdef USE_TDM_BUFFER_QUEUE
178 static void output_buffer_queue_init(struct tinyds_output *output);
179 static void output_renderer_init(struct tinyds_output *output);
180 static void output_draw_with_renderer(struct tinyds_output *output);
181 #else
182 static void output_swapchain_init(struct tinyds_output *output,
183         int width, int height, uint32_t format);
184 static void output_draw_with_swapchain(struct tinyds_output *output);
185 static void draw_view(struct tinyds_view *view, pixman_image_t *dst_image);
186 #endif
187 static void dpms_handle_destroy(struct wl_listener *listener, void *data);
188 static void dpms_handle_set_dpms(struct wl_listener *listener, void *data);
189 static void dpms_handle_get_dpms(struct wl_listener *listener, void *data);
190 static void server_add_keyboard(struct tinyds_server *server,
191         struct ds_input_device *dev);
192 static void server_add_pointer(struct tinyds_server *server,
193         struct ds_input_device *dev);
194 static void server_add_touch(struct tinyds_server *server,
195         struct ds_input_device *dev);
196 static struct tinyds_view *
197 server_view_at(struct tinyds_server *server, double lx, double ly,
198         double *sx, double *sy);
199
200 static bool add_new_text_input(struct tinyds_server *server);
201 static bool add_new_input_method(struct tinyds_server *server);
202 static bool add_new_input_method_context(
203         struct tinyds_input_method *input_method,
204         struct tinyds_text_input *text_input);
205
206 static void text_input_mgr_handle_destroy(struct wl_listener *listener,
207         void *data TINYDS_UNUSED);
208 static void text_input_mgr_handle_new_text_input(struct wl_listener *listener,
209         void *data TINYDS_UNUSED);
210
211 static void input_method_mgr_handle_destroy(struct wl_listener *listener,
212         void *data TINYDS_UNUSED);
213
214 static void input_method_handle_destroy(struct wl_listener *listener,
215         void *data TINYDS_UNUSED);
216
217 int
218 main(void)
219 {
220     struct tinyds_server *server = &tinyds;
221     struct wl_display *display;
222     struct wl_event_loop *loop;
223     const char *socket;
224     bool res;
225
226     ds_log_init(DS_INF, NULL);
227
228     display = wl_display_create();
229     assert(display);
230
231     res = init_server(server, display);
232     assert(res);
233
234     socket = wl_display_add_socket_auto(display);
235     assert(socket);
236
237     ds_backend_start(server->backend);
238     ds_backend_start(server->input_backend);
239
240     setenv("WAYLAND_DISPLAY", socket, true);
241
242     ds_inf("Running Wayland compositor on WAYLAND_DISPLAY=%s", socket);
243
244     loop = wl_display_get_event_loop(display);
245     server->stdin_source = wl_event_loop_add_fd(loop, STDIN_FILENO,
246             WL_EVENT_READABLE, server_dispatch_stdin, server);
247
248     wl_display_run(display);
249
250     protocol_trace_enable(false);
251     protocol_trace_fini();
252
253     wl_display_destroy_clients(display);
254     wl_display_destroy(display);
255
256     return 0;
257 }
258
259 static void
260 view_populate_pid(struct tinyds_view *view)
261 {
262     pid_t pid;
263     struct wl_client *client = NULL;
264     struct ds_surface *surface;
265
266     surface = ds_xdg_surface_get_surface(view->xdg_surface);
267     if (!surface)
268         return;
269
270     client = wl_resource_get_client(ds_surface_get_wl_resource(surface));
271     if (!client)
272         return;
273
274     wl_client_get_credentials(client, &pid, NULL, NULL);
275
276     ds_inf("view pid(%u)", pid);
277     view->pid = pid;
278
279     view->effect_type = ds_tizen_launch_effect_get_effect_type(view->server->effect, pid);
280     ds_tizen_launch_effect_unset_effect_type(view->server->effect, pid);
281     ds_inf("view effect_type(%d)", view->effect_type);
282 }
283
284 static void
285 view_handle_xdg_surface_map(struct wl_listener *listener,
286         void *data TINYDS_UNUSED)
287 {
288     struct tinyds_view *view;
289     struct ds_keyboard *keyboard;
290     struct tinyds_keyboard *kbd;
291
292     view = wl_container_of(listener, view, xdg_surface_map);
293     view->mapped = true;
294
295     view_populate_pid(view);
296
297     wl_list_for_each(kbd, &view->server->keyboards, link) {
298         keyboard = ds_input_device_get_keyboard(kbd->dev);
299         if (keyboard != NULL) {
300             ds_seat_keyboard_notify_enter(view->server->seat,
301                     ds_xdg_surface_get_surface(view->xdg_surface),
302                     keyboard->keycodes, keyboard->num_keycodes,
303                     &keyboard->modifiers);
304             return;
305         }
306     }
307 }
308
309 static void
310 view_handle_xdg_surface_unmap(struct wl_listener *listener,
311         void *data TINYDS_UNUSED)
312 {
313     struct tinyds_view *view;
314
315     view = wl_container_of(listener, view, xdg_surface_unmap);
316     view->mapped = false;
317 }
318
319 static void
320 view_handle_xdg_surface_destroy(struct wl_listener *listener,
321         void *data TINYDS_UNUSED) 
322 {
323     struct tinyds_view *view;
324
325     view = wl_container_of(listener, view, xdg_surface_destroy);
326
327     draw_server_with_damage(view->server);
328
329     ds_tdm_output_hwc_window_destroy(view->hwc_window);
330
331     wl_list_remove(&view->xdg_surface_destroy.link);
332     wl_list_remove(&view->xdg_surface_map.link);
333     wl_list_remove(&view->xdg_surface_unmap.link);
334     wl_list_remove(&view->surface_commit.link);
335     wl_list_remove(&view->link);
336     free(view);
337 }
338
339 static void
340 view_handle_surface_commit(struct wl_listener *listener,
341         void *data TINYDS_UNUSED)
342 {
343     struct tinyds_view *view;
344
345     view = wl_container_of(listener, view, surface_commit);
346     draw_server_with_damage(view->server);
347 }
348
349 static void
350 server_new_xdg_surface(struct wl_listener *listener, void *data)
351 {
352     static unsigned int seedx = 1;
353     static unsigned int seedy = 43210;
354     struct tinyds_server *server;
355     struct tinyds_view *view;
356     struct ds_xdg_surface *xdg_surface;
357
358     server = wl_container_of(listener, server, new_xdg_surface);
359     xdg_surface = data;
360
361     ds_inf("New xdg_surface(%p)", (void *)xdg_surface);
362
363     view = calloc(1, sizeof *view);
364     assert(view);
365
366     view->server = server;
367     view->xdg_surface = xdg_surface;
368
369     view->xdg_surface_map.notify = view_handle_xdg_surface_map;
370     ds_xdg_surface_add_map_listener(xdg_surface,
371             &view->xdg_surface_map);
372
373     view->xdg_surface_unmap.notify = view_handle_xdg_surface_unmap;
374     ds_xdg_surface_add_unmap_listener(xdg_surface,
375             &view->xdg_surface_unmap);
376
377     view->xdg_surface_destroy.notify = view_handle_xdg_surface_destroy;
378     ds_xdg_surface_add_destroy_listener(xdg_surface,
379             &view->xdg_surface_destroy);
380
381     view->surface_commit.notify = view_handle_surface_commit;
382     ds_surface_add_commit_listener(
383             ds_xdg_surface_get_surface(xdg_surface),
384             &view->surface_commit);
385
386     view->x = rand_r(&seedx) % 1000;
387     view->y = rand_r(&seedy) % 500;
388
389     view->hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc);
390     assert(view->hwc_window);
391
392     wl_list_insert(server->views.prev, &view->link);
393
394     view->pid = 0;
395     view->effect_type = -1;
396
397     ds_inf("view at (%d, %d)", view->x, view->y);
398 }
399
400 static void
401 backend_handle_new_output(struct wl_listener *listener, void *data)
402 {
403     struct tinyds_server *server;
404     struct tinyds_output *output;
405     struct ds_output *ds_output;
406     const struct ds_output_mode *mode;
407     struct ds_tdm_box src_box;
408
409     server = wl_container_of(listener, server, new_output);
410     ds_output = data;
411
412     ds_inf("New output(%p)", ds_output);
413
414     if (server->output)
415         return;
416
417     mode = ds_output_get_preferred_mode(ds_output);
418     ds_output_set_mode(ds_output, mode);
419
420     output = calloc(1, sizeof *output);
421     if (!output)
422         return;
423
424     output->server = server;
425     output->ds_output = ds_output;
426     output->width = mode->width;
427     output->height = mode->height;
428     output->damaged = true;
429     output->committable = true;
430
431     output_hwc_init(output);
432
433 #ifdef USE_TDM_BUFFER_QUEUE
434     output_buffer_queue_init(output);
435     output_renderer_init(output);
436 #else
437     output_swapchain_init(output, mode->width, mode->height,
438             DRM_FORMAT_XRGB8888);
439 #endif
440
441     output->bg_hwc_window = ds_tdm_output_hwc_window_create(output->hwc);
442     assert(output->bg_hwc_window);
443
444     src_box.x = 0;
445     src_box.y = 0;
446     src_box.width = output->width;
447     src_box.height = output->height;
448
449     ds_tdm_output_hwc_window_set_src_box(output->bg_hwc_window, &src_box);
450     ds_tdm_output_hwc_window_set_position(output->bg_hwc_window, 0, 0);
451     ds_tdm_output_hwc_window_set_dest_size(output->bg_hwc_window, output->width, output->height);
452     ds_tdm_output_hwc_window_set_transform(output->bg_hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
453
454 #ifdef USE_CURSOR
455     output->cursor_enabled = false;
456 #endif
457
458     output->output_destroy.notify = output_handle_destroy;
459     ds_output_add_destroy_listener(ds_output, &output->output_destroy);
460
461     output->output_frame.notify = output_handle_frame;
462     ds_output_add_frame_listener(ds_output, &output->output_frame);
463
464     ds_tizen_input_devicemgr_set_output_width_height(server->devicemgr, (uint32_t)output->width, (uint32_t)output->height);
465
466     server->output = output;
467     server->output_x = (double)(output->width) / 2;
468     server->output_y = (double)(output->height) / 2;
469
470     output_schedule_commit(output);
471 }
472
473 static bool
474 add_new_dpms(struct tinyds_server *server)
475 {
476     struct tinyds_dpms *dpms;
477
478     dpms = calloc(1, sizeof *dpms);
479     if (!dpms)
480         return false;
481
482     dpms->ds_dpms = ds_tizen_dpms_create(server->display);
483     if (!dpms->ds_dpms) {
484         free(dpms);
485         ds_err("Could not create ds_tizen_dpms");
486         return false;
487     }
488
489     dpms->destroy.notify = dpms_handle_destroy;
490     ds_tizen_dpms_add_destroy_listener(dpms->ds_dpms, &dpms->destroy);
491
492     dpms->set_dpms.notify = dpms_handle_set_dpms;
493     ds_tizen_dpms_add_set_dpms_listener(dpms->ds_dpms, &dpms->set_dpms);
494
495     dpms->get_dpms.notify = dpms_handle_get_dpms;
496     ds_tizen_dpms_add_get_dpms_listener(dpms->ds_dpms, &dpms->get_dpms);
497
498     server->dpms = dpms;
499
500     ds_inf("Dpms (%p) added", dpms);
501
502     return true;
503 }
504
505 static void
506 backend_handle_new_input(struct wl_listener *listener, void *data)
507 {
508     struct tinyds_server *server;
509     struct ds_input_device *dev = data;
510     enum ds_input_device_type dev_type;
511
512     server = wl_container_of(listener, server, new_input);
513
514     dev_type = ds_input_device_get_type(dev);
515
516     switch (dev_type) {
517         case DS_INPUT_DEVICE_KEYBOARD:
518             server_add_keyboard(server, dev);
519             server->seat_caps |= WL_SEAT_CAPABILITY_KEYBOARD;
520             break;
521         case DS_INPUT_DEVICE_TOUCH:
522             server_add_touch(server, dev);
523             server->seat_caps |= WL_SEAT_CAPABILITY_TOUCH;
524             break;
525         case DS_INPUT_DEVICE_POINTER:
526             server_add_pointer(server, dev);
527             server->seat_caps |= WL_SEAT_CAPABILITY_POINTER;
528             break;
529         default:
530             ds_err("Unknown type(%d) of ds_input_device", dev_type);
531             break;
532     }
533
534     ds_seat_set_capabilities(server->seat, server->seat_caps);
535 }
536
537 static void
538 devicemgr_add_keymap_data(struct wl_list *list, const char *name, int keycode)
539 {
540     struct ds_tizen_input_devicemgr_keymap_data *data;
541
542     data = calloc(1, sizeof *data);
543     if (!data) {
544         ds_err("Failed to alloc memory");
545         return;
546     }
547
548     data->name = strdup(name);
549     data->keycode = keycode;
550
551     wl_list_insert(list, &data->link);
552 }
553
554 static void
555 devicemgr_cleanup_keymap_list(struct wl_list *list)
556 {
557     struct ds_tizen_input_devicemgr_keymap_data *data, *tmp;
558
559     wl_list_for_each_safe(data, tmp, list, link) {
560         wl_list_remove(&data->link);
561         free(data->name);
562         free(data);
563     }
564 }
565
566 static void
567 devicemgr_set_keymap(struct ds_tizen_input_devicemgr *devicemgr)
568 {
569     struct wl_list keymap_list;
570     bool res;
571
572     wl_list_init(&keymap_list);
573
574     devicemgr_add_keymap_data(&keymap_list, "XF86VolumeRaise", 455);
575     devicemgr_add_keymap_data(&keymap_list, "XF86VolumeLower", 456);
576     devicemgr_add_keymap_data(&keymap_list, "XF86LightOn", 457);
577     devicemgr_add_keymap_data(&keymap_list, "XF86LightOff", 458);
578
579     res = ds_tizen_input_devicemgr_set_keymap_list(devicemgr, &keymap_list);
580     if (!res)
581         ds_inf("Failed to set keymap");
582
583     devicemgr_cleanup_keymap_list(&keymap_list);
584 }
585
586 static void
587 devicemgr_handle_pointer_warp(struct wl_listener *listener, void *data)
588 {
589     struct tinyds_server *server;
590     struct tinyds_pointer *pointer;
591     struct ds_tizen_input_devicemgr_event_pointer_warp *event = data;
592     double sx = 0.f, sy = 0.f;
593     struct tinyds_view *view = NULL;
594
595     server = wl_container_of(listener, server, pointer_warp);
596
597     ds_inf("Pointer warp: surface(%p) x(%.2f) y(%.2f)", event->surface,
598             event->x, event->y);
599
600     wl_list_for_each(pointer, &server->pointers, link){
601         if (!pointer->focused_view) continue;
602         view = pointer->focused_view;
603     }
604     if (!view) return;
605
606     if (event->surface != ds_xdg_surface_get_surface(view->xdg_surface)) {
607         ds_inf("Pointer is not on the requested surface");
608         return;
609     }
610
611     server->output_x = view->x + (event->x * server->output->width);
612     server->output_y = view->y + (event->y * server->output->height);
613
614     server_view_at(server, server->output_x, server->output_y, &sx, &sy);
615
616     ds_inf("notify motion: sx:%.2f sy:%.2f, output_x:%.1f, output_y:%.1f",
617             sx, sy, server->output_x, server->output_y);
618
619     ds_seat_pointer_notify_motion(server->seat,
620             event->time_msec, sx, sy);
621 }
622
623 static void
624 devicemgr_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
625 {
626     struct tinyds_server *server =
627         wl_container_of(listener, server, devicemgr_destroy);
628
629     wl_list_remove(&server->devicemgr_destroy.link);
630     wl_list_remove(&server->pointer_warp.link);
631
632     server->devicemgr = NULL;
633 }
634
635 static void
636 launch_effect_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
637 {
638     struct tinyds_server *server =
639         wl_container_of(listener, server, effect_destroy);
640
641     wl_list_remove(&server->effect_destroy.link);
642     wl_list_remove(&server->effect_type_set.link);
643     wl_list_remove(&server->effect_type_unset.link);
644     wl_list_remove(&server->new_splash.link);
645
646     server->effect = NULL;
647 }
648
649 static void
650 launch_effect_handle_type_set(struct wl_listener *listener, void *data)
651 {
652     struct tinyds_server *server;
653     struct ds_tizen_launch_effect_event_type_set *event = data;
654     struct tinyds_view *view = NULL;
655     bool existing = false;
656
657     server = wl_container_of(listener, server, effect_type_set);
658
659     ds_inf("Launch effect. type_set: pid(%u) type:%s", event->pid, (event->effect_type == 1) ? "depth-in" : "launch");
660
661     wl_list_for_each(view, &server->views, link) {
662         if (view->pid == event->pid) {
663             view->effect_type = event->effect_type;
664             ds_inf("Launch effect. existing pid");
665             existing = true;
666         }
667     }
668     if (existing) {
669         ds_tizen_launch_effect_unset_effect_type(server->effect, event->pid);
670     } else {
671         ds_tizen_launch_effect_set_effect_type(server->effect, event->pid, event->effect_type);
672     }
673 }
674
675 static void
676 launch_effect_handle_type_unset(struct wl_listener *listener, void *data)
677 {
678     struct tinyds_server *server;
679     struct ds_tizen_launch_effect_event_type_unset *event = data;
680     struct tinyds_view *view = NULL;
681
682     server = wl_container_of(listener, server, effect_type_unset);
683
684     ds_inf("Launch effect. type_unset: pid(%u)", event->pid);
685
686     wl_list_for_each(view, &server->views, link) {
687         if (view->pid == event->pid) {
688             view->effect_type = -1;
689             ds_inf("Launch effect. pid found");
690         }
691     }
692     ds_tizen_launch_effect_unset_effect_type(server->effect, event->pid);
693 }
694
695 static void
696 launch_splash_handle_owner(struct wl_listener *listener, void *data)
697 {
698     struct tinyds_server *server;
699     struct ds_tizen_launch_splash_event_owner *event = data;
700     struct tinyds_view *view = NULL;
701
702     server = wl_container_of(listener, server, splash_owner);
703
704     ds_inf("Splash owner. pid(%u)", event->pid);
705
706     wl_list_for_each(view, &server->views, link) {
707         if (view->pid == event->pid) {
708             if (event->pid == ds_tizen_launch_splash_get_pid(server->splash))
709                 ;//
710             else {
711                 ds_tizen_launch_splash_set_pid(server->splash, event->pid);
712             }
713         }
714     }
715 }
716
717 static void
718 launch_effect_handle_new_splash(struct wl_listener *listener, void *data)
719 {
720     struct tinyds_server *server;
721     struct ds_tizen_launch_splash *splash = data;
722     struct tinyds_view *view = NULL;
723
724     server = wl_container_of(listener, server, new_splash);
725
726     ds_inf("Launch new splash. splash(%p)", splash);
727     if (!splash) return;
728
729     server->splash = splash;
730
731     // new view for "Launchscreen"
732     view = calloc(1, sizeof *view);
733     assert(view);
734     wl_list_insert(server->views.prev, &view->link);
735     view->pid = ds_tizen_launch_splash_get_pid(splash);
736
737     server->splash_owner.notify = launch_splash_handle_owner;
738     ds_tizen_launch_splash_add_owner_listener(server->splash,
739             &server->splash_owner);
740 }
741
742 static void
743 policy_free_func(void *data)
744 {
745     struct tinyds_server *server = (struct tinyds_server *)data;
746
747     server->policy = NULL;
748 }
749
750 static bool
751 init_server(struct tinyds_server *server, struct wl_display *display)
752 {
753     server->display = display;
754
755     wl_list_init(&server->views);
756
757     if (wl_display_init_shm(display) != 0)
758         return false;
759
760     server->backend = ds_tdm_backend_create(display);
761     if (!server->backend)
762         return false;
763
764     server->input_backend = ds_libinput_backend_create(display);
765     if (!server->input_backend) {
766         ds_backend_destroy(server->backend);
767         return false;
768     }
769
770     server->new_output.notify = backend_handle_new_output;
771     ds_backend_add_new_output_listener(server->backend,
772             &server->new_output);
773
774     wl_list_init(&server->keyboards);
775     wl_list_init(&server->pointers);
776     server->new_input.notify = backend_handle_new_input;
777     ds_backend_add_new_input_listener(server->input_backend, &server->new_input);
778
779     server->compositor = ds_compositor_create(display);
780     if (!server->compositor)
781         goto err;
782
783     server->tbm_server = ds_tbm_server_create(display);
784     if (!server->tbm_server)
785         goto err;
786
787     server->xdg_shell = ds_xdg_shell_create(display);
788     if (!server->xdg_shell)
789         goto err;
790
791     server->new_xdg_surface.notify = server_new_xdg_surface;
792     ds_xdg_shell_add_new_surface_listener(server->xdg_shell,
793             &server->new_xdg_surface);
794
795     if (!add_new_dpms(server))
796         goto err;
797
798     server->policy = tinyds_policy_init(server->display, policy_free_func, (void *)server);
799     if (!server->policy)
800         goto err;
801
802     server->seat = ds_seat_create(display, "seat0" /* arbitrary name */);
803     if (!server->seat)
804         goto err;
805     server->seat_caps = 0;
806
807     server->devicemgr = ds_tizen_input_devicemgr_create(
808             server->input_backend, server->seat);
809     if (!server->devicemgr) {
810         ds_err("Could not create ds_tizen_input_devicemgr");
811         goto err;
812     }
813
814     devicemgr_set_keymap(server->devicemgr);
815
816     server->devicemgr_destroy.notify = devicemgr_handle_destroy;
817     ds_tizen_input_devicemgr_add_destroy_listener(server->devicemgr,
818             &server->devicemgr_destroy);
819
820     server->pointer_warp.notify = devicemgr_handle_pointer_warp;
821     ds_tizen_input_devicemgr_add_pointer_warp_listener(server->devicemgr,
822             &server->pointer_warp);
823
824     server->effect = ds_tizen_launch_effect_create(display);
825     if (!server->effect) {
826         goto err;
827     }
828
829     server->effect_destroy.notify = launch_effect_handle_destroy;
830     ds_tizen_launch_effect_add_destroy_listener(server->effect,
831             &server->effect_destroy);
832
833     server->effect_type_set.notify = launch_effect_handle_type_set;
834     ds_tizen_launch_effect_add_type_set_listener(server->effect,
835             &server->effect_type_set);
836
837     server->effect_type_unset.notify = launch_effect_handle_type_unset;
838     ds_tizen_launch_effect_add_type_unset_listener(server->effect,
839             &server->effect_type_unset);
840
841     server->new_splash.notify = launch_effect_handle_new_splash;
842     ds_tizen_launch_effect_add_new_splash_listener(server->effect,
843             &server->new_splash);
844
845     if (!add_new_text_input(server))
846         goto err;
847
848     if (!add_new_input_method(server))
849         goto err;
850
851     if (protocol_trace_init(display))
852         protocol_trace_enable(true);
853
854     return true;
855
856 err:
857     ds_backend_destroy(server->backend);
858     ds_backend_destroy(server->input_backend);
859
860     return false;
861 }
862
863 static void
864 output_handle_destroy(struct wl_listener *listener, void *data TINYDS_UNUSED)
865 {
866     struct tinyds_output *output =
867         wl_container_of(listener, output, output_destroy);
868
869     if (output->bg_hwc_window)
870         ds_tdm_output_hwc_window_destroy(output->bg_hwc_window);
871
872     wl_list_remove(&output->output_destroy.link);
873     wl_list_remove(&output->output_frame.link);
874
875     if (output->front_buffer)
876         ds_buffer_unlock(output->front_buffer);
877
878 #ifdef USE_TDM_BUFFER_QUEUE
879     fini_renderer(&output->renderer);
880 #else
881     if (output->swapchain)
882         ds_swapchain_destroy(output->swapchain);
883
884     if (output->allocator)
885         ds_allocator_destroy(output->allocator);
886 #endif
887
888     wl_display_terminate(output->server->display);
889
890     output->server->output = NULL;
891
892     free(output);
893 }
894
895 static void
896 output_commit(struct tinyds_output *output)
897 {
898     uint32_t num_changed = 0;
899     uint32_t num_windows = 0, current_num_windows = 0;
900     struct ds_tdm_output_hwc_window **composited_hwc_windows = NULL;
901     struct ds_tdm_output_hwc_window **changed_hwc_windows = NULL;
902     enum ds_tdm_output_hwc_window_composition composition;
903     struct tinyds_view *view;
904     int i;
905     bool need_target = false;
906     bool fully_obscured = false;
907     struct ds_buffer *ds_buffer;
908     struct ds_tdm_box src_box;
909     int w = 0, h = 0;
910
911     if (!output->committable)
912         return;
913
914     if (!output->damaged && !output->target_updated)
915         return;
916
917     wl_list_for_each_reverse(view, &output->server->views, link) {
918         if (!view->hwc_window)
919             continue;
920
921         ds_buffer = ds_surface_get_buffer(
922                 ds_xdg_surface_get_surface(view->xdg_surface));
923         if (!ds_buffer)
924             continue;
925
926         if (!view->mapped)
927             continue;
928
929         num_windows++;
930
931         ds_buffer_get_size(ds_buffer, &w, &h);
932
933         if ((output->width <= w) && (output->height <= h))
934             fully_obscured = true;
935     }
936
937     if (fully_obscured) {
938         ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window,
939                 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE);
940     } else {
941         ds_tdm_output_hwc_window_set_composition(output->bg_hwc_window,
942                 DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT);
943         num_windows++;
944         need_target = true;
945     }
946
947 #ifdef USE_CURSOR
948     if (output->cursor_hwc_window) {
949         src_box.x = 0;
950         src_box.y = 0;
951         src_box.width = CURSOR_W;
952         src_box.height = CURSOR_H;
953
954         ds_tdm_output_hwc_window_set_src_box(output->cursor_hwc_window, &src_box);
955         ds_tdm_output_hwc_window_set_position(output->cursor_hwc_window, output->server->output_x, output->server->output_y);
956         ds_tdm_output_hwc_window_set_dest_size(output->cursor_hwc_window, CURSOR_W, CURSOR_H);
957         ds_tdm_output_hwc_window_set_transform(output->cursor_hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
958
959         ds_tdm_output_hwc_window_set_composition(output->cursor_hwc_window,
960                     DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT);
961         num_windows++;
962         need_target = true;
963     }
964 #endif
965
966     if (num_windows) {
967         composited_hwc_windows = calloc(num_windows, sizeof *composited_hwc_windows);
968         if (!composited_hwc_windows)
969             return;
970
971         wl_list_for_each_reverse(view, &output->server->views, link) {
972             if (!view->hwc_window)
973                 continue;
974
975             ds_buffer = ds_surface_get_buffer(
976                     ds_xdg_surface_get_surface(view->xdg_surface));
977             if (!ds_buffer)
978                 continue;
979
980             ds_tdm_output_hwc_window_set_buffer(view->hwc_window, ds_buffer);
981
982             ds_buffer_get_size(ds_buffer, &w, &h);
983
984             src_box.x = 0;
985             src_box.y = 0;
986             src_box.width = w;
987             src_box.height = h;
988
989             ds_tdm_output_hwc_window_set_src_box(view->hwc_window, &src_box);
990             ds_tdm_output_hwc_window_set_position(view->hwc_window, view->x, view->y);
991             ds_tdm_output_hwc_window_set_dest_size(view->hwc_window, w, h);
992             ds_tdm_output_hwc_window_set_transform(view->hwc_window, WL_OUTPUT_TRANSFORM_NORMAL);
993
994             if (view->mapped) {
995 #ifdef USE_CURSOR
996                 ds_tdm_output_hwc_window_set_composition(view->hwc_window,
997                         DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT);
998 #endif
999                 ds_tdm_output_hwc_window_set_composition(view->hwc_window,
1000                         DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE);
1001
1002                 composited_hwc_windows[current_num_windows] = view->hwc_window;
1003                 current_num_windows++;
1004             } else {
1005                 ds_tdm_output_hwc_window_set_composition(view->hwc_window,
1006                         DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_NONE);
1007             }
1008         }
1009
1010         if (!fully_obscured) {
1011             composited_hwc_windows[current_num_windows] = output->bg_hwc_window;
1012             current_num_windows++;
1013         }
1014
1015 #ifdef USE_CURSOR
1016         if (output->cursor_hwc_window) {
1017             composited_hwc_windows[current_num_windows] = output->cursor_hwc_window;
1018             current_num_windows++;
1019         }
1020 #endif
1021     }
1022
1023     if (!ds_tdm_output_hwc_validate(output->hwc, composited_hwc_windows,
1024             num_windows, &num_changed)) {
1025         free(composited_hwc_windows);
1026         ds_err("Could not hwc validate");
1027         return;
1028     }
1029
1030     if (composited_hwc_windows)
1031         free(composited_hwc_windows);
1032
1033     if (num_changed > 0) {
1034         changed_hwc_windows = calloc(num_windows, sizeof *changed_hwc_windows);
1035         if (!changed_hwc_windows)
1036             return;
1037
1038         if (!ds_tdm_output_hwc_get_changed_composition(output->hwc, &num_changed,
1039                 changed_hwc_windows)) {
1040             free(changed_hwc_windows);
1041             ds_err("Could not get chaged composition");
1042             return;
1043         }
1044
1045         for (i = 0; i < num_changed; i++) {
1046             composition = ds_tdm_output_hwc_window_get_composition(changed_hwc_windows[i]);
1047             if (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CLIENT) {
1048                 need_target = true;
1049                 break;
1050             }
1051         }
1052     }
1053
1054     if (changed_hwc_windows)
1055         free(changed_hwc_windows);
1056
1057     if (need_target && output->damaged)
1058         draw_output(output);
1059
1060 #ifdef USE_TDM_BUFFER_QUEUE
1061     struct ds_buffer *buffer;
1062
1063     buffer = ds_tdm_buffer_queue_acquire(output->buffer_queue);
1064     if (buffer) {
1065         if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, buffer)) {
1066             ds_err("Could not set hwc client target buffer");
1067             return;
1068         }
1069
1070         output_swap_buffer(output, buffer);
1071     }
1072 #endif
1073
1074     if (!ds_tdm_output_hwc_accept_validation(output->hwc)) {
1075         ds_err("Could not hwc accept validateion");
1076         return;
1077     }
1078
1079     ds_output_commit(output->ds_output);
1080
1081     output->committable = false;
1082     output->damaged = false;
1083     output->target_updated = false;
1084
1085     wl_list_for_each(view, &output->server->views, link) {
1086         enum ds_tdm_output_hwc_window_composition composition;
1087
1088         if (!view->mapped)
1089             continue;
1090
1091         composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
1092         if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
1093             (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
1094             (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
1095             view_send_frame_done(view);
1096     }
1097
1098     ds_dbg("output:%p commit", output);
1099 }
1100
1101 static void
1102 output_handle_frame(struct wl_listener *listener, void *data TINYDS_UNUSED)
1103 {
1104     struct tinyds_output *output =
1105         wl_container_of(listener, output, output_frame);
1106
1107     ds_dbg("output:%p handle frame", output);
1108
1109     output->committable = true;
1110
1111     output_commit(output);
1112 }
1113
1114 static void
1115 draw_server_with_damage(struct tinyds_server *server)
1116 {
1117     server->output->damaged = true;
1118     output_schedule_commit(server->output);
1119 }
1120
1121 static void
1122 output_hwc_init(struct tinyds_output *output)
1123 {
1124     struct ds_tdm_output *tdm_output;
1125
1126     tdm_output = ds_tdm_output_from_output(output->ds_output);
1127     assert(tdm_output);
1128
1129     output->hwc = ds_tdm_output_get_hwc(tdm_output);
1130     assert(output->hwc);
1131
1132     ds_tdm_output_hwc_set_enabled(output->hwc, true);
1133 }
1134
1135 #ifdef USE_TDM_BUFFER_QUEUE
1136 static void
1137 output_handle_buffer_queue_acquirable(struct wl_listener *listener,
1138         void *data TINYDS_UNUSED)
1139 {
1140     struct tinyds_output *output;
1141
1142     output = wl_container_of(listener, output, buffer_queue_acquirable);
1143
1144     output->target_updated = true;
1145     output_schedule_commit(output);
1146 }
1147
1148 static void
1149 output_buffer_queue_init(struct tinyds_output *output)
1150 {
1151     struct ds_tdm_output *tdm_output;
1152
1153     tdm_output = ds_tdm_output_from_output(output->ds_output);
1154     assert(tdm_output);
1155
1156     output->buffer_queue = ds_tdm_output_get_buffer_queue(tdm_output);
1157     assert(output->buffer_queue);
1158
1159     output->buffer_queue_acquirable.notify =
1160         output_handle_buffer_queue_acquirable;
1161     ds_tdm_buffer_queue_add_acquirable_listener(output->buffer_queue,
1162             &output->buffer_queue_acquirable);
1163 }
1164
1165 static void
1166 output_renderer_init(struct tinyds_output *output)
1167 {
1168     init_renderer(&output->renderer);
1169
1170     renderer_set_surface_queue(&output->renderer,
1171             ds_tdm_buffer_queue_get_native_queue(output->buffer_queue));
1172
1173     renderer_set_bg_color(&output->renderer, 80, 80, 80);
1174 }
1175
1176 static void
1177 output_draw_with_renderer(struct tinyds_output *output)
1178 {
1179     struct tinyds_view *view;
1180
1181     ds_dbg(">> BEGIN UPDATE TEXTURES");
1182
1183     wl_list_for_each(view, &output->server->views, link) {
1184         struct ds_buffer *ds_buffer;
1185         struct ds_tbm_client_buffer *tbm_buffer;
1186         tbm_surface_h surface;
1187         enum ds_tdm_output_hwc_window_composition composition;
1188
1189         if (!view->mapped)
1190             continue;
1191
1192         composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
1193         if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
1194             (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
1195             (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
1196             continue;
1197
1198         ds_buffer = ds_surface_get_buffer(
1199                 ds_xdg_surface_get_surface(view->xdg_surface));
1200         if (!ds_buffer)
1201             continue;
1202
1203         tbm_buffer = ds_tbm_client_buffer_from_buffer(ds_buffer);
1204         if (!tbm_buffer)
1205             continue;
1206
1207         surface = ds_tbm_client_buffer_get_tbm_surface(tbm_buffer);
1208         if (!surface)
1209             continue;
1210
1211         renderer_add_texture(&output->renderer, surface, view->x, view->y);
1212
1213         view_send_frame_done(view);
1214     }
1215
1216     ds_dbg("<< END UPDATE TEXTURES");
1217
1218     renderer_draw(&output->renderer);
1219 }
1220 #else
1221 static void
1222 output_swapchain_init(struct tinyds_output *output,
1223         int width, int height, uint32_t format)
1224
1225 {
1226     output->allocator = ds_tbm_allocator_create();
1227     assert(output->allocator);
1228
1229     output->swapchain = ds_swapchain_create(output->allocator,
1230             width, height, format);
1231     assert(output->swapchain);
1232 }
1233
1234 static void
1235 output_draw_with_swapchain(struct tinyds_output *output)
1236 {
1237     struct tinyds_view *view;
1238     struct ds_buffer *output_buffer;
1239     pixman_image_t *output_image;
1240     enum ds_tdm_output_hwc_window_composition composition;
1241
1242     output_buffer = ds_swapchain_acquire(output->swapchain, NULL);
1243     if (!output_buffer)
1244         return;
1245
1246     output_image = pixman_image_from_buffer(output_buffer,
1247             DS_BUFFER_DATA_PTR_ACCESS_WRITE);
1248     if (!output_image) {
1249         ds_buffer_unlock(output_buffer);
1250         return;
1251     }
1252
1253     pixman_image_fill_color(output_image, 80, 80, 80);
1254
1255     wl_list_for_each(view, &output->server->views, link) {
1256         if (!view->mapped)
1257             continue;
1258
1259         composition = ds_tdm_output_hwc_window_get_composition(view->hwc_window);
1260         if ((composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_DEVICE) ||
1261             (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_VIDEO) ||
1262             (composition == DS_TDM_OUTPUT_HWC_WINDOW_COMPOSITION_CURSOR))
1263             continue;
1264
1265         draw_view(view, output_image);
1266     }
1267     pixman_image_unref(output_image);
1268
1269     if (!ds_tdm_output_hwc_set_client_target_buffer(output->hwc, output_buffer)) {
1270         ds_err("Could not set hwc client target buffer");
1271         ds_buffer_unlock(output_buffer);
1272         return;
1273     }
1274
1275     output_swap_buffer(output, output_buffer);
1276 }
1277
1278 static void
1279 draw_view(struct tinyds_view *view, pixman_image_t *dst_image)
1280 {
1281     struct ds_buffer *buffer;
1282     pixman_image_t *src_image;
1283
1284     buffer = ds_surface_get_buffer(
1285             ds_xdg_surface_get_surface(view->xdg_surface));
1286     if (!buffer)
1287         return;
1288
1289     src_image = pixman_image_from_buffer(buffer,
1290             DS_BUFFER_DATA_PTR_ACCESS_READ);
1291     pixman_image_composite32(PIXMAN_OP_OVER,
1292             src_image,
1293             NULL,
1294             dst_image,
1295             0, 0, 0, 0,
1296             view->x, view->y,
1297             pixman_image_get_width(src_image),
1298             pixman_image_get_height(src_image));
1299     pixman_image_unref(src_image);
1300
1301     view_send_frame_done(view);
1302 }
1303 #endif
1304
1305 static void
1306 draw_output(struct tinyds_output *output)
1307 {
1308 #ifdef USE_TDM_BUFFER_QUEUE
1309     output_draw_with_renderer(output);
1310 #else
1311     output_draw_with_swapchain(output);
1312 #endif
1313
1314     ds_dbg("output:%p draw", output);
1315 }
1316
1317 static void
1318 output_swap_buffer(struct tinyds_output *output, struct ds_buffer *buffer)
1319 {
1320     ds_output_attach_buffer(output->ds_output, buffer);
1321
1322     if (output->front_buffer)
1323         ds_buffer_unlock(output->front_buffer);
1324     output->front_buffer = buffer;
1325 }
1326
1327 static void
1328 view_send_frame_done(struct tinyds_view *view)
1329 {
1330     struct timespec now;
1331     clock_gettime(CLOCK_MONOTONIC, &now);
1332     ds_surface_send_frame_done(ds_xdg_surface_get_surface(view->xdg_surface),
1333             &now);
1334 }
1335
1336 static int
1337 server_dispatch_stdin(int fd, uint32_t mask, void *data)
1338 {
1339     struct tinyds_server *server = data;
1340
1341     wl_display_terminate(server->display);
1342
1343     return 1;
1344 }
1345
1346 static void
1347 dpms_handle_destroy(struct wl_listener *listener, void *data)
1348 {
1349     struct tinyds_dpms *dpms;
1350
1351     dpms = wl_container_of(listener, dpms, destroy);
1352
1353     ds_inf("Dpms(%p) destroyed", dpms);
1354
1355     wl_list_remove(&dpms->destroy.link);
1356     wl_list_remove(&dpms->set_dpms.link);
1357     wl_list_remove(&dpms->get_dpms.link);
1358
1359     free(dpms);
1360 }
1361
1362 static void
1363 dpms_handle_set_dpms(struct wl_listener *listener, void *data)
1364 {
1365     struct tinyds_dpms *dpms;
1366     struct ds_tizen_dpms_event *event = data;
1367
1368     dpms = wl_container_of(listener, dpms, set_dpms);
1369
1370     ds_inf("Dpms(%p) set dpms : %d", dpms, event->mode);
1371
1372     //To do
1373     //set dpms mode to output
1374     ds_tizen_dpms_send_set_result(dpms->ds_dpms, event->mode,
1375         DS_TIZEN_DPMS_ERROR_NONE);
1376 }
1377
1378 static void
1379 dpms_handle_get_dpms(struct wl_listener *listener, void *data)
1380 {
1381     struct tinyds_dpms *dpms;
1382
1383     dpms = wl_container_of(listener, dpms, get_dpms);
1384
1385     ds_inf("Dpms(%p) get dpms", dpms);
1386
1387     //To do
1388     //get dpms mode from output
1389     ds_tizen_dpms_send_get_result(dpms->ds_dpms, DS_TIZEN_DPMS_MODE_ON,
1390         DS_TIZEN_DPMS_ERROR_NONE);
1391 }
1392
1393 static void
1394 keyboard_handle_device_destroy(struct wl_listener *listener, void *data)
1395 {
1396     struct tinyds_keyboard *kbd;
1397
1398     kbd = wl_container_of(listener, kbd, destroy);
1399
1400     ds_inf("Keyboard(%p) destroyed", kbd);
1401
1402     wl_list_remove(&kbd->destroy.link);
1403     wl_list_remove(&kbd->key.link);
1404     wl_list_remove(&kbd->link);
1405
1406     free(kbd);
1407 }
1408
1409 static bool
1410 server_handle_keybinding(struct tinyds_server *server, xkb_keysym_t sym)
1411 {
1412     switch (sym) {
1413         case XKB_KEY_BackSpace:
1414             wl_display_terminate(server->display);
1415             break;
1416         default:
1417             return false;
1418     }
1419
1420     return true;
1421 }
1422
1423 static void
1424 keyboard_handle_key(struct wl_listener *listener, void *data)
1425 {
1426     struct tinyds_keyboard *kbd;
1427     struct ds_event_keyboard_key *event = data;
1428     struct ds_keyboard *ds_keyboard;
1429     struct xkb_state *xkb_state;
1430     const xkb_keysym_t *syms;
1431     int nsyms;
1432     bool handled = false;
1433
1434     kbd = wl_container_of(listener, kbd, key);
1435
1436     ds_inf("Keyboard(%p) event key: keycode(%d), state(%d), time_msec(%d), "
1437             "update_state(%d)", kbd->dev,
1438             event->keycode, event->state, event->time_msec,
1439             event->update_state);
1440
1441     ds_keyboard = ds_input_device_get_keyboard(kbd->dev);
1442
1443     if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1444         xkb_state = ds_keyboard_get_xkb_state(ds_keyboard);
1445         if (xkb_state) {
1446             nsyms = xkb_state_key_get_syms(xkb_state, event->keycode + 8,
1447                     &syms);
1448             for (int i = 0; i < nsyms; i++) {
1449                 handled = server_handle_keybinding(kbd->server, syms[i]);
1450             }
1451         }
1452     }
1453
1454     if (!handled) {
1455         ds_seat_keyboard_notify_key(kbd->server->seat, event->time_msec,
1456                 event->keycode, event->state);
1457     }
1458 }
1459
1460 static void
1461 server_add_keyboard(struct tinyds_server *server, struct ds_input_device *dev)
1462 {
1463     struct tinyds_keyboard *kbd;
1464     struct xkb_context *context;
1465     struct xkb_keymap *keymap;
1466
1467     kbd = calloc(1, sizeof *kbd);
1468     assert(kbd);
1469
1470     kbd->dev = dev;
1471     kbd->server = server;
1472
1473     context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
1474     if (!context)
1475         goto err;
1476
1477     keymap = xkb_keymap_new_from_names(context, NULL,
1478             XKB_KEYMAP_COMPILE_NO_FLAGS);
1479
1480     if (!keymap) {
1481         ds_err("Failed to compile keymap");
1482         xkb_context_unref(context);
1483         goto err;
1484     }
1485
1486     ds_keyboard_set_keymap(ds_input_device_get_keyboard(dev), keymap);
1487
1488     xkb_keymap_unref(keymap);
1489     xkb_context_unref(context);
1490
1491     kbd->destroy.notify = keyboard_handle_device_destroy;
1492     ds_input_device_add_destroy_listener(dev, &kbd->destroy);
1493
1494     kbd->key.notify = keyboard_handle_key;
1495     ds_keyboard_add_key_listener(ds_input_device_get_keyboard(dev), &kbd->key);
1496
1497     wl_list_insert(&server->keyboards, &kbd->link);
1498
1499     ds_inf("Keyboard(%p) added", kbd);
1500
1501     return;
1502
1503 err:
1504     free(kbd);
1505 }
1506
1507 static struct tinyds_view *
1508 server_view_at(struct tinyds_server *server, double lx, double ly,
1509         double *sx, double *sy)
1510 {
1511     struct tinyds_view *view;
1512     struct ds_surface *surface;
1513     struct ds_buffer *buffer;
1514     int x, y, w = 0, h = 0;
1515
1516     wl_list_for_each(view, &server->views, link) {
1517         surface = ds_xdg_surface_get_surface(view->xdg_surface);
1518         buffer = ds_surface_get_buffer(surface);
1519         ds_buffer_get_size(buffer, &w, &h);
1520
1521         x = view->x;
1522         y = view->y;
1523
1524         if (lx >= x && lx <= x + w && ly >= y && ly <= y + h) {
1525             *sx = lx - x;
1526             *sy = ly - y;
1527
1528             return view;
1529         }
1530     }
1531
1532     return NULL;
1533 }
1534
1535 static void
1536 touch_handle_device_destroy(struct wl_listener *listener, void *data)
1537 {
1538     struct tinyds_touch *touch;
1539
1540     touch = wl_container_of(listener, touch, destroy);
1541
1542     ds_inf("Touch(%p) destroyed", touch);
1543
1544     wl_list_remove(&touch->destroy.link);
1545     wl_list_remove(&touch->down.link);
1546     wl_list_remove(&touch->up.link);
1547     wl_list_remove(&touch->motion.link);
1548
1549     free(touch);
1550 }
1551
1552 static void
1553 touch_handle_down(struct wl_listener *listener, void *data)
1554 {
1555     struct ds_event_touch_down *event = data;
1556     struct tinyds_touch *touch;
1557     struct tinyds_view *view;
1558     struct tinyds_server *server;
1559     double sx = 0.f, sy = 0.f;
1560
1561     touch = wl_container_of(listener, touch, down);
1562
1563     server = touch->server;
1564     server->output_x = event->x * server->output->width;
1565     server->output_y = event->y * server->output->height;
1566
1567     ds_inf("Touch(%p) event down: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1568             touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1569
1570     view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1571
1572     if (view) {
1573         ds_seat_touch_notify_down(touch->server->seat, ds_xdg_surface_get_surface(view->xdg_surface),
1574                 event->time_msec, event->id, sx, sy);
1575     }
1576
1577 #ifdef USE_CURSOR
1578     if (server->output && server->output->cursor_enabled) {
1579         renderer_cursor_update(&server->output->renderer, server->output_x, server->output_y);
1580         draw_server_with_damage(server);
1581     }
1582 #endif
1583 }
1584
1585 static void
1586 touch_handle_up(struct wl_listener *listener, void *data)
1587 {
1588     struct ds_event_touch_up *event = data;
1589     struct tinyds_touch *touch;
1590
1591     touch = wl_container_of(listener, touch, up);
1592
1593     ds_inf("Touch(%p) event up: id(%d) time_msec(%d)",
1594             touch->dev, event->id, event->time_msec);
1595
1596     ds_seat_touch_notify_up(touch->server->seat, event->time_msec, event->id);
1597 }
1598
1599 static void
1600 touch_handle_motion(struct wl_listener *listener, void *data)
1601 {
1602     struct ds_event_touch_motion *event = data;
1603     struct tinyds_touch *touch;
1604     struct tinyds_view *view;
1605     struct tinyds_server *server;
1606     double sx = 0.f, sy = 0.f;
1607
1608     touch = wl_container_of(listener, touch, motion);
1609
1610     server = touch->server;
1611     server->output_x = event->x * server->output->width;
1612     server->output_y = event->y * server->output->height;
1613
1614     ds_inf("Touch(%p) event motion: id(%d) x %.3f y %.3f output_x %.1f output_y %.1f",
1615             touch->dev, event->id, event->x, event->y, server->output_x, server->output_y);
1616
1617     view = server_view_at(server, server->output_x, server->output_y, &sx, &sy);
1618
1619     if (view) {
1620         ds_seat_touch_notify_motion(server->seat, event->time_msec,
1621                 event->id, sx, sy);
1622     }
1623
1624 #ifdef USE_CURSOR
1625     if (server->output && server->output->cursor_enabled) {
1626         renderer_cursor_update(&server->output->renderer, server->output_x, server->output_y);
1627         draw_server_with_damage(server);
1628     }
1629 #endif
1630 }
1631
1632 static void
1633 server_add_touch(struct tinyds_server *server, struct ds_input_device *dev)
1634 {
1635     struct tinyds_touch *touch;
1636
1637     touch = calloc(1, sizeof *touch);
1638     assert(touch);
1639
1640     touch->dev = dev;
1641     touch->server = server;
1642
1643     touch->destroy.notify = touch_handle_device_destroy;
1644     ds_input_device_add_destroy_listener(dev, &touch->destroy);
1645
1646     touch->down.notify = touch_handle_down;
1647     ds_touch_add_down_listener(ds_input_device_get_touch(dev), &touch->down);
1648
1649     touch->up.notify = touch_handle_up;
1650     ds_touch_add_up_listener(ds_input_device_get_touch(dev), &touch->up);
1651
1652     touch->motion.notify = touch_handle_motion;
1653     ds_touch_add_motion_listener(ds_input_device_get_touch(dev), &touch->motion);
1654
1655     ds_inf("Touch(%p) added", touch);
1656 }
1657
1658 static void
1659 pointer_handle_device_destroy(struct wl_listener *listener, void *data)
1660 {
1661     struct tinyds_pointer *pointer;
1662     struct tinyds_server *server;
1663
1664     pointer = wl_container_of(listener, pointer, destroy);
1665
1666     ds_inf("Pointer(%p) destroyed", pointer);
1667
1668     wl_list_remove(&pointer->destroy.link);
1669     wl_list_remove(&pointer->motion.link);
1670     wl_list_remove(&pointer->button.link);
1671     wl_list_remove(&pointer->frame.link);
1672     wl_list_remove(&pointer->link);
1673
1674 #ifdef USE_CURSOR
1675     server = pointer->server;
1676     if (server->output && wl_list_empty(&server->pointers))
1677     {
1678         server->output->cursor_enabled = false;
1679         renderer_cursor_destroy(&server->output->renderer);
1680
1681         if (server->output->cursor_hwc_window)
1682         {
1683             ds_tdm_output_hwc_window_destroy(server->output->cursor_hwc_window);
1684             server->output->cursor_hwc_window = NULL;
1685         }
1686         draw_server_with_damage(server);
1687     }
1688 #endif
1689
1690     free(pointer);
1691 }
1692
1693 static void
1694 pointer_handle_motion(struct wl_listener *listener, void *data)
1695 {
1696     struct tinyds_pointer *pointer;
1697     struct ds_event_pointer_motion *event = data;
1698     struct tinyds_view *view;
1699     struct tinyds_server *server;
1700     int ow = 0, oh = 0;
1701     double sx, sy;
1702
1703     pointer = wl_container_of(listener, pointer, motion);
1704
1705     server = pointer->server;
1706     if (server->output) {
1707         ow = server->output->width;
1708         oh = server->output->height;
1709     }
1710
1711     if (server->output_x + event->delta_x >= ow)
1712         server->output_x = ow;
1713     else if(server->output_x + event->delta_x <= 0.f)
1714         server->output_x = 0.f;
1715     else
1716         server->output_x = server->output_x + event->delta_x ;
1717     if (server->output_y + event->delta_y >= oh)
1718         server->output_y = oh;
1719     else if(server->output_y + event->delta_y <= 0.f)
1720         server->output_y = 0.f;
1721     else
1722         server->output_y = server->output_y + event->delta_y ;
1723
1724     ds_inf("Pointer(%p) motion: (delta_x %.1f delta_y %.1f) output_x %.1f output_y %.1f",
1725             pointer, event->delta_x, event->delta_y, server->output_x, server->output_y);
1726
1727     view = server_view_at(pointer->server, server->output_x, server->output_y, &sx, &sy);
1728
1729     if (pointer->focused_view != view) {
1730         if (pointer->focused_view) {
1731             ds_inf("Clear pointer focus from view(%p)", pointer->focused_view);
1732             ds_seat_pointer_notify_clear_focus(pointer->server->seat);
1733             pointer->focused_view = NULL;
1734         }
1735
1736         if (view) {
1737             ds_inf("Set pointer focus to view(%p)", view);
1738             ds_seat_pointer_notify_enter(pointer->server->seat,
1739                     ds_xdg_surface_get_surface(view->xdg_surface), sx, sy);
1740             pointer->focused_view = view;
1741         }
1742     }
1743
1744     if (view) {
1745         ds_seat_pointer_notify_motion(pointer->server->seat,
1746                 event->time_msec, sx, sy);
1747     }
1748
1749 #ifdef USE_CURSOR
1750     if (server->output && server->output->cursor_enabled) {
1751         renderer_cursor_update(&server->output->renderer, server->output_x, server->output_y);
1752         draw_server_with_damage(server);
1753     }
1754 #endif
1755 }
1756
1757 static void
1758 pointer_handle_button(struct wl_listener *listener, void *data)
1759 {
1760     struct tinyds_pointer *pointer;
1761     struct ds_event_pointer_button *event = data;
1762
1763     pointer = wl_container_of(listener, pointer, button);
1764
1765     ds_inf("Pointer(%p) button(%d): state(%s) time(%d)",
1766             pointer, event->button,
1767             (event->state == DS_BUTTON_PRESSED) ? "Pressed" : "Released",
1768             event->time_msec);
1769
1770     ds_seat_pointer_notify_button(pointer->server->seat, event->time_msec, event->button, event->state);
1771 }
1772
1773 static void
1774 pointer_handle_frame(struct wl_listener *listener, void *data)
1775 {
1776     struct tinyds_pointer *pointer;
1777
1778     pointer = wl_container_of(listener, pointer, frame);
1779
1780     ds_inf("Pointer(%p) frame", pointer);
1781     ds_seat_pointer_notify_frame(pointer->server->seat);
1782 }
1783
1784 static void
1785 server_add_pointer(struct tinyds_server *server, struct ds_input_device *dev)
1786 {
1787     struct tinyds_pointer *pointer;
1788
1789     pointer = calloc(1, sizeof *pointer);
1790     assert(pointer);
1791
1792     pointer->dev = dev;
1793     pointer->server = server;
1794
1795     pointer->destroy.notify = pointer_handle_device_destroy;
1796     ds_input_device_add_destroy_listener(dev, &pointer->destroy);
1797
1798     pointer->motion.notify = pointer_handle_motion;
1799     ds_pointer_add_motion_listener(ds_input_device_get_pointer(dev),
1800             &pointer->motion);
1801
1802     pointer->button.notify = pointer_handle_button;
1803     ds_pointer_add_button_listener(ds_input_device_get_pointer(dev),
1804             &pointer->button);
1805
1806     pointer->frame.notify = pointer_handle_frame;
1807     ds_pointer_add_frame_listener(ds_input_device_get_pointer(dev),
1808             &pointer->frame);
1809
1810     pointer->focused_view = NULL;
1811
1812 #ifdef USE_CURSOR
1813     if (server->output && wl_list_empty(&server->pointers)) {
1814         server->output_x = (double)(server->output->width) / 2;
1815         server->output_y = (double)(server->output->height) / 2;
1816
1817         server->output->cursor_enabled = true;
1818         renderer_cursor_create(&server->output->renderer, 255, 0, 0, CURSOR_W, CURSOR_H);
1819         renderer_cursor_update(&server->output->renderer, server->output_x, server->output_y);
1820
1821         server->output->cursor_hwc_window = ds_tdm_output_hwc_window_create(server->output->hwc);
1822         assert(server->output->cursor_hwc_window);
1823         draw_server_with_damage(server);
1824     }
1825 #endif
1826
1827     wl_list_insert(&server->pointers, &pointer->link);
1828
1829     ds_inf("Pointer(%p) added", pointer);
1830 }
1831
1832 static void
1833 output_schedule_commit_handle_idle_timer(void *data)
1834 {
1835     struct tinyds_output *output = data;
1836     output->idle_commit = NULL;
1837
1838     output_commit(output);
1839 }
1840
1841 static void
1842 output_schedule_commit(struct tinyds_output *output)
1843 {
1844     if (output->idle_commit)
1845         return;
1846
1847     struct wl_event_loop *ev = wl_display_get_event_loop(output->server->display);
1848     output->idle_commit =
1849         wl_event_loop_add_idle(ev, output_schedule_commit_handle_idle_timer, output);
1850 }
1851
1852 static void
1853 text_input_mgr_handle_destroy(struct wl_listener *listener, void *data)
1854 {
1855     struct tinyds_text_input *text_input;
1856     struct tinyds_server *server;
1857
1858     ds_inf("text_input_mgr_handle_destroy");
1859     text_input = wl_container_of(listener, text_input, mgr_destroy);
1860
1861     wl_list_remove(&text_input->mgr_destroy.link);
1862     wl_list_remove(&text_input->new_text_input.link);
1863
1864     server = text_input->server;
1865     server->text_input = NULL;
1866 }
1867
1868 static void
1869 text_input_handle_destroy(struct wl_listener *listener, void *data)
1870 {
1871     struct tinyds_text_input *text_input;
1872
1873     ds_inf("text_input_handle_destroy");
1874
1875     text_input = wl_container_of(listener, text_input, destroy);
1876
1877     wl_list_remove(&text_input->destroy.link);
1878     wl_list_remove(&text_input->text_input_activate.link);
1879     wl_list_remove(&text_input->text_input_deactivate.link);
1880     wl_list_remove(&text_input->text_input_reset.link);
1881     wl_list_remove(&text_input->text_input_set_content_type.link);
1882     wl_list_remove(&text_input->text_input_invoke_action.link);
1883     wl_list_remove(&text_input->text_input_commit_state.link);
1884     wl_list_remove(&text_input->text_input_set_preferred_language.link);
1885
1886     free(text_input);
1887 }
1888
1889 static void
1890 text_input_handle_activate(struct wl_listener *listener, void *data)
1891 {
1892     struct tinyds_text_input *text_input;
1893     struct tinyds_input_method *input_method;
1894     struct ds_tizen_text_input_event_activate *event = data;
1895
1896     text_input = wl_container_of(listener, text_input, text_input_activate);
1897
1898     input_method = text_input->server->input_method;
1899
1900     ds_inf("text_input_handle_activate. text_input(%p) seat(%p) surface(%p) text_input(%p)",
1901         text_input, event->seat, event->surface, event->text_input);
1902
1903     if (input_method->input == text_input)
1904         return;
1905     if (input_method->input)
1906         ;//deactivate_input_method(server->input_method);
1907     input_method->input = text_input;
1908     wl_list_insert(&text_input->input_methods, &input_method->link);
1909
1910     text_input->surface = event->surface;
1911
1912     if (!add_new_input_method_context(input_method, text_input))
1913         return;
1914
1915     // ds_tizen_input_method_send_set_text_input_id();
1916 }
1917
1918 static void
1919 text_input_handle_deactivate(struct wl_listener *listener, void *data)
1920 {
1921     struct tinyds_text_input *text_input;
1922     struct tinyds_input_method *input_method, *tmp;
1923     struct ds_tizen_text_input_event_deactivate *event = data;
1924
1925     text_input = wl_container_of(listener, text_input, text_input_deactivate);
1926     ds_inf("text_input_handle_deactivate. text_input(%p) seat(%p) text_input(%p)",
1927         text_input, event->seat, event->text_input);
1928
1929     wl_list_for_each_safe(input_method, tmp, &text_input->input_methods, link) {
1930         if (!input_method->input_method || !input_method->context->context) continue;
1931         ds_tizen_input_method_send_deactivate(input_method->input_method, input_method->context->context);
1932         input_method->input = NULL;
1933         input_method->context = NULL;
1934         wl_list_remove(&input_method->link);
1935     }
1936
1937     text_input->surface = NULL;
1938     // ds_tizen_input_method_send_close_connection();
1939 }
1940
1941 static void
1942 text_input_handle_reset(struct wl_listener *listener, void *data)
1943 {
1944     struct tinyds_text_input *text_input;
1945     struct tinyds_input_method *input_method;
1946
1947     text_input = wl_container_of(listener, text_input, text_input_reset);
1948
1949     ds_inf("text_input_handle_reset. text_input(%p)", text_input);
1950
1951     wl_list_for_each(input_method, &text_input->input_methods, link) {
1952         if (!input_method->context || !input_method->context->context) continue;
1953         ds_tizen_input_method_context_send_reset(input_method->context->context);
1954     }
1955 }
1956
1957 static void
1958 text_input_handle_set_content_type(struct wl_listener *listener, void *data)
1959 {
1960     struct tinyds_text_input *text_input;
1961     struct ds_tizen_text_input_event_set_content_type *event = data;
1962     struct tinyds_input_method *input_method;
1963
1964     text_input = wl_container_of(listener, text_input, text_input_set_content_type);
1965
1966     ds_inf("text_input_handle_content_type. text_input(%p) hint(%u) purpose(%u)",
1967         text_input, event->hint, event->purpose);
1968
1969     wl_list_for_each(input_method, &text_input->input_methods, link) {
1970         if (!input_method->context || !input_method->context->context) continue;
1971         ds_tizen_input_method_context_send_content_type(input_method->context->context,
1972             event->hint, event->purpose);
1973     }
1974 }
1975
1976 static void
1977 text_input_handle_invoke_action(struct wl_listener *listener, void *data)
1978 {
1979     struct tinyds_text_input *text_input;
1980     struct ds_tizen_text_input_event_invoke_action *event = data;
1981     struct tinyds_input_method *input_method;
1982
1983     text_input = wl_container_of(listener, text_input, text_input_invoke_action);
1984
1985     ds_inf("text_input_handle_invoke_action. text_input(%p) button(%u) index(%u)",
1986         text_input, event->button, event->index);
1987
1988     wl_list_for_each(input_method, &text_input->input_methods, link) {
1989         if (!input_method->context || !input_method->context->context) continue;
1990         ds_tizen_input_method_context_send_invoke_action(input_method->context->context,
1991             event->button, event->index);
1992     }
1993 }
1994
1995 static void
1996 text_input_handle_commit_state(struct wl_listener *listener, void *data)
1997 {
1998     struct tinyds_text_input *text_input;
1999     struct ds_tizen_text_input_event_commit_state *event = data;
2000     struct tinyds_input_method *input_method;
2001
2002     text_input = wl_container_of(listener, text_input, text_input_commit_state);
2003
2004     ds_inf("text_input_handle_commit_state. text_input(%p) serial(%u)",
2005         text_input, event->serial);
2006
2007     wl_list_for_each(input_method, &text_input->input_methods, link) {
2008         if (!input_method->context || !input_method->context->context) continue;
2009         ds_tizen_input_method_context_send_commit_state(input_method->context->context,
2010             event->serial);
2011     }
2012 }
2013
2014 static void
2015 text_input_handle_set_preferred_language(struct wl_listener *listener, void *data)
2016 {
2017     struct tinyds_text_input *text_input;
2018     struct ds_tizen_text_input_event_set_preferred_language *event = data;
2019     struct tinyds_input_method *input_method;
2020
2021     text_input = wl_container_of(listener, text_input, text_input_set_preferred_language);
2022
2023     ds_inf("text_input_handle_set_preferred_language. text_input(%p) language(%s)",
2024         text_input, event->language);
2025
2026     wl_list_for_each(input_method, &text_input->input_methods, link) {
2027         if (!input_method->context || !input_method->context->context) continue;
2028         ds_tizen_input_method_context_send_preferred_language(input_method->context->context,
2029             event->language);
2030     }
2031 }
2032
2033 static void
2034 text_input_mgr_handle_new_text_input(struct wl_listener *listener, void *data)
2035 {
2036     struct tinyds_text_input *text_input;
2037     struct ds_tizen_text_input *input = data;
2038
2039     text_input = wl_container_of(listener, text_input, new_text_input);
2040
2041     ds_inf("text_input_mgr_handle_new_text_input");
2042
2043     text_input->input = input;
2044
2045     text_input->destroy.notify = text_input_handle_destroy;
2046     ds_tizen_text_input_add_destroy_listener(text_input->input,
2047         &text_input->destroy);
2048
2049     text_input->text_input_activate.notify = text_input_handle_activate;
2050     ds_tizen_text_input_add_activate_listener(text_input->input,
2051         &text_input->text_input_activate);
2052
2053     text_input->text_input_deactivate.notify = text_input_handle_deactivate;
2054     ds_tizen_text_input_add_deactivate_listener(text_input->input,
2055         &text_input->text_input_deactivate);
2056
2057     text_input->text_input_reset.notify = text_input_handle_reset;
2058     ds_tizen_text_input_add_reset_listener(text_input->input,
2059         &text_input->text_input_reset);
2060
2061     text_input->text_input_set_content_type.notify = text_input_handle_set_content_type;
2062     ds_tizen_text_input_add_set_content_type_listener(text_input->input,
2063         &text_input->text_input_set_content_type);
2064
2065     text_input->text_input_invoke_action.notify = text_input_handle_invoke_action;
2066     ds_tizen_text_input_add_invoke_action_listener(text_input->input,
2067         &text_input->text_input_invoke_action);
2068
2069     text_input->text_input_commit_state.notify = text_input_handle_commit_state;
2070     ds_tizen_text_input_add_commit_state_listener(text_input->input,
2071         &text_input->text_input_commit_state);
2072
2073     text_input->text_input_set_preferred_language.notify = text_input_handle_set_preferred_language;
2074     ds_tizen_text_input_add_set_preferred_language_listener(text_input->input,
2075         &text_input->text_input_set_preferred_language);
2076 }
2077
2078 static void
2079 input_method_mgr_handle_destroy(struct wl_listener *listener, void *data)
2080 {
2081     struct tinyds_input_method *input_method;
2082
2083     ds_inf("input_method_mgr_handle_destroy");
2084
2085     input_method = wl_container_of(listener, input_method, mgr_destroy);
2086
2087     wl_list_remove(&input_method->mgr_destroy.link);
2088 }
2089
2090 static void
2091 input_method_handle_destroy(struct wl_listener *listener, void *data)
2092 {
2093     struct tinyds_input_method *input_method;
2094     struct tinyds_server *server;
2095
2096     ds_inf("input_method_handle_destroy");
2097
2098     input_method = wl_container_of(listener, input_method, destroy);
2099
2100     wl_list_remove(&input_method->destroy.link);
2101
2102     server = input_method->server;
2103     server->input_method = NULL;
2104
2105     free(input_method);
2106 }
2107
2108 static void
2109 context_handle_destroy(struct wl_listener *listener, void *data)
2110 {
2111     struct tinyds_input_method_context *context;
2112     struct tinyds_server *server;
2113
2114     ds_inf("context_handle_destroy");
2115
2116     context = wl_container_of(listener, context, destroy);
2117
2118     wl_list_remove(&context->destroy.link);
2119
2120     wl_list_remove(&context->im_context_commit_string.link);
2121     wl_list_remove(&context->im_context_preedit_string.link);
2122     wl_list_remove(&context->im_context_preedit_styling.link);
2123     wl_list_remove(&context->im_context_preedit_cursor.link);
2124     wl_list_remove(&context->im_context_delete_surrounding_text.link);
2125     wl_list_remove(&context->im_context_cursor_position.link);
2126     wl_list_remove(&context->im_context_modifiers_map.link);
2127     wl_list_remove(&context->im_context_keysym.link);
2128     wl_list_remove(&context->im_context_grab_keyboard.link);
2129     wl_list_remove(&context->im_context_key.link);
2130     wl_list_remove(&context->im_context_modifiers.link);
2131     wl_list_remove(&context->im_context_language.link);
2132     wl_list_remove(&context->im_context_text_direction.link);
2133
2134     server = context->server;
2135     server->input_method->context = NULL;
2136
2137     free(context);
2138 }
2139
2140 static void
2141 context_handle_commit_string(struct wl_listener *listener, void *data)
2142 {
2143     struct tinyds_text_input *text_input;
2144     struct tinyds_input_method_context *context;
2145     struct ds_tizen_input_method_context_event_commit_string *event = data;
2146
2147     context = wl_container_of(listener, context, im_context_commit_string);
2148     text_input = context->server->text_input;
2149
2150     ds_inf("context_handle_commit_string. text_input(%p) serial(%u) text(%s)",
2151         text_input, event->serial, event->text);
2152
2153     ds_tizen_text_input_send_commit_string(text_input->input, event->serial, event->text);
2154 }
2155
2156 static void
2157 context_handle_preedit_string(struct wl_listener *listener, void *data)
2158 {
2159     struct tinyds_input_method_context *context;
2160     struct tinyds_text_input *text_input;
2161     struct ds_tizen_input_method_context_event_preedit_string *event = data;
2162
2163     context = wl_container_of(listener, context, im_context_preedit_string);
2164     text_input = context->server->text_input;
2165
2166     ds_inf("context_handle_preedit_string. text_input(%p) serial(%u) text(%s) commit(%s)",
2167         text_input, event->serial, event->text, event->commit);
2168
2169     ds_tizen_text_input_send_preedit_string(text_input->input, event->serial, event->text, event->commit);
2170 }
2171
2172 static void
2173 context_handle_preedit_styling(struct wl_listener *listener, void *data)
2174 {
2175     struct tinyds_input_method_context *context;
2176     struct tinyds_text_input *text_input;
2177     struct ds_tizen_input_method_context_event_preedit_styling *event = data;
2178
2179     context = wl_container_of(listener, context, im_context_preedit_styling);
2180     text_input = context->server->text_input;
2181
2182     ds_inf("context_handle_preedit_styling. text_input(%p) index(%u) length(%u) style(%u)",
2183         text_input, event->index, event->length, event->style);
2184
2185     ds_tizen_text_input_send_preedit_styling(text_input->input, event->index, event->length, event->style);
2186 }
2187
2188 static void
2189 context_handle_preedit_cursor(struct wl_listener *listener, void *data)
2190 {
2191     struct tinyds_input_method_context *context;
2192     struct tinyds_text_input *text_input;
2193     struct ds_tizen_input_method_context_event_preedit_cursor *event = data;
2194
2195     context = wl_container_of(listener, context, im_context_preedit_cursor);
2196     text_input = context->server->text_input;
2197
2198     ds_inf("context_handle_preedit_cursor. text_input(%p) index(%u)",
2199         text_input, event->index);
2200
2201     ds_tizen_text_input_send_preedit_cursor(text_input->input, event->index);
2202 }
2203
2204 static void
2205 context_handle_delete_surrounding_text(struct wl_listener *listener, void *data)
2206 {
2207     struct tinyds_input_method_context *context;
2208     struct tinyds_text_input *text_input;
2209     struct ds_tizen_input_method_context_event_delete_surrounding_text *event = data;
2210
2211     context = wl_container_of(listener, context, im_context_delete_surrounding_text);
2212     text_input = context->server->text_input;
2213
2214     ds_inf("context_handle_delete_surrounding_text. text_input(%p) index(%d) length(%u)",
2215         text_input, event->index, event->length);
2216
2217     ds_tizen_text_input_send_delete_surrounding_text(text_input->input, event->index, event->length);
2218 }
2219
2220 static void
2221 context_handle_cursor_position(struct wl_listener *listener, void *data)
2222 {
2223     struct tinyds_input_method_context *context;
2224     struct tinyds_text_input *text_input;
2225     struct ds_tizen_input_method_context_event_cursor_position *event = data;
2226
2227     context = wl_container_of(listener, context, im_context_cursor_position);
2228     text_input = context->server->text_input;
2229
2230     ds_inf("context_handle_cursor_position. text_input(%p) index(%d) length(%d)",
2231         text_input, event->index, event->anchor);
2232
2233     ds_tizen_text_input_send_cursor_position(text_input->input, event->index, event->anchor);
2234 }
2235
2236 static void
2237 context_handle_modifiers_map(struct wl_listener *listener, void *data)
2238 {
2239     struct tinyds_input_method_context *context;
2240     struct tinyds_text_input *text_input;
2241     struct ds_tizen_input_method_context_event_modifiers_map *event = data;
2242
2243     context = wl_container_of(listener, context, im_context_modifiers_map);
2244     text_input = context->server->text_input;
2245
2246     ds_inf("context_handle_modifiers_map. text_input(%p) map(%p)",
2247         text_input, event->map);
2248
2249     ds_tizen_text_input_send_modifiers_map(text_input->input, event->map);
2250 }
2251
2252 static void
2253 context_handle_keysym(struct wl_listener *listener, void *data)
2254 {
2255     struct tinyds_input_method_context *context;
2256     struct tinyds_text_input *text_input;
2257     struct ds_tizen_input_method_context_event_keysym *event = data;
2258
2259     context = wl_container_of(listener, context, im_context_keysym);
2260     text_input = context->server->text_input;
2261
2262     ds_inf("context_handle_keysym. text_input(%p) serial(%u) time(%u) sysm(%u) state(%u) modifiers(%u)",
2263         text_input, event->serial, event->time, event->sym, event->state, event->modifiers);
2264
2265     ds_tizen_text_input_send_keysym(text_input->input, event->serial, event->time, event->sym, event->state, event->modifiers);
2266 }
2267
2268 static void
2269 context_handle_grab_keyboard(struct wl_listener *listener, void *data)
2270 {
2271     struct tinyds_input_method_context *context;
2272     struct tinyds_text_input *text_input;
2273
2274     context = wl_container_of(listener, context, im_context_grab_keyboard);
2275     text_input = context->server->text_input;
2276
2277     ds_inf("context_handle_grab_keyboard. text_input(%p)",
2278         text_input);
2279
2280     //TODO
2281 }
2282
2283 static void
2284 context_handle_key(struct wl_listener *listener, void *data)
2285 {
2286     struct tinyds_input_method_context *context;
2287     struct tinyds_text_input *text_input;
2288
2289     context = wl_container_of(listener, context, im_context_key);
2290     text_input = context->server->text_input;
2291
2292     ds_inf("context_handle_key. text_input(%p)",
2293         text_input);
2294
2295    //TODO
2296 }
2297
2298 static void
2299 context_handle_modifiers(struct wl_listener *listener, void *data)
2300 {
2301     struct tinyds_input_method_context *context;
2302     struct tinyds_text_input *text_input;
2303
2304     context = wl_container_of(listener, context, im_context_modifiers);
2305     text_input = context->server->text_input;
2306
2307     ds_inf("context_handle_modifiers. text_input(%p)",
2308         text_input);
2309
2310    //TODO
2311 }
2312
2313 static void
2314 context_handle_language(struct wl_listener *listener, void *data)
2315 {
2316     struct tinyds_input_method_context *context;
2317     struct tinyds_text_input *text_input;
2318     struct ds_tizen_input_method_context_event_language *event = data;
2319
2320     context = wl_container_of(listener, context, im_context_language);
2321     text_input = context->server->text_input;
2322
2323     ds_inf("context_handle_language. text_input(%p) serial(%u), language(%s)",
2324         text_input, event->serial, event->language);
2325
2326     ds_tizen_text_input_send_language(text_input->input, event->serial, event->language);
2327 }
2328
2329 static void
2330 context_handle_text_direction(struct wl_listener *listener, void *data)
2331 {
2332     struct tinyds_input_method_context *context;
2333     struct tinyds_text_input *text_input;
2334     struct ds_tizen_input_method_context_event_text_direction *event = data;
2335
2336     context = wl_container_of(listener, context, im_context_text_direction);
2337     text_input = context->server->text_input;
2338
2339     ds_inf("context_handle_text_direction. text_input(%p) serial(%u), direction(%u)",
2340         text_input, event->serial, event->direction);
2341
2342     ds_tizen_text_input_send_text_direction(text_input->input, event->serial, event->direction);
2343 }
2344
2345 static bool
2346 add_new_text_input(struct tinyds_server *server)
2347 {
2348     struct tinyds_text_input *text_input;
2349
2350     text_input = calloc(1, sizeof *text_input);
2351     if (!text_input)
2352         return false;
2353
2354     text_input->text_input_mgr = ds_tizen_text_input_manager_create(server->display);
2355     if (!text_input->text_input_mgr) {
2356         free(text_input);
2357         ds_err("Could not create ds_tizen_text_input_manager");
2358         return false;
2359     }
2360
2361     wl_list_init(&text_input->input_methods);
2362
2363     text_input->mgr_destroy.notify = text_input_mgr_handle_destroy;
2364     ds_tizen_text_input_manager_add_destroy_listener(text_input->text_input_mgr,
2365             &text_input->mgr_destroy);
2366
2367     text_input->new_text_input.notify = text_input_mgr_handle_new_text_input;
2368     ds_tizen_text_input_manager_add_new_text_input_listener(text_input->text_input_mgr,
2369             &text_input->new_text_input);
2370
2371     text_input->server = server;
2372     server->text_input = text_input;
2373
2374     ds_inf("Text_Input (%p) added", text_input);
2375
2376     return true;
2377 }
2378
2379 static bool
2380 add_new_input_method(struct tinyds_server *server)
2381 {
2382     struct tinyds_input_method *input_method;
2383
2384     input_method = calloc(1, sizeof *input_method);
2385     if (!input_method)
2386         return false;
2387
2388     input_method->input_method = ds_tizen_input_method_create(server->display);
2389     if (!input_method->input_method) {
2390         free(input_method);
2391         ds_err("Could not create ds_tizen_input_method");
2392         return false;
2393     }
2394     input_method->destroy.notify = input_method_handle_destroy;
2395     ds_tizen_input_method_add_destroy_listener(input_method->input_method,
2396             &input_method->destroy);
2397
2398     input_method->input_method_mgr = ds_tizen_input_method_manager_create(server->display);
2399     if (!input_method->input_method_mgr) {
2400         free(input_method);
2401         ds_err("Could not create ds_tizen_input_method_manager");
2402         return false;
2403     }
2404
2405     input_method->mgr_destroy.notify = input_method_mgr_handle_destroy;
2406     ds_tizen_input_method_manager_add_destroy_listener(input_method->input_method_mgr,
2407             &input_method->mgr_destroy);
2408
2409     input_method->server = server;
2410     server->input_method = input_method;
2411
2412     ds_inf("Input_Method (%p) added", input_method);
2413
2414     return true;
2415 }
2416
2417 static bool
2418 add_new_input_method_context(struct tinyds_input_method *input_method,
2419         struct tinyds_text_input *text_input)
2420 {
2421     struct tinyds_input_method_context *context;
2422
2423     context = calloc(1, sizeof *context);
2424     if (context == NULL)
2425     {
2426         ds_err("calloc is failed. tinyds_input_method_context");
2427         return false;
2428     }
2429     input_method->context = context;
2430     context->input_method = input_method;
2431     context->server = input_method->server;
2432     context->input = text_input;
2433
2434     context->context = ds_tizen_input_method_create_context(input_method->input_method);
2435     if (context->context == NULL) {
2436         ds_err("ds_tizen_input_method_create_context() failed.");
2437         return false;
2438     }
2439
2440     context->destroy.notify = context_handle_destroy;
2441     ds_tizen_input_method_context_add_destroy_listener(context->context,
2442         &context->destroy);
2443
2444     context->im_context_commit_string.notify = context_handle_commit_string;
2445     ds_tizen_input_method_context_add_commit_string_listener(context->context,
2446         &context->im_context_commit_string);
2447
2448     context->im_context_preedit_string.notify = context_handle_preedit_string;
2449     ds_tizen_input_method_context_add_preedit_string_listener(context->context,
2450         &context->im_context_preedit_string);
2451
2452     context->im_context_preedit_styling.notify = context_handle_preedit_styling;
2453     ds_tizen_input_method_context_add_preedit_styling_listener(context->context,
2454         &context->im_context_preedit_styling);
2455
2456     context->im_context_preedit_cursor.notify = context_handle_preedit_cursor;
2457     ds_tizen_input_method_context_add_preedit_cursor_listener(context->context,
2458         &context->im_context_preedit_cursor);
2459
2460     context->im_context_delete_surrounding_text.notify = context_handle_delete_surrounding_text;
2461     ds_tizen_input_method_context_add_delete_surrounding_text_listener(context->context,
2462         &context->im_context_delete_surrounding_text);
2463
2464     context->im_context_cursor_position.notify = context_handle_cursor_position;
2465     ds_tizen_input_method_context_add_cursor_position_listener(context->context,
2466         &context->im_context_cursor_position);
2467
2468     context->im_context_modifiers_map.notify = context_handle_modifiers_map;
2469     ds_tizen_input_method_context_add_modifiers_map_listener(context->context,
2470         &context->im_context_modifiers_map);
2471
2472     context->im_context_keysym.notify = context_handle_keysym;
2473     ds_tizen_input_method_context_add_keysym_listener(context->context,
2474         &context->im_context_keysym);
2475
2476     context->im_context_grab_keyboard.notify = context_handle_grab_keyboard;
2477     ds_tizen_input_method_context_add_grab_keyboard_listener(context->context,
2478         &context->im_context_grab_keyboard);
2479
2480     context->im_context_key.notify = context_handle_key;
2481     ds_tizen_input_method_context_add_key_listener(context->context,
2482         &context->im_context_key);
2483
2484     context->im_context_modifiers.notify = context_handle_modifiers;
2485     ds_tizen_input_method_context_add_modifiers_listener(context->context,
2486         &context->im_context_modifiers);
2487
2488     context->im_context_language.notify = context_handle_language;
2489     ds_tizen_input_method_context_add_language_listener(context->context,
2490         &context->im_context_language);
2491
2492     context->im_context_text_direction.notify = context_handle_text_direction;
2493     ds_tizen_input_method_context_add_text_direction_listener(context->context,
2494         &context->im_context_text_direction);
2495
2496     return true;
2497 }