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