cfa1800d32a059405cae9621167a8360430348cd
[platform/core/uifw/libds-tizen.git] / clients / input-generator.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 #include <tizen-extension-client-protocol.h>
14
15 #define MAX_STR 1024
16 #define SIZE_EPOLL 16
17
18 enum keyboard_state {
19     KEYBOARD_STATE_DEFAULT,
20     KEYBOARD_STATE_UPPERCASE,
21     KEYBOARD_STATE_SYMBOLS
22 };
23
24 enum enum_key_type
25 {
26     KEY_UP = 0,
27     KEY_DOWN,
28     KEY_ALL
29 };
30
31 enum enum_touch_type
32 {
33     POINTER_BEGIN = 0,
34     POINTER_UPDATE,
35     POINTER_END,
36     POINTER_ALL
37 };
38
39 struct display
40 {
41     struct wl_display *display;
42     struct wl_registry *registry;
43     struct wl_compositor *compositor;
44
45     struct tizen_input_device_manager *devicemgr;
46     enum tizen_input_device_manager_clas clas;
47     struct wl_event_queue *queue;
48
49     int run;
50     int fd_epoll;
51     int fd_display;
52
53     int request_notified;
54     int init;
55
56     int enable_log;
57
58     struct zwp_input_method_manager_v1 *input_method_mgr;
59     struct zwp_input_method_v1 *input_method;
60     struct zwp_input_method_context_v1 *context;
61
62     char *preedit_string;
63     uint32_t preedit_style;
64     struct {
65         xkb_mod_mask_t shift_mask;
66     } keysym;
67     uint32_t serial;
68     uint32_t content_hint;
69     int32_t content_purpose;
70     char *preferred_language;
71     char *surrounding_text;
72     uint32_t surrounding_cursor;
73     enum keyboard_state state; //struct keyboard *keyboard;
74
75     //struct zwp_input_panel_surface_v1 *ips;
76 };
77
78 struct layout {
79     const struct key *keys;
80     uint32_t count;
81
82     uint32_t columns;
83     uint32_t rows;
84
85     const char *language;
86     uint32_t text_direction;
87 };
88
89 enum key_type {
90     keytype_default,
91     keytype_backspace,
92     keytype_enter,
93     keytype_space,
94     keytype_switch,
95     keytype_symbols,
96     keytype_tab,
97     keytype_arrow_up,
98     keytype_arrow_left,
99     keytype_arrow_right,
100     keytype_arrow_down,
101     keytype_style
102 };
103
104 struct key {
105     enum key_type key_type;
106
107     char *label;
108     char *uppercase;
109     char *symbol;
110
111     unsigned int width;
112 };
113
114 static const struct key normal_keys[] = {
115     { keytype_default, "q", "Q", "1", 1},
116     { keytype_default, "w", "W", "2", 1},
117     { keytype_default, "e", "E", "3", 1},
118     { keytype_default, "r", "R", "4", 1},
119     { keytype_default, "t", "T", "5", 1},
120     { keytype_default, "y", "Y", "6", 1},
121     { keytype_default, "u", "U", "7", 1},
122     { keytype_default, "i", "I", "8", 1},
123     { keytype_default, "o", "O", "9", 1},
124     { keytype_default, "p", "P", "0", 1},
125     { keytype_backspace, "<--", "<--", "<--", 2},
126
127     { keytype_tab, "->|", "->|", "->|", 1},
128     { keytype_default, "a", "A", "-", 1},
129     { keytype_default, "s", "S", "@", 1},
130     { keytype_default, "d", "D", "*", 1},
131     { keytype_default, "f", "F", "^", 1},
132     { keytype_default, "g", "G", ":", 1},
133     { keytype_default, "h", "H", ";", 1},
134     { keytype_default, "j", "J", "(", 1},
135     { keytype_default, "k", "K", ")", 1},
136     { keytype_default, "l", "L", "~", 1},
137     { keytype_enter, "Enter", "Enter", "Enter", 2},
138
139     { keytype_switch, "ABC", "abc", "ABC", 2},
140     { keytype_default, "z", "Z", "/", 1},
141     { keytype_default, "x", "X", "\'", 1},
142     { keytype_default, "c", "C", "\"", 1},
143     { keytype_default, "v", "V", "+", 1},
144     { keytype_default, "b", "B", "=", 1},
145     { keytype_default, "n", "N", "?", 1},
146     { keytype_default, "m", "M", "!", 1},
147     { keytype_default, ",", ",", "\\", 1},
148     { keytype_default, ".", ".", "|", 1},
149     { keytype_switch, "ABC", "abc", "ABC", 1},
150
151     { keytype_symbols, "?123", "?123", "abc", 1},
152     { keytype_space, "", "", "", 5},
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 key numeric_keys[] = {
161     { keytype_default, "1", "1", "1", 1},
162     { keytype_default, "2", "2", "2", 1},
163     { keytype_default, "3", "3", "3", 1},
164     { keytype_default, "4", "4", "4", 1},
165     { keytype_default, "5", "5", "5", 1},
166     { keytype_default, "6", "6", "6", 1},
167     { keytype_default, "7", "7", "7", 1},
168     { keytype_default, "8", "8", "8", 1},
169     { keytype_default, "9", "9", "9", 1},
170     { keytype_default, "0", "0", "0", 1},
171     { keytype_backspace, "<--", "<--", "<--", 2},
172
173     { keytype_space, "", "", "", 4},
174     { keytype_enter, "Enter", "Enter", "Enter", 2},
175     { keytype_arrow_up, "/\\", "/\\", "/\\", 1},
176     { keytype_arrow_left, "<", "<", "<", 1},
177     { keytype_arrow_right, ">", ">", ">", 1},
178     { keytype_arrow_down, "\\/", "\\/", "\\/", 1},
179     { keytype_style, "", "", "", 2}
180 };
181
182 static const struct layout normal_layout = {
183     normal_keys,
184     sizeof(normal_keys) / sizeof(*normal_keys),
185     12,
186     4,
187     "en",
188     WL_TEXT_INPUT_TEXT_DIRECTION_LTR
189 };
190
191 static const struct layout numeric_layout = {
192     numeric_keys,
193     sizeof(numeric_keys) / sizeof(*numeric_keys),
194     12,
195     2,
196     "en",
197     WL_TEXT_INPUT_TEXT_DIRECTION_LTR
198 };
199
200 struct display data_wl;
201
202 static void
203 request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state state);
204
205 static const struct layout *
206 get_current_layout(void);
207
208 static void
209 usage(void)
210 {
211     printf("  Supported commands:  init  (Initialize input generator)\n");
212     printf("                    :  deinit  (Deinitialize input generator)\n");
213     printf("                    :  key  (Generate key events)\n");
214     printf("                    :  touch  (Generate touch events)\n");
215     printf("                    :  help  (Print this help text)\n");
216     printf("                    :  q/quit  (Quit program)\n");
217     printf("                    :  log  (Print detailed logs)\n");
218     printf("init {device type}\n");
219     printf("  : device type:\n");
220     printf("    - default: all\n");
221     printf("    - keyboard / touch / mouse\n");
222     printf("    - all: all of devices\n");
223     printf("  : ex> init keyboard / init\n");
224     printf("\n");
225     printf("deinit\n");
226     printf("  : ex> deinit\n");
227     printf("\n");
228     printf("key [keyname] {pressed}\n");
229     printf("  : pressed:\n");
230     printf("    - default: down&up pair\n");
231     printf("    - key down: 1\n");
232     printf("    - key up: 0\n");
233     printf("  : ex> key XF86Back 1\n");
234     printf("\n");
235     printf("touch {index} {type} {x} {y}\n");
236     printf("  : index:\n");
237     printf("    - default: first finger(0)\n");
238     printf("  : type:\n");
239     printf("    - default: generate sample touch events\n");
240     printf("    - touch down: 0\n");
241     printf("    - touch move: 1\n");
242     printf("    - touch up: 2\n");
243     printf("  : x/y:\n");
244     printf("    - default: 0\n");
245     printf("  : ex> touch\n");
246     printf("  : ex> touch 0 0 400 400\n");
247     printf("  :     touch 0 1 410 410\n");
248     printf("  :     touch 0 2 0 0\n");
249     printf("mouse {button} {type} {x} {y}\n");
250     printf("  : button:\n");
251     printf("    - default: left button(1)\n");
252     printf("  : type:\n");
253     printf("    - default: generate sample mouse events\n");
254     printf("    - button down: 0\n");
255     printf("    - mouse move: 1\n");
256     printf("    - button up: 2\n");
257     printf("  : x/y:\n");
258     printf("    - default: 0\n");
259     printf("    - relative motion\n");
260     printf("  : ex> mouse\n");
261     printf("  : ex> mouse 1 0 0 0\n");
262     printf("  :     mouse 1 1 10 10\n");
263     printf("  :     mouse 1 1 -10 -10\n");
264     printf("  :     mouse 1 2 0 0\n");
265     printf("ime {key_idx} {type}\n");
266     printf("  : key_index\n");
267     printf("  : - keys = [q,w,e,r,t,,,]\n");
268     printf("  : type:\n");
269     printf("  : - default: down & up\n");
270     printf("  : - down: 1\n");
271     printf("  : - up: 0\n");
272     printf("\n");
273 }
274
275 static void
276 init_input_generator(enum tizen_input_device_manager_clas clas)
277 {
278     if (data_wl.init) {
279         printf("Already init input generator\n");
280         return;
281     }
282
283     tizen_input_device_manager_init_generator(data_wl.devicemgr, clas);
284
285     while (data_wl.request_notified == -1)
286         wl_display_dispatch_queue(data_wl.display, data_wl.queue);
287
288     if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
289         data_wl.init = 1;
290         printf("Success to init input generator\n");
291     } else {
292         printf("Failed to init input generator: %d\n", data_wl.request_notified);
293     }
294
295     data_wl.clas = clas;
296     data_wl.request_notified = -1;
297 }
298
299 static void
300 deinit_input_generator(void)
301 {
302     if (!data_wl.init) {
303         printf("input generator is not initialized\n");
304         return;
305     }
306
307     tizen_input_device_manager_deinit_generator(data_wl.devicemgr, data_wl.clas);
308
309     while (data_wl.request_notified == -1)
310         wl_display_dispatch_queue(data_wl.display, data_wl.queue);
311
312     if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
313         data_wl.init = 0;
314         printf("Success to deinit input generator\n");
315     } else {
316         printf("Failed to deinit input generator: %d\n", data_wl.request_notified);
317     }
318
319     data_wl.request_notified = -1;
320 }
321
322 static void
323 input_generator_key(char *name, int type)
324 {
325     tizen_input_device_manager_generate_key(data_wl.devicemgr, name, !!type);
326
327     while (data_wl.request_notified == -1)
328         wl_display_dispatch_queue(data_wl.display, data_wl.queue);
329
330     if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
331         if (data_wl.enable_log) {
332             printf("Success to generate key: %s key %s\n", name, type?"down":"up");
333         }
334     } else {
335         printf("Failed to generate %s key %s: %d\n", name, type?"down":"up", data_wl.request_notified);
336     }
337
338     data_wl.request_notified = -1;
339 }
340
341 static void
342 key_generate(char *name, int type)
343 {
344     printf("name: %s, type: %d\n", name, type);
345
346     if (!data_wl.init) {
347         printf("Input generator is not initialized\n");
348         return;
349     }
350
351     if (!name) {
352         printf("Type which key is generated\n");
353         return;
354     }
355
356     if (type == KEY_ALL) {
357         input_generator_key(name, 1);
358         input_generator_key(name, 0);
359     } else {
360         input_generator_key(name, !!type);
361     }
362 }
363
364 static char *
365 type_string_get(int type)
366 {
367     switch (type) {
368         case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN:
369             return "begin";
370         case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE:
371             return "update";
372         case TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END:
373             return "end";
374         default:
375             return "Unknown";
376     }
377 }
378
379 static void
380 input_generator_touch(int idx, int type, int x, int y)
381 {
382     tizen_input_device_manager_generate_touch(data_wl.devicemgr, type, x, y, idx);
383
384     while (data_wl.request_notified == -1)
385         wl_display_dispatch_queue(data_wl.display, data_wl.queue);
386
387     if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
388         if (data_wl.enable_log) {
389             printf("Success to generate touch: %d finger %s on (%d, %d)\n", idx, type_string_get(type), x, y);
390         }
391     } else {
392         printf("Failed to generate touch(%d finger %s on (%d, %d)): %d\n", idx, type_string_get(type), x, y, data_wl.request_notified);
393     }
394
395     data_wl.request_notified = -1;
396 }
397
398 static void
399 touch_generate(int idx, int type, int x, int y)
400 {
401     if (!data_wl.init) {
402         printf("Input generator is not initialized\n");
403         return;
404     }
405
406     if (type == POINTER_ALL) {
407         input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 300, 300);
408         input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 400, 400);
409         input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 500, 500);
410
411         input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 310, 310);
412         input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 410, 410);
413         input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 510, 510);
414
415         input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 320, 320);
416         input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 420, 420);
417         input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 520, 520);
418
419         input_generator_touch(0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 320, 320);
420         input_generator_touch(1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 420, 420);
421         input_generator_touch(2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 520, 520);
422     } else {
423         input_generator_touch(idx, type, x, y);
424     }
425 }
426
427 static void
428 input_generator_mouse(int type, int x, int y, int button)
429 {
430     tizen_input_device_manager_generate_pointer(data_wl.devicemgr, type, x, y, button);
431
432     while (data_wl.request_notified == -1)
433         wl_display_dispatch_queue(data_wl.display, data_wl.queue);
434
435     if (data_wl.request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
436         if (data_wl.enable_log) {
437             printf("Success to generate mouse: %s on (%d, %d)\n", type_string_get(type), x, y);
438         }
439     } else {
440         printf("Failed to generate mouse(%s on (%d, %d)): %d\n", type_string_get(type), x, y, data_wl.request_notified);
441     }
442
443     data_wl.request_notified = -1;
444 }
445
446 static void
447 mouse_generate(int btn, int type, int x, int y)
448 {
449     if (!data_wl.init) {
450         printf("Input generator is not initialized\n");
451         return;
452     }
453
454     if (type == POINTER_ALL) {
455         input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, -1, -1, 1);
456         input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1);
457         input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1);
458         input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1);
459         input_generator_mouse(TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, -1, -1, 1);
460
461     } else {
462         input_generator_mouse(type, x, y, btn);
463     }
464 }
465
466 static void
467 stdin_read(void)
468 {
469     int c;
470     char buf[MAX_STR] = {0, }, *tmp, *buf_ptr, key_name[MAX_STR] = {0, };
471     int count = 0;
472     int key_type = KEY_ALL, idx = 0, type = POINTER_ALL, x = 0, y = 0;
473     static uint32_t time = 12345;
474     const struct layout *layout;
475
476     while ((c = getchar()) != EOF) {
477         if (c == '\n') break;
478         if (count >= MAX_STR) break;
479
480         buf[count] = c;
481         count++;
482     }
483
484     count = 0;
485     tmp = strtok_r(buf, " ", &buf_ptr);
486     if (!tmp) return;
487
488     if (!strncmp(tmp, "init", sizeof("init"))) {
489         while (tmp) {
490             tmp = strtok_r(NULL, " ", &buf_ptr);
491             if (tmp) {
492                 switch (count) {
493                     case 0:
494                         if (!strncmp("keyboard", tmp, MAX_STR-1))
495                             init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD);
496                         else if (!strncmp("touch", tmp, MAX_STR-1))
497                             init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN);
498                         else if (!strncmp("mouse", tmp, MAX_STR-1))
499                             init_input_generator(TIZEN_INPUT_DEVICE_MANAGER_CLAS_MOUSE);
500                         break;
501                     default:
502                         break;
503                 }
504             }
505             count++;
506         }
507     } else if (!strncmp(tmp, "deinit", sizeof("deinit"))) {
508         deinit_input_generator();
509     } else if (!strncmp(tmp, "key", sizeof("key"))) {
510         while (tmp) {
511             tmp = strtok_r(NULL, " ", &buf_ptr);
512             if (tmp) {
513                 switch (count) {
514                     case 0:
515                         strncpy(key_name, tmp, MAX_STR-1);
516                         break;
517                     case 1:
518                         key_type = atoi(tmp);
519                         break;
520                     default:
521                         break;
522                 }
523             }
524             count++;
525         }
526         key_generate(key_name, key_type);
527     } else if (!strncmp(tmp, "touch", sizeof("touch"))) {
528         while (tmp) {
529             tmp = strtok_r(NULL, " ", &buf_ptr);
530             if (tmp) {
531                 switch (count) {
532                     case 0:
533                         idx = atoi(tmp);
534                         break;
535                     case 1:
536                         type = atoi(tmp);
537                         break;
538                     case 2:
539                         x = atoi(tmp);
540                         break;
541                     case 3:
542                         y = atoi(tmp);
543                         break;
544                     default:
545                         break;
546                 }
547             }
548             count++;
549         }
550         touch_generate(idx, type, x, y);
551     } else if (!strncmp(tmp, "mouse", sizeof("mouse"))) {
552         while (tmp) {
553             tmp = strtok_r(NULL, " ", &buf_ptr);
554             if (tmp) {
555                 switch (count) {
556                     case 0:
557                         idx = atoi(tmp);
558                         break;
559                     case 1:
560                         type = atoi(tmp);
561                         break;
562                     case 2:
563                         x = atoi(tmp);
564                         break;
565                     case 3:
566                         y = atoi(tmp);
567                         break;
568                     default:
569                         break;
570                 }
571             }
572             count++;
573         }
574         mouse_generate(idx, type, x, y);
575     }  else if (!strncmp(tmp, "ime", MAX_STR)) {
576         while (tmp) {
577             tmp = strtok_r(NULL, " ", &buf_ptr);
578             if (tmp) {
579                 switch (count) {
580                     case 0:
581                         idx = atoi(tmp);
582                         break;
583                     case 1:
584                         key_type = atoi(tmp);
585                         break;
586                     default:
587                         break;
588                 }
589             }
590             count++;
591         }
592         if (data_wl.enable_log)
593             printf("request key() key_idx:%u, key_type:%u\n", idx, key_type);
594
595         layout = get_current_layout();
596         if (key_type == KEY_ALL) {
597             request_key(time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_PRESSED);
598             request_key(time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_RELEASED);
599         }
600         else
601             request_key(time++, &layout->keys[idx], key_type);
602     } else if (!strncmp(buf, "q", MAX_STR) || !strncmp(buf, "quit", MAX_STR)) {
603         data_wl.run = 0;
604     } else if (!strncmp(buf, "help", MAX_STR)) {
605         usage();
606     } else if (!strncmp(buf, "log", MAX_STR)) {
607         if (data_wl.enable_log)
608             printf("Disable detailed logs\n");
609         else
610             printf("Enable detailed logs\n");
611
612         data_wl.enable_log = !data_wl.enable_log;
613     } else {
614         printf("Invalid arguments\n");
615         usage();
616     }
617 }
618
619 static void
620 input_device_manager_handle_error(void *data,
621         struct tizen_input_device_manager *tizen_input_device_manager,
622         uint32_t errorcode)
623 {
624     if (data_wl.enable_log)
625         printf("errorcode: %d\n", errorcode);
626     data_wl.request_notified = errorcode;
627 }
628
629 static const struct tizen_input_device_manager_listener _input_device_manager_listener =
630 {
631     .device_add = NULL,
632     .device_remove = NULL,
633     .error = input_device_manager_handle_error,
634     .block_expired = NULL,
635 };
636
637 static const struct layout *
638 get_current_layout(void)
639 {
640     switch (data_wl.content_purpose) {
641         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
642         case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
643             return &numeric_layout;
644         default:
645             return &normal_layout;
646     }
647 }
648
649 static const char *
650 prev_utf8_char(const char *s, const char *p)
651 {
652     for (--p; p >= s; --p) {
653         if ((*p & 0xc0) != 0x80)
654             return p;
655     }
656     return NULL;
657 }
658
659 static void
660 delete_before_cursor(void)
661 {
662     const char *start, *end;
663
664     if (!data_wl.surrounding_text) {
665         printf("delete_before_cursor: No surrounding text available\n");
666         return;
667     }
668
669     start = prev_utf8_char(data_wl.surrounding_text,
670                    data_wl.surrounding_text + data_wl.surrounding_cursor);
671     if (!start) {
672         printf("delete_before_cursor: No previous character to delete\n");
673         return;
674     }
675
676     end = data_wl.surrounding_text + data_wl.surrounding_cursor;
677
678     zwp_input_method_context_v1_delete_surrounding_text(data_wl.context,
679                                 (start - data_wl.surrounding_text) - data_wl.surrounding_cursor,
680                                 end - start);
681     zwp_input_method_context_v1_commit_string(data_wl.context,
682                           data_wl.serial,
683                           "");
684
685     /* Update surrounding text */
686     data_wl.surrounding_cursor = start - data_wl.surrounding_text;
687     data_wl.surrounding_text[data_wl.surrounding_cursor] = '\0';
688     if (*end)
689         memmove(data_wl.surrounding_text + data_wl.surrounding_cursor, end, strlen(end));
690 }
691
692 static char *
693 append(char *s1, const char *s2)
694 {
695     int len1, len2;
696     char *s = NULL;
697
698     len1 = strlen(s1);
699     len2 = strlen(s2);
700     s = realloc(s1, len1 + len2 + 1);
701     if (s == NULL) {
702         printf("alloc fail");
703         return NULL;
704     }
705     memcpy(s + len1, s2, len2);
706     s[len1 + len2] = '\0';
707
708     return s;
709 }
710
711 static void
712 request_preedit(int32_t cursor)
713 {
714     printf("request_preedit() preedit_string:%s\n", data_wl.preedit_string);
715     uint32_t index = strlen(data_wl.preedit_string);
716
717     if (!data_wl.context) return;
718
719     if (data_wl.preedit_style)
720         zwp_input_method_context_v1_preedit_styling(data_wl.context,
721                                 0,
722                                 strlen(data_wl.preedit_string),
723                                 data_wl.preedit_style);
724     if (cursor > 0)
725         index = cursor;
726     zwp_input_method_context_v1_preedit_cursor(data_wl.context,
727                            index);
728     zwp_input_method_context_v1_preedit_string(data_wl.context,
729                            data_wl.serial,
730                            data_wl.preedit_string,
731                            data_wl.preedit_string);
732 }
733
734 static char *
735 insert_text(const char *text, uint32_t offset, const char *insert)
736 {
737     int tlen = strlen(text), ilen = strlen(insert);
738     char *new_text = NULL;
739
740     new_text = malloc(tlen + ilen + 1);
741     if (new_text == NULL) {
742         printf("alloc fail");
743         return NULL;
744     }
745
746     memcpy(new_text, text, offset);
747     memcpy(new_text + offset, insert, ilen);
748     memcpy(new_text + offset + ilen, text + offset, tlen - offset);
749     new_text[tlen + ilen] = '\0';
750
751     return new_text;
752 }
753
754 static void
755 request_commit_string(void)
756 {
757     char *surrounding_text;
758
759     printf("request_commit_string()\n");
760
761     if (!data_wl.preedit_string ||
762         strlen(data_wl.preedit_string) == 0)
763         return;
764     printf("request_commit_string() preedit_string:%s\n", data_wl.preedit_string);
765
766     if (!data_wl.context) return;
767
768     zwp_input_method_context_v1_cursor_position(data_wl.context,
769                             0, 0);
770     zwp_input_method_context_v1_commit_string(data_wl.context,
771                           data_wl.serial,
772                           data_wl.preedit_string);
773
774     if (data_wl.surrounding_text) {
775         surrounding_text = insert_text(data_wl.surrounding_text,
776                            data_wl.surrounding_cursor,
777                            data_wl.preedit_string);
778         free(data_wl.surrounding_text);
779         data_wl.surrounding_text = surrounding_text;
780         data_wl.surrounding_cursor += strlen(data_wl.preedit_string);
781     } else {
782         data_wl.surrounding_text = strdup(data_wl.preedit_string);
783         data_wl.surrounding_cursor = strlen(data_wl.preedit_string);
784     }
785
786     free(data_wl.preedit_string);
787     data_wl.preedit_string = strdup("");
788 }
789
790 static void
791 request_key(uint32_t time, const struct key *key, enum wl_keyboard_key_state state)
792 {
793     const char *label = NULL;
794     static uint32_t serial = 9999;
795
796     switch(data_wl.state) {
797     case KEYBOARD_STATE_DEFAULT :
798         label = key->label;
799         break;
800     case KEYBOARD_STATE_UPPERCASE :
801         label = key->uppercase;
802         break;
803     case KEYBOARD_STATE_SYMBOLS :
804         label = key->symbol;
805         break;
806     default :
807         label = key->label;
808         break;
809     }
810
811     xkb_mod_mask_t mod_mask = data_wl.state == KEYBOARD_STATE_DEFAULT ? 0 : data_wl.keysym.shift_mask;
812     uint32_t key_state = (state == WL_KEYBOARD_KEY_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED;
813
814     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);
815     switch (key->key_type) {
816         case keytype_default:
817             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
818                 break;
819
820             printf("request_key() keytype_default. append label(%s) to preedit_string(%s)\n", label, data_wl.preedit_string);
821             data_wl.preedit_string =
822                 append(data_wl.preedit_string,
823                        label);
824             request_preedit(-1);
825             break;
826         case keytype_backspace:
827             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
828                 break;
829
830             if (strlen(data_wl.preedit_string) == 0) {
831                 delete_before_cursor();
832             } else {
833                 data_wl.preedit_string[strlen(data_wl.preedit_string) - 1] = '\0';
834                 request_preedit(-1);
835             }
836             break;
837         case keytype_enter:
838             request_commit_string();
839
840             if (!data_wl.context) break;
841             zwp_input_method_context_v1_keysym(data_wl.context,
842                                serial++,
843                                time,
844                                XKB_KEY_Return, key_state, mod_mask);
845             break;
846         case keytype_space:
847             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
848                 break;
849             data_wl.preedit_string =
850                 append(data_wl.preedit_string, " ");
851             request_commit_string();
852             break;
853         case keytype_switch:
854             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
855                 break;
856             switch(data_wl.state) {
857             case KEYBOARD_STATE_DEFAULT:
858                 data_wl.state = KEYBOARD_STATE_UPPERCASE;
859                 break;
860             case KEYBOARD_STATE_UPPERCASE:
861                 data_wl.state = KEYBOARD_STATE_DEFAULT;
862                 break;
863             case KEYBOARD_STATE_SYMBOLS:
864                 data_wl.state = KEYBOARD_STATE_UPPERCASE;
865                 break;
866             }
867             break;
868         case keytype_symbols:
869             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
870                 break;
871             switch(data_wl.state) {
872             case KEYBOARD_STATE_DEFAULT:
873                 data_wl.state = KEYBOARD_STATE_SYMBOLS;
874                 break;
875             case KEYBOARD_STATE_UPPERCASE:
876                 data_wl.state = KEYBOARD_STATE_SYMBOLS;
877                 break;
878             case KEYBOARD_STATE_SYMBOLS:
879                 data_wl.state = KEYBOARD_STATE_DEFAULT;
880                 break;
881             }
882             break;
883         case keytype_tab:
884             request_commit_string();
885             if (!data_wl.context) break;
886             zwp_input_method_context_v1_keysym(data_wl.context,
887                                serial++,
888                                time,
889                                XKB_KEY_Tab, key_state, mod_mask);
890             break;
891         case keytype_arrow_up:
892             request_commit_string();
893             if (!data_wl.context) break;
894             zwp_input_method_context_v1_keysym(data_wl.context,
895                                serial++,
896                                time,
897                                XKB_KEY_Up, key_state, mod_mask);
898             break;
899         case keytype_arrow_left:
900             request_commit_string();
901             if (!data_wl.context) break;
902             zwp_input_method_context_v1_keysym(data_wl.context,
903                                serial++,
904                                time,
905                                XKB_KEY_Left, key_state, mod_mask);
906             break;
907         case keytype_arrow_right:
908             request_commit_string();
909             if (!data_wl.context) break;
910             zwp_input_method_context_v1_keysym(data_wl.context,
911                                serial++,
912                                time,
913                                XKB_KEY_Right, key_state, mod_mask);
914             break;
915         case keytype_arrow_down:
916             request_commit_string();
917             if (!data_wl.context) break;
918             zwp_input_method_context_v1_keysym(data_wl.context,
919                                serial++,
920                                time,
921                                XKB_KEY_Down, key_state, mod_mask);
922             break;
923         case keytype_style:
924             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
925                 break;
926             data_wl.preedit_style = (data_wl.preedit_style + 1) % 8; /* TODO */
927             request_preedit(-1);
928             break;
929     }
930 }
931
932 static void
933 im_context_cb_surrounding_text (void *data, struct zwp_input_method_context_v1 *im_ctx, const char *text, uint32_t cursor, uint32_t anchor)
934 {
935     printf("im_context_cb_surrounding_text\n");
936         free(data_wl.surrounding_text);
937     data_wl.surrounding_text = strdup(text);
938
939     data_wl.surrounding_cursor = cursor;
940 }
941
942 static void
943 im_context_cb_reset (void *data, struct zwp_input_method_context_v1 *im_ctx)
944 {
945     printf("im_context_cb_reset\n");
946
947     if (strlen(data_wl.preedit_string)) {
948         free(data_wl.preedit_string);
949         data_wl.preedit_string = strdup("");
950     }
951 }
952
953 static void
954 im_context_cb_content_type (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t hint, uint32_t purpose)
955 {
956     printf("im_context_cb_content_type\n");
957
958     data_wl.content_hint = hint;
959     data_wl.content_purpose = purpose;
960 }
961
962 static void
963 im_context_cb_invoke_action (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t button, uint32_t index)
964 {
965     printf("im_context_cb_invoke_action\n");
966
967     //if (button != BTN_LEFT)
968     //    return;
969
970     request_preedit(index);
971 }
972
973 static void
974 im_context_cb_commit_state (void *data, struct zwp_input_method_context_v1 *context, uint32_t serial)
975 {
976     printf("im_context_cb_commit_state\n");
977
978     const struct layout *layout;
979
980     data_wl.serial = serial;
981
982     layout = get_current_layout();
983
984     if (data_wl.surrounding_text)
985         printf("Surrounding text updated: %s\n", data_wl.surrounding_text);
986
987     if (!context) return;
988     zwp_input_method_context_v1_language(context,
989                          data_wl.serial,
990                          layout->language);
991     zwp_input_method_context_v1_text_direction(context,
992                            data_wl.serial,
993                            layout->text_direction);
994 }
995
996 static void
997 im_context_cb_preferred_language (void *data, struct zwp_input_method_context_v1 *context, const char *language)
998 {
999     printf("im_context_cb_preferred_language\n");
1000
1001     if (data_wl.preferred_language)
1002         free(data_wl.preferred_language);
1003
1004     data_wl.preferred_language = NULL;
1005
1006     if (language)
1007         data_wl.preferred_language = strdup(language);
1008 }
1009
1010 static const struct zwp_input_method_context_v1_listener input_method_context_cb_listener = {
1011     .surrounding_text = im_context_cb_surrounding_text,
1012     .reset = im_context_cb_reset,
1013     .content_type = im_context_cb_content_type,
1014     .invoke_action = im_context_cb_invoke_action,
1015     .commit_state = im_context_cb_commit_state,
1016     .preferred_language = im_context_cb_preferred_language,
1017     //for tizen only
1018     .return_key_type = NULL,
1019     .return_key_disabled = NULL,
1020     .input_panel_data = NULL,
1021     .bidi_direction = NULL,
1022     .cursor_position = NULL,
1023     .process_input_device_event = NULL,
1024     .filter_key_event = NULL,
1025     .capital_mode = NULL,
1026     .prediction_hint = NULL,
1027     .mime_type = NULL,
1028     .finalized_content = NULL,
1029     .prediction_hint_data = NULL,
1030     .input_panel_enabled = NULL,
1031 };
1032
1033 static void
1034 keysym_modifiers_add(struct wl_array *modifiers_map,
1035              const char *name)
1036 {
1037     size_t len = strlen(name) + 1;
1038     char *p;
1039
1040     p = wl_array_add(modifiers_map, len);
1041
1042     if (p == NULL)
1043         return;
1044
1045     strncpy(p, name, len);
1046 }
1047
1048 static xkb_mod_index_t
1049 keysym_modifiers_get_index(struct wl_array *modifiers_map,
1050                const char *name)
1051 {
1052     xkb_mod_index_t index = 0;
1053     char *p = modifiers_map->data;
1054
1055     while ((const char *)p < (const char *)(modifiers_map->data + modifiers_map->size)) {
1056         if (strcmp(p, name) == 0)
1057             return index;
1058
1059         index++;
1060         p += strlen(p) + 1;
1061     }
1062
1063     return XKB_MOD_INVALID;
1064 }
1065
1066 static xkb_mod_mask_t
1067 keysym_modifiers_get_mask(struct wl_array *modifiers_map,
1068               const char *name)
1069 {
1070     xkb_mod_index_t index = keysym_modifiers_get_index(modifiers_map, name);
1071
1072     if (index == XKB_MOD_INVALID)
1073         return XKB_MOD_INVALID;
1074
1075     return 1 << index;
1076 }
1077
1078 static void
1079 im_cb_activate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *context)
1080 {
1081     printf("im_cb_activate\n");
1082
1083     struct wl_array modifiers_map;
1084     const struct layout *layout;
1085
1086     if (data_wl.context)
1087         zwp_input_method_context_v1_destroy(data_wl.context);
1088
1089     if (data_wl.preedit_string)
1090         free(data_wl.preedit_string);
1091
1092     data_wl.preedit_style = 0;
1093     data_wl.preedit_string = strdup("");
1094     data_wl.content_hint = 0;
1095     data_wl.content_purpose = 0;
1096     free(data_wl.preferred_language);
1097     data_wl.preferred_language = NULL;
1098     free(data_wl.surrounding_text);
1099     data_wl.surrounding_text = NULL;
1100
1101     data_wl.serial = 0;
1102
1103     data_wl.context = context;
1104     zwp_input_method_context_v1_add_listener(context,
1105                          &input_method_context_cb_listener,
1106                          NULL);
1107
1108     wl_array_init(&modifiers_map);
1109     keysym_modifiers_add(&modifiers_map, "Shift");
1110     keysym_modifiers_add(&modifiers_map, "Control");
1111     keysym_modifiers_add(&modifiers_map, "Mod1");
1112     zwp_input_method_context_v1_modifiers_map(context, &modifiers_map);
1113     data_wl.keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift");
1114     wl_array_release(&modifiers_map);
1115
1116     layout = get_current_layout();
1117
1118     zwp_input_method_context_v1_language(context,
1119                          data_wl.serial,
1120                          layout->language);
1121     zwp_input_method_context_v1_text_direction(context,
1122                            data_wl.serial,
1123                            layout->text_direction);
1124 }
1125 static void
1126 im_cb_deactivate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
1127 {
1128     printf("im_cb_deactivate\n");
1129
1130     if (!data_wl.context)
1131         return;
1132
1133     zwp_input_method_context_v1_destroy(data_wl.context);
1134     data_wl.context = NULL;
1135 }
1136
1137 static void
1138 im_cb_destroy (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
1139 {
1140     printf("im_cb_destroy\n");
1141     zwp_input_method_v1_destroy(data_wl.input_method);
1142     data_wl.input_method = NULL;
1143 }
1144
1145 static const struct zwp_input_method_v1_listener input_method_cb_listener = {
1146     .activate = im_cb_activate,
1147     .deactivate = im_cb_deactivate,
1148     //for tizen only
1149     .destroy = im_cb_destroy,
1150     .show_input_panel = NULL,
1151     .hide_input_panel = NULL,
1152     .open_connection = NULL,
1153     .close_connection = NULL,
1154     .set_text_input_id = NULL,
1155 };
1156
1157 static void
1158 registry_handle_global(void * data, struct wl_registry * registry, uint32_t id,
1159         const char * interface, uint32_t version)
1160 {
1161     if (strcmp(interface, "wl_compositor") == 0) {
1162         data_wl.compositor = wl_registry_bind(registry, id,
1163                 &wl_compositor_interface, version);
1164         if (!data_wl.compositor) {
1165             printf("Failed to bind compositor.\n");
1166             return;
1167         }
1168         if (data_wl.enable_log)
1169             printf("Success to bind compositor.\n");
1170     } else if (strcmp(interface, "tizen_input_device_manager") == 0) {
1171         data_wl.devicemgr = wl_registry_bind(registry, id,
1172                 &tizen_input_device_manager_interface, version);
1173         if (!data_wl.devicemgr) {
1174             printf("Failed to bind input device manager");
1175             return;
1176         }
1177         if (data_wl.enable_log)
1178             printf("Success to bind tizen input device manager.");
1179         tizen_input_device_manager_add_listener(data_wl.devicemgr,
1180             &_input_device_manager_listener, data_wl.display);
1181     } else if (!strcmp(interface, "zwp_input_method_manager_v1")) {
1182         data_wl.input_method_mgr = wl_registry_bind(registry, id,
1183                 &zwp_input_method_manager_v1_interface, version);
1184     } else if (!strcmp(interface, "zwp_input_method_v1")) {
1185         data_wl.input_method = wl_registry_bind(registry, id,
1186                 &zwp_input_method_v1_interface, version);
1187         zwp_input_method_v1_add_listener(data_wl.input_method,
1188                          &input_method_cb_listener,
1189                          NULL);
1190
1191         //TODO: delte this code. this job should be done in cb_activate
1192         data_wl.preedit_string = strdup("");
1193         data_wl.content_hint = 0;
1194         data_wl.content_purpose = 0;
1195         free(data_wl.preferred_language);
1196         data_wl.preferred_language = NULL;
1197         free(data_wl.surrounding_text);
1198         data_wl.surrounding_text = NULL;
1199         data_wl.serial = 0;
1200     }
1201 }
1202
1203 static void
1204 registry_handle_global_remove(void * data, struct wl_registry * registry, uint32_t id)
1205 {
1206     if (data_wl.enable_log)
1207         printf("registry is removed. id: %d !\n", id);
1208 }
1209
1210 static const struct wl_registry_listener _registry_listener = {
1211     registry_handle_global,
1212     registry_handle_global_remove
1213 };
1214
1215 static int
1216 wayland_init(void)
1217 {
1218     memset(&data_wl, 0, sizeof(struct display));
1219     data_wl.request_notified = -1;
1220
1221     data_wl.display = wl_display_connect(NULL);
1222     if (!data_wl.display) {
1223         printf("Failed to connect wayland display\n");
1224         return 0;
1225     }
1226
1227     data_wl.queue = wl_display_create_queue(data_wl.display);
1228     if (!data_wl.queue) {
1229         printf("Failed to create queue\n");
1230         return 0;
1231     }
1232
1233     data_wl.registry = wl_display_get_registry(data_wl.display);
1234     if (!data_wl.registry) {
1235         printf("Failed to get registry\n");
1236         return 0;
1237     }
1238
1239     wl_proxy_set_queue((struct wl_proxy*)data_wl.registry, data_wl.queue);
1240     wl_registry_add_listener(data_wl.registry, &_registry_listener, NULL);
1241
1242     if (wl_display_dispatch_queue(data_wl.display, data_wl.queue) == -1) {
1243         printf("Failed to dispatch display\n");
1244         return 0;
1245     }
1246     if (wl_display_roundtrip_queue(data_wl.display, data_wl.queue) == -1) {
1247         printf("Failed to roundtrip display\n");
1248         return 0;
1249     }
1250
1251     return 1;
1252 }
1253
1254 static void
1255 wayland_deinit(void)
1256 {
1257     if (data_wl.enable_log)
1258         printf("Shutdown wayland system\n");
1259
1260     if (data_wl.init) deinit_input_generator();
1261
1262     if (data_wl.queue) wl_event_queue_destroy(data_wl.queue);
1263     if (data_wl.devicemgr) tizen_input_device_manager_destroy(data_wl.devicemgr);
1264     if (data_wl.display) {
1265         if (data_wl.input_method)
1266             zwp_input_method_v1_destroy(data_wl.input_method);
1267         zwp_input_method_manager_v1_destroy(data_wl.input_method_mgr);
1268         wl_registry_destroy(data_wl.registry);
1269         wl_display_flush(data_wl.display);
1270         wl_display_disconnect(data_wl.display);
1271     }
1272 }
1273
1274 static int
1275 epoll_init(void)
1276 {
1277     struct epoll_event ep[2];
1278
1279     data_wl.fd_epoll = epoll_create(SIZE_EPOLL);
1280     if (data_wl.fd_epoll <= 0) {
1281         printf("Failed to epoll create: %d\n", SIZE_EPOLL);
1282         return 0;
1283     }
1284
1285     data_wl.fd_display = wl_display_get_fd(data_wl.display);
1286
1287     memset(ep, 0, sizeof(struct epoll_event)*2);
1288
1289     ep[0].events = EPOLLIN | EPOLLERR | EPOLLHUP;
1290     ep[0].data.fd = data_wl.fd_display;
1291     epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, data_wl.fd_display, &ep[0]);
1292     ep[1].events = EPOLLIN | EPOLLERR | EPOLLHUP;
1293     ep[1].data.fd = STDIN_FILENO;
1294     epoll_ctl(data_wl.fd_epoll, EPOLL_CTL_ADD, 0, &ep[1]);
1295
1296     return 1;
1297 }
1298
1299 static void
1300 mainloop(void)
1301 {
1302     struct epoll_event ep[SIZE_EPOLL];
1303     int res, count, i;
1304
1305     res = epoll_init();
1306     if (!res) {
1307         printf("Failed to init epoll\n");
1308         return;
1309     }
1310
1311     data_wl.run = 1;
1312     while (data_wl.run) {
1313         res = wl_display_dispatch_queue_pending(data_wl.display, data_wl.queue);
1314         if (res < 0) {
1315             printf("Failed to dispatch pending. result: %d\n", res);
1316             data_wl.run = 0;
1317             break;
1318         }
1319         res = wl_display_flush(data_wl.display);
1320         if (res < 0) {
1321             printf("Failed to flush display. result: %d\n", res);
1322             data_wl.run = 0;
1323             break;
1324         }
1325
1326         count = epoll_wait(data_wl.fd_epoll, ep, SIZE_EPOLL, -1);
1327         for (i = 0; i < count; i++) {
1328             if (ep[i].events & EPOLLIN) {
1329                 if (ep[i].data.fd == data_wl.fd_display) {
1330                     wl_display_dispatch_queue(data_wl.display, data_wl.queue);
1331                 } else {
1332                     stdin_read();
1333                 }
1334             }
1335             if (ep[i].events & EPOLLERR) {
1336                 data_wl.run = 0;
1337             }
1338             if (ep[i].events & EPOLLHUP) {
1339                 data_wl.run = 0;
1340             }
1341         }
1342     }
1343 }
1344
1345 int
1346 main(int argc, char **argv)
1347 {
1348     int res;
1349
1350     res = wayland_init();
1351     if (!res) return 0;
1352
1353     mainloop();
1354
1355     wayland_deinit();
1356
1357     return 0;
1358 }