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