clients: add ime-keyboard(input_method), text-entry(text_input)
[platform/core/uifw/libds-tizen.git] / clients / ime-keyboard.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/epoll.h>
6
7 #include <wayland-client.h>
8 #include <xkbcommon/xkbcommon.h>
9 #include <linux/input.h>
10
11 #include <input-method-client-protocol.h>
12 #include <text-client-protocol.h>
13
14 #define MAX_STR 1024
15 #define SIZE_EPOLL 16
16
17 enum keyboard_state {
18     KEYBOARD_STATE_DEFAULT,
19     KEYBOARD_STATE_UPPERCASE,
20     KEYBOARD_STATE_SYMBOLS
21 };
22
23 struct display
24 {
25     struct wl_display *display;
26     struct wl_registry *registry;
27     struct wl_compositor *compositor;
28     struct wl_event_queue *queue;
29
30     int run;
31     int fd_epoll;
32     int fd_display;
33
34     int enable_log;
35
36     struct zwp_input_method_manager_v1 *input_method_mgr;
37     struct zwp_input_method_v1 *input_method;
38     struct zwp_input_method_context_v1 *context;
39
40     char *preedit_string;
41     uint32_t preedit_style;
42     struct {
43         xkb_mod_mask_t shift_mask;
44     } keysym;
45     uint32_t serial;
46     uint32_t content_hint;
47     int32_t content_purpose;
48     char *preferred_language;
49     char *surrounding_text;
50     uint32_t surrounding_cursor;
51     enum keyboard_state state; //struct keyboard *keyboard;
52
53     //struct zwp_input_panel_surface_v1 *ips;
54 };
55
56 struct layout {
57     const struct key *keys;
58     uint32_t count;
59
60     uint32_t columns;
61     uint32_t rows;
62
63     const char *language;
64     uint32_t text_direction;
65 };
66
67 enum key_type {
68     keytype_default,
69     keytype_backspace,
70     keytype_enter,
71     keytype_space,
72     keytype_switch,
73     keytype_symbols,
74     keytype_tab,
75     keytype_arrow_up,
76     keytype_arrow_left,
77     keytype_arrow_right,
78     keytype_arrow_down,
79     keytype_style
80 };
81
82 struct key {
83     enum key_type key_type;
84
85     char *label;
86     char *uppercase;
87     char *symbol;
88
89     unsigned int width;
90 };
91
92 static const struct key normal_keys[] = {
93     { keytype_default, "q", "Q", "1", 1},
94     { keytype_default, "w", "W", "2", 1},
95     { keytype_default, "e", "E", "3", 1},
96     { keytype_default, "r", "R", "4", 1},
97     { keytype_default, "t", "T", "5", 1},
98     { keytype_default, "y", "Y", "6", 1},
99     { keytype_default, "u", "U", "7", 1},
100     { keytype_default, "i", "I", "8", 1},
101     { keytype_default, "o", "O", "9", 1},
102     { keytype_default, "p", "P", "0", 1},
103     { keytype_backspace, "<--", "<--", "<--", 2},
104
105     { keytype_tab, "->|", "->|", "->|", 1},
106     { keytype_default, "a", "A", "-", 1},
107     { keytype_default, "s", "S", "@", 1},
108     { keytype_default, "d", "D", "*", 1},
109     { keytype_default, "f", "F", "^", 1},
110     { keytype_default, "g", "G", ":", 1},
111     { keytype_default, "h", "H", ";", 1},
112     { keytype_default, "j", "J", "(", 1},
113     { keytype_default, "k", "K", ")", 1},
114     { keytype_default, "l", "L", "~", 1},
115     { keytype_enter, "Enter", "Enter", "Enter", 2},
116
117     { keytype_switch, "ABC", "abc", "ABC", 2},
118     { keytype_default, "z", "Z", "/", 1},
119     { keytype_default, "x", "X", "\'", 1},
120     { keytype_default, "c", "C", "\"", 1},
121     { keytype_default, "v", "V", "+", 1},
122     { keytype_default, "b", "B", "=", 1},
123     { keytype_default, "n", "N", "?", 1},
124     { keytype_default, "m", "M", "!", 1},
125     { keytype_default, ",", ",", "\\", 1},
126     { keytype_default, ".", ".", "|", 1},
127     { keytype_switch, "ABC", "abc", "ABC", 1},
128
129     { keytype_symbols, "?123", "?123", "abc", 1},
130     { keytype_space, "", "", "", 5},
131     { keytype_arrow_up, "/\\", "/\\", "/\\", 1},
132     { keytype_arrow_left, "<", "<", "<", 1},
133     { keytype_arrow_right, ">", ">", ">", 1},
134     { keytype_arrow_down, "\\/", "\\/", "\\/", 1},
135     { keytype_style, "", "", "", 2}
136 };
137
138 static const struct key numeric_keys[] = {
139     { keytype_default, "1", "1", "1", 1},
140     { keytype_default, "2", "2", "2", 1},
141     { keytype_default, "3", "3", "3", 1},
142     { keytype_default, "4", "4", "4", 1},
143     { keytype_default, "5", "5", "5", 1},
144     { keytype_default, "6", "6", "6", 1},
145     { keytype_default, "7", "7", "7", 1},
146     { keytype_default, "8", "8", "8", 1},
147     { keytype_default, "9", "9", "9", 1},
148     { keytype_default, "0", "0", "0", 1},
149     { keytype_backspace, "<--", "<--", "<--", 2},
150
151     { keytype_space, "", "", "", 4},
152     { keytype_enter, "Enter", "Enter", "Enter", 2},
153     { keytype_arrow_up, "/\\", "/\\", "/\\", 1},
154     { keytype_arrow_left, "<", "<", "<", 1},
155     { keytype_arrow_right, ">", ">", ">", 1},
156     { keytype_arrow_down, "\\/", "\\/", "\\/", 1},
157     { keytype_style, "", "", "", 2}
158 };
159
160 static const struct layout normal_layout = {
161     normal_keys,
162     sizeof(normal_keys) / sizeof(*normal_keys),
163     12,
164     4,
165     "en",
166     WL_TEXT_INPUT_TEXT_DIRECTION_LTR
167 };
168
169 static const struct layout numeric_layout = {
170     numeric_keys,
171     sizeof(numeric_keys) / sizeof(*numeric_keys),
172     12,
173     2,
174     "en",
175     WL_TEXT_INPUT_TEXT_DIRECTION_LTR
176 };
177
178 struct display data_wl;
179 static void
180 request_key(uint32_t time, const struct key *key, enum wl_pointer_button_state state);
181
182 static void
183 usage(void)
184 {
185     printf(" This is virtual keyboard. (refer to weston/clients/keyboard.c)\n");
186     printf("\n");
187 }
188
189 static const struct layout *
190 get_current_layout(void)
191 {
192     switch (data_wl.content_purpose) {
193         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
194         case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
195             return &numeric_layout;
196         default:
197             return &normal_layout;
198     }
199 }
200
201 static void
202 stdin_read(void)
203 {
204     int c;
205     char buf[MAX_STR] = {0, }, *tmp, *buf_ptr;
206     int count = 0;
207     static uint32_t time = 12345;
208     const struct layout *layout;
209     uint32_t key_type = 0, key_idx = 0;
210
211     while ((c = getchar()) != EOF) {
212         if (c == '\n') break;
213         if (count >= MAX_STR) break;
214
215         buf[count] = c;
216         count++;
217     }
218
219     count = 0;
220     tmp = strtok_r(buf, " ", &buf_ptr);
221     if (!tmp) return;
222
223     if (!strncmp(buf, "q", MAX_STR) || !strncmp(buf, "quit", MAX_STR)) {
224         data_wl.run = 0;
225     } else if (!strncmp(buf, "help", MAX_STR)) {
226         usage();
227     } else if (!strncmp(buf, "log", MAX_STR)) {
228         if (data_wl.enable_log)
229             printf("Disable detailed logs\n");
230         else
231             printf("Enable detailed logs\n");
232
233         data_wl.enable_log = !data_wl.enable_log;
234     } else if (!strncmp(tmp, "key", MAX_STR)) {
235         while (tmp) {
236             tmp = strtok_r(NULL, " ", &buf_ptr);
237             if (tmp) {
238                 switch (count) {
239                     case 0:
240                         key_idx = atoi(tmp);
241                         break;
242                     case 1:
243                         key_type = atoi(tmp);
244                         break;
245                     default:
246                         break;
247                 }
248             }
249             count++;
250         }
251         if (data_wl.enable_log)
252             printf("request key() key_idx:%u, key_type:%u\n", key_idx, key_type);
253
254         layout = get_current_layout();
255         request_key(time++, &layout->keys[key_idx], key_type);
256
257     } else {
258         printf("Invalid arguments\n");
259         usage();
260     }
261 }
262
263 static const char *
264 prev_utf8_char(const char *s, const char *p)
265 {
266     for (--p; p >= s; --p) {
267         if ((*p & 0xc0) != 0x80)
268             return p;
269     }
270     return NULL;
271 }
272
273 static void
274 delete_before_cursor(void)
275 {
276     const char *start, *end;
277
278     if (!data_wl.surrounding_text) {
279         printf("delete_before_cursor: No surrounding text available\n");
280         return;
281     }
282
283     start = prev_utf8_char(data_wl.surrounding_text,
284                    data_wl.surrounding_text + data_wl.surrounding_cursor);
285     if (!start) {
286         printf("delete_before_cursor: No previous character to delete\n");
287         return;
288     }
289
290     end = data_wl.surrounding_text + data_wl.surrounding_cursor;
291
292     zwp_input_method_context_v1_delete_surrounding_text(data_wl.context,
293                                 (start - data_wl.surrounding_text) - data_wl.surrounding_cursor,
294                                 end - start);
295     zwp_input_method_context_v1_commit_string(data_wl.context,
296                           data_wl.serial,
297                           "");
298
299     /* Update surrounding text */
300     data_wl.surrounding_cursor = start - data_wl.surrounding_text;
301     data_wl.surrounding_text[data_wl.surrounding_cursor] = '\0';
302     if (*end)
303         memmove(data_wl.surrounding_text + data_wl.surrounding_cursor, end, strlen(end));
304 }
305
306 static char *
307 append(char *s1, const char *s2)
308 {
309     int len1, len2;
310     char *s = NULL;
311
312     len1 = strlen(s1);
313     len2 = strlen(s2);
314     s = realloc(s1, len1 + len2 + 1);
315     if (s == NULL) {
316         printf("alloc fail");
317         return NULL;
318     }
319     memcpy(s + len1, s2, len2);
320     s[len1 + len2] = '\0';
321
322     return s;
323 }
324
325 static void
326 request_preedit(int32_t cursor)
327 {
328     printf("request_preedit() preedit_string:%s\n", data_wl.preedit_string);
329     uint32_t index = strlen(data_wl.preedit_string);
330
331     if (!data_wl.context) return;
332
333     if (data_wl.preedit_style)
334         zwp_input_method_context_v1_preedit_styling(data_wl.context,
335                                 0,
336                                 strlen(data_wl.preedit_string),
337                                 data_wl.preedit_style);
338     if (cursor > 0)
339         index = cursor;
340     zwp_input_method_context_v1_preedit_cursor(data_wl.context,
341                            index);
342     zwp_input_method_context_v1_preedit_string(data_wl.context,
343                            data_wl.serial,
344                            data_wl.preedit_string,
345                            data_wl.preedit_string);
346 }
347
348 static char *
349 insert_text(const char *text, uint32_t offset, const char *insert)
350 {
351     int tlen = strlen(text), ilen = strlen(insert);
352     char *new_text = NULL;
353
354     new_text = malloc(tlen + ilen + 1);
355     if (new_text == NULL) {
356         printf("alloc fail");
357         return NULL;
358     }
359
360     memcpy(new_text, text, offset);
361     memcpy(new_text + offset, insert, ilen);
362     memcpy(new_text + offset + ilen, text + offset, tlen - offset);
363     new_text[tlen + ilen] = '\0';
364
365     return new_text;
366 }
367
368 static void
369 request_commit_string(void)
370 {
371     char *surrounding_text;
372
373     printf("request_commit_string()\n");
374
375     if (!data_wl.preedit_string ||
376         strlen(data_wl.preedit_string) == 0)
377         return;
378     printf("request_commit_string() preedit_string:%s\n", data_wl.preedit_string);
379
380     if (!data_wl.context) return;
381
382     zwp_input_method_context_v1_cursor_position(data_wl.context,
383                             0, 0);
384     zwp_input_method_context_v1_commit_string(data_wl.context,
385                           data_wl.serial,
386                           data_wl.preedit_string);
387
388     if (data_wl.surrounding_text) {
389         surrounding_text = insert_text(data_wl.surrounding_text,
390                            data_wl.surrounding_cursor,
391                            data_wl.preedit_string);
392         free(data_wl.surrounding_text);
393         data_wl.surrounding_text = surrounding_text;
394         data_wl.surrounding_cursor += strlen(data_wl.preedit_string);
395     } else {
396         data_wl.surrounding_text = strdup(data_wl.preedit_string);
397         data_wl.surrounding_cursor = strlen(data_wl.preedit_string);
398     }
399
400     free(data_wl.preedit_string);
401     data_wl.preedit_string = strdup("");
402 }
403
404 static void
405 request_key(uint32_t time, const struct key *key, enum wl_pointer_button_state state)
406 {
407     const char *label = NULL;
408     static uint32_t serial = 9999;
409
410     switch(data_wl.state) {
411     case KEYBOARD_STATE_DEFAULT :
412         label = key->label;
413         break;
414     case KEYBOARD_STATE_UPPERCASE :
415         label = key->uppercase;
416         break;
417     case KEYBOARD_STATE_SYMBOLS :
418         label = key->symbol;
419         break;
420     default :
421         label = key->label;
422         break;
423     }
424
425     xkb_mod_mask_t mod_mask = data_wl.state == KEYBOARD_STATE_DEFAULT ? 0 : data_wl.keysym.shift_mask;
426     uint32_t key_state = (state == WL_POINTER_BUTTON_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED;
427
428     printf("request_key() data_wl.state:%d, key->key_type:%d, pressed:%u, label:%s\n", data_wl.state, key->key_type, key_state, label);
429     switch (key->key_type) {
430         case keytype_default:
431             if (state != WL_POINTER_BUTTON_STATE_PRESSED)
432                 break;
433
434             printf("request_key() keytype_default. append label(%s) to preedit_string(%s)\n", label, data_wl.preedit_string);
435             data_wl.preedit_string =
436                 append(data_wl.preedit_string,
437                        label);
438             request_preedit(-1);
439             break;
440         case keytype_backspace:
441             if (state != WL_POINTER_BUTTON_STATE_PRESSED)
442                 break;
443
444             if (strlen(data_wl.preedit_string) == 0) {
445                 delete_before_cursor();
446             } else {
447                 data_wl.preedit_string[strlen(data_wl.preedit_string) - 1] = '\0';
448                 request_preedit(-1);
449             }
450             break;
451         case keytype_enter:
452             request_commit_string();
453
454             if (!data_wl.context) break;
455             zwp_input_method_context_v1_keysym(data_wl.context,
456                                serial++,
457                                time,
458                                XKB_KEY_Return, key_state, mod_mask);
459             break;
460         case keytype_space:
461             if (state != WL_POINTER_BUTTON_STATE_PRESSED)
462                 break;
463             data_wl.preedit_string =
464                 append(data_wl.preedit_string, " ");
465             request_commit_string();
466             break;
467         case keytype_switch:
468             if (state != WL_POINTER_BUTTON_STATE_PRESSED)
469                 break;
470             switch(data_wl.state) {
471             case KEYBOARD_STATE_DEFAULT:
472                 data_wl.state = KEYBOARD_STATE_UPPERCASE;
473                 break;
474             case KEYBOARD_STATE_UPPERCASE:
475                 data_wl.state = KEYBOARD_STATE_DEFAULT;
476                 break;
477             case KEYBOARD_STATE_SYMBOLS:
478                 data_wl.state = KEYBOARD_STATE_UPPERCASE;
479                 break;
480             }
481             break;
482         case keytype_symbols:
483             if (state != WL_POINTER_BUTTON_STATE_PRESSED)
484                 break;
485             switch(data_wl.state) {
486             case KEYBOARD_STATE_DEFAULT:
487                 data_wl.state = KEYBOARD_STATE_SYMBOLS;
488                 break;
489             case KEYBOARD_STATE_UPPERCASE:
490                 data_wl.state = KEYBOARD_STATE_SYMBOLS;
491                 break;
492             case KEYBOARD_STATE_SYMBOLS:
493                 data_wl.state = KEYBOARD_STATE_DEFAULT;
494                 break;
495             }
496             break;
497         case keytype_tab:
498             request_commit_string();
499             if (!data_wl.context) break;
500             zwp_input_method_context_v1_keysym(data_wl.context,
501                                serial++,
502                                time,
503                                XKB_KEY_Tab, key_state, mod_mask);
504             break;
505         case keytype_arrow_up:
506             request_commit_string();
507             if (!data_wl.context) break;
508             zwp_input_method_context_v1_keysym(data_wl.context,
509                                serial++,
510                                time,
511                                XKB_KEY_Up, key_state, mod_mask);
512             break;
513         case keytype_arrow_left:
514             request_commit_string();
515             if (!data_wl.context) break;
516             zwp_input_method_context_v1_keysym(data_wl.context,
517                                serial++,
518                                time,
519                                XKB_KEY_Left, key_state, mod_mask);
520             break;
521         case keytype_arrow_right:
522             request_commit_string();
523             if (!data_wl.context) break;
524             zwp_input_method_context_v1_keysym(data_wl.context,
525                                serial++,
526                                time,
527                                XKB_KEY_Right, key_state, mod_mask);
528             break;
529         case keytype_arrow_down:
530             request_commit_string();
531             if (!data_wl.context) break;
532             zwp_input_method_context_v1_keysym(data_wl.context,
533                                serial++,
534                                time,
535                                XKB_KEY_Down, key_state, mod_mask);
536             break;
537         case keytype_style:
538             if (state != WL_POINTER_BUTTON_STATE_PRESSED)
539                 break;
540             data_wl.preedit_style = (data_wl.preedit_style + 1) % 8; /* TODO */
541             request_preedit(-1);
542             break;
543     }
544 }
545
546 static void
547 im_context_cb_surrounding_text (void *data, struct zwp_input_method_context_v1 *im_ctx, const char *text, uint32_t cursor, uint32_t anchor)
548 {
549     printf("im_context_cb_surrounding_text\n");
550         free(data_wl.surrounding_text);
551     data_wl.surrounding_text = strdup(text);
552
553     data_wl.surrounding_cursor = cursor;
554 }
555
556 static void
557 im_context_cb_reset (void *data, struct zwp_input_method_context_v1 *im_ctx)
558 {
559     printf("im_context_cb_reset\n");
560     
561     if (strlen(data_wl.preedit_string)) {
562         free(data_wl.preedit_string);
563         data_wl.preedit_string = strdup("");
564     }
565 }
566
567 static void
568 im_context_cb_content_type (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t hint, uint32_t purpose)
569 {
570     printf("im_context_cb_content_type\n");
571
572     data_wl.content_hint = hint;
573     data_wl.content_purpose = purpose;
574 }
575
576 static void
577 im_context_cb_invoke_action (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t button, uint32_t index)
578 {
579     printf("im_context_cb_invoke_action\n");
580
581     if (button != BTN_LEFT)
582         return;
583
584     request_preedit(index);
585 }
586
587 static void
588 im_context_cb_commit_state (void *data, struct zwp_input_method_context_v1 *context, uint32_t serial)
589 {
590     printf("im_context_cb_commit_state\n");
591
592     const struct layout *layout;
593
594     data_wl.serial = serial;
595
596     layout = get_current_layout();
597
598     if (data_wl.surrounding_text)
599         printf("Surrounding text updated: %s\n", data_wl.surrounding_text);
600
601     if (!context) return;
602     zwp_input_method_context_v1_language(context,
603                          data_wl.serial,
604                          layout->language);
605     zwp_input_method_context_v1_text_direction(context,
606                            data_wl.serial,
607                            layout->text_direction);
608 }
609
610 static void
611 im_context_cb_preferred_language (void *data, struct zwp_input_method_context_v1 *context, const char *language)
612 {
613     printf("im_context_cb_preferred_language\n");
614
615     if (data_wl.preferred_language)
616         free(data_wl.preferred_language);
617
618     data_wl.preferred_language = NULL;
619
620     if (language)
621         data_wl.preferred_language = strdup(language);
622 }
623
624 static const struct zwp_input_method_context_v1_listener input_method_context_cb_listener = {
625     .surrounding_text = im_context_cb_surrounding_text,
626     .reset = im_context_cb_reset,
627     .content_type = im_context_cb_content_type,
628     .invoke_action = im_context_cb_invoke_action,
629     .commit_state = im_context_cb_commit_state,
630     .preferred_language = im_context_cb_preferred_language,
631     //for tizen only
632     .return_key_type = NULL,
633     .return_key_disabled = NULL,
634     .input_panel_data = NULL,
635     .bidi_direction = NULL,
636     .cursor_position = NULL,
637     .process_input_device_event = NULL,
638     .filter_key_event = NULL,
639     .capital_mode = NULL,
640     .prediction_hint = NULL,
641     .mime_type = NULL,
642     .finalized_content = NULL,
643     .prediction_hint_data = NULL,
644     .input_panel_enabled = NULL,
645 };
646
647 static void
648 keysym_modifiers_add(struct wl_array *modifiers_map,
649              const char *name)
650 {
651     size_t len = strlen(name) + 1;
652     char *p;
653
654     p = wl_array_add(modifiers_map, len);
655
656     if (p == NULL)
657         return;
658
659     strncpy(p, name, len);
660 }
661
662 static xkb_mod_index_t
663 keysym_modifiers_get_index(struct wl_array *modifiers_map,
664                const char *name)
665 {
666     xkb_mod_index_t index = 0;
667     char *p = modifiers_map->data;
668
669     while ((const char *)p < (const char *)(modifiers_map->data + modifiers_map->size)) {
670         if (strcmp(p, name) == 0)
671             return index;
672
673         index++;
674         p += strlen(p) + 1;
675     }
676
677     return XKB_MOD_INVALID;
678 }
679
680 xkb_mod_mask_t
681 keysym_modifiers_get_mask(struct wl_array *modifiers_map,
682               const char *name)
683 {
684     xkb_mod_index_t index = keysym_modifiers_get_index(modifiers_map, name);
685
686     if (index == XKB_MOD_INVALID)
687         return XKB_MOD_INVALID;
688
689     return 1 << index;
690 }
691
692 static void
693 im_cb_activate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *context)
694 {
695     printf("im_cb_activate\n");
696
697     struct wl_array modifiers_map;
698     const struct layout *layout;
699
700     if (data_wl.context)
701         zwp_input_method_context_v1_destroy(data_wl.context);
702
703     if (data_wl.preedit_string)
704         free(data_wl.preedit_string);
705
706     data_wl.preedit_style = 0;
707     data_wl.preedit_string = strdup("");
708     data_wl.content_hint = 0;
709     data_wl.content_purpose = 0;
710     free(data_wl.preferred_language);
711     data_wl.preferred_language = NULL;
712     free(data_wl.surrounding_text);
713     data_wl.surrounding_text = NULL;
714
715     data_wl.serial = 0;
716
717     data_wl.context = context;
718     zwp_input_method_context_v1_add_listener(context,
719                          &input_method_context_cb_listener,
720                          NULL);
721
722     wl_array_init(&modifiers_map);
723     keysym_modifiers_add(&modifiers_map, "Shift");
724     keysym_modifiers_add(&modifiers_map, "Control");
725     keysym_modifiers_add(&modifiers_map, "Mod1");
726     zwp_input_method_context_v1_modifiers_map(context, &modifiers_map);
727     data_wl.keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift");
728     wl_array_release(&modifiers_map);
729
730     layout = get_current_layout();
731
732     zwp_input_method_context_v1_language(context,
733                          data_wl.serial,
734                          layout->language);
735     zwp_input_method_context_v1_text_direction(context,
736                            data_wl.serial,
737                            layout->text_direction);
738 }
739 static void
740 im_cb_deactivate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
741 {
742     printf("im_cb_deactivate\n");
743
744     if (!data_wl.context)
745         return;
746
747     zwp_input_method_context_v1_destroy(data_wl.context);
748     data_wl.context = NULL;
749 }
750
751 static void
752 im_cb_destroy (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
753 {
754     printf("im_cb_destroy\n");
755     zwp_input_method_v1_destroy(data_wl.input_method);
756     data_wl.input_method = NULL;
757 }
758
759 static const struct zwp_input_method_v1_listener input_method_cb_listener = {
760     .activate = im_cb_activate,
761     .deactivate = im_cb_deactivate,
762     //for tizen only
763     .destroy = im_cb_destroy,
764     .show_input_panel = NULL,
765     .hide_input_panel = NULL,
766     .open_connection = NULL,
767     .close_connection = NULL,
768     .set_text_input_id = NULL,
769 };
770
771 static void
772 registry_handle_global(void * data, struct wl_registry * registry, uint32_t id,
773         const char * interface, uint32_t version)
774 {
775     if (strcmp(interface, "wl_compositor") == 0) {
776         data_wl.compositor = wl_registry_bind(registry, id,
777                 &wl_compositor_interface, version);
778         if (!data_wl.compositor) {
779             printf("Failed to bind compositor.\n");
780             return;
781         }
782         if (data_wl.enable_log)
783             printf("Success to bind compositor.\n");
784     } else if (!strcmp(interface, "zwp_input_method_manager_v1")) {
785         data_wl.input_method_mgr = wl_registry_bind(registry, id,
786                 &zwp_input_method_manager_v1_interface, version);
787     } else if (!strcmp(interface, "zwp_input_method_v1")) {
788         data_wl.input_method = wl_registry_bind(registry, id,
789                 &zwp_input_method_v1_interface, version);
790         zwp_input_method_v1_add_listener(data_wl.input_method,
791                          &input_method_cb_listener,
792                          NULL);
793
794         //TODO: delte this code. this job should be done in cb_activate
795         data_wl.preedit_string = strdup("");
796         data_wl.content_hint = 0;
797         data_wl.content_purpose = 0;
798         free(data_wl.preferred_language);
799         data_wl.preferred_language = NULL;
800         free(data_wl.surrounding_text);
801         data_wl.surrounding_text = NULL;
802         data_wl.serial = 0;
803     }
804 }
805
806 static void
807 registry_handle_global_remove(void * data, struct wl_registry * registry, uint32_t id)
808 {
809     if (data_wl.enable_log)
810         printf("registry is removed. id: %d !\n", id);
811 }
812
813 static const struct wl_registry_listener _registry_listener = {
814     registry_handle_global,
815     registry_handle_global_remove
816 };
817
818 static int
819 wayland_init(void)
820 {
821     memset(&data_wl, 0, sizeof(struct display));
822
823     data_wl.display = wl_display_connect(NULL);
824     if (!data_wl.display) {
825         printf("Failed to connect wayland display\n");
826         return 0;
827     }
828
829     data_wl.queue = wl_display_create_queue(data_wl.display);
830     if (!data_wl.queue) {
831         printf("Failed to create queue\n");
832         return 0;
833     }
834
835     data_wl.registry = wl_display_get_registry(data_wl.display);
836     if (!data_wl.registry) {
837         printf("Failed to get registry\n");
838         return 0;
839     }
840
841     wl_proxy_set_queue((struct wl_proxy*)data_wl.registry, data_wl.queue);
842     wl_registry_add_listener(data_wl.registry, &_registry_listener, NULL);
843
844     if (wl_display_dispatch_queue(data_wl.display, data_wl.queue) == -1) {
845         printf("Failed to dispatch display\n");
846         return 0;
847     }
848     if (wl_display_roundtrip_queue(data_wl.display, data_wl.queue) == -1) {
849         printf("Failed to roundtrip display\n");
850         return 0;
851     }
852
853     return 1;
854 }
855
856 static void
857 wayland_deinit(void)
858 {
859     if (data_wl.enable_log)
860         printf("Shutdown wayland system\n");
861
862     if (data_wl.queue) wl_event_queue_destroy(data_wl.queue);
863     if (data_wl.display) {
864         if (data_wl.input_method)
865             zwp_input_method_v1_destroy(data_wl.input_method);
866         zwp_input_method_manager_v1_destroy(data_wl.input_method_mgr);
867         wl_registry_destroy(data_wl.registry);
868         wl_display_flush(data_wl.display);
869         wl_display_disconnect(data_wl.display);
870     }
871 }
872
873 static int
874 epoll_init(void)
875 {
876     struct epoll_event ep[2];
877
878     data_wl.fd_epoll = epoll_create(SIZE_EPOLL);
879     if (data_wl.fd_epoll <= 0) {
880         printf("Failed to epoll create: %d\n", SIZE_EPOLL);
881         return 0;
882     }
883
884     data_wl.fd_display = wl_display_get_fd(data_wl.display);
885
886     memset(ep, 0, sizeof(struct epoll_event)*2);
887
888     ep[0].events = EPOLLIN | EPOLLERR | EPOLLHUP;
889     ep[0].data.fd = data_wl.fd_display;
890     epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, data_wl.fd_display, &ep[0]);
891     ep[1].events = EPOLLIN | EPOLLERR | EPOLLHUP;
892     ep[1].data.fd = STDIN_FILENO;
893     epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, 0, &ep[1]);
894
895     return 1;
896 }
897
898 static void
899 mainloop(void)
900 {
901     struct epoll_event ep[SIZE_EPOLL];
902     int res, count, i;
903
904     res = epoll_init();
905     if (!res) {
906         printf("Failed to init epoll\n");
907         return;
908     }
909
910     data_wl.run = 1;
911     while (data_wl.run) {
912         res = wl_display_dispatch_queue_pending(data_wl.display, data_wl.queue);
913         if (res < 0) {
914             printf("Failed to dispatch pending. result: %d\n", res);
915             data_wl.run = 0;
916             break;
917         }
918         res = wl_display_flush(data_wl.display);
919         if (res < 0) {
920             printf("Failed to flush display. result: %d\n", res);
921             data_wl.run = 0;
922             break;
923         }
924
925         count = epoll_wait(data_wl.fd_epoll, ep, SIZE_EPOLL, -1);
926         for (i = 0; i < count; i++) {
927             if (ep[i].events & EPOLLIN) {
928                 if (ep[i].data.fd == data_wl.fd_display) {
929                     wl_display_dispatch_queue(data_wl.display, data_wl.queue);
930                 } else {
931                     stdin_read();
932                 }
933             }
934             if (ep[i].events & EPOLLERR) {
935                 data_wl.run = 0;
936             }
937             if (ep[i].events & EPOLLHUP) {
938                 data_wl.run = 0;
939             }
940         }
941     }
942 }
943
944 int
945 main(int argc, char **argv)
946 {
947     int res;
948
949     res = wayland_init();
950     if (!res) return 0;
951
952     mainloop();
953
954     wayland_deinit();
955
956     return 0;
957 }