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