change wl_signal_emit_mutable into wl_signal_emit
[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(struct display *d, uint32_t time, const struct key *key, enum wl_keyboard_key_state state);
204
205 static const struct layout *
206 get_current_layout(struct display *d);
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(struct display *d, enum tizen_input_device_manager_clas clas)
277 {
278     if (d->init) {
279         printf("Already init input generator\n");
280         return;
281     }
282
283     tizen_input_device_manager_init_generator(d->devicemgr, clas);
284
285     while (d->request_notified == -1)
286         wl_display_dispatch_queue(d->display, d->queue);
287
288     if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
289         d->init = 1;
290         printf("Success to init input generator\n");
291     } else {
292         printf("Failed to init input generator: %d\n", d->request_notified);
293     }
294
295     d->clas = clas;
296     d->request_notified = -1;
297 }
298
299 static void
300 deinit_input_generator(struct display *d)
301 {
302     if (!d->init) {
303         printf("input generator is not initialized\n");
304         return;
305     }
306
307     tizen_input_device_manager_deinit_generator(d->devicemgr, d->clas);
308
309     while (d->request_notified == -1)
310         wl_display_dispatch_queue(d->display, d->queue);
311
312     if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
313         d->init = 0;
314         printf("Success to deinit input generator\n");
315     } else {
316         printf("Failed to deinit input generator: %d\n", d->request_notified);
317     }
318
319     d->request_notified = -1;
320 }
321
322 static void
323 input_generator_key(struct display *d, char *name, int type)
324 {
325     tizen_input_device_manager_generate_key(d->devicemgr, name, !!type);
326
327     while (d->request_notified == -1)
328         wl_display_dispatch_queue(d->display, d->queue);
329
330     if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
331         if (d->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", d->request_notified);
336     }
337
338     d->request_notified = -1;
339 }
340
341 static void
342 key_generate(struct display *d, char *name, int type)
343 {
344     printf("name: %s, type: %d\n", name, type);
345
346     if (!d->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(d, name, 1);
358         input_generator_key(d, name, 0);
359     } else {
360         input_generator_key(d, 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(struct display *d, int idx, int type, int x, int y)
381 {
382     tizen_input_device_manager_generate_touch(d->devicemgr, type, x, y, idx);
383
384     while (d->request_notified == -1)
385         wl_display_dispatch_queue(d->display, d->queue);
386
387     if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
388         if (d->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, d->request_notified);
393     }
394
395     d->request_notified = -1;
396 }
397
398 static void
399 touch_generate(struct display *d, int idx, int type, int x, int y)
400 {
401     if (!d->init) {
402         printf("Input generator is not initialized\n");
403         return;
404     }
405
406     if (type == POINTER_ALL) {
407         input_generator_touch(d, 0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 300, 300);
408         input_generator_touch(d, 1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 400, 400);
409         input_generator_touch(d, 2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, 500, 500);
410
411         input_generator_touch(d, 0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 310, 310);
412         input_generator_touch(d, 1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 410, 410);
413         input_generator_touch(d, 2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 510, 510);
414
415         input_generator_touch(d, 0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 320, 320);
416         input_generator_touch(d, 1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 420, 420);
417         input_generator_touch(d, 2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 520, 520);
418
419         input_generator_touch(d, 0, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 320, 320);
420         input_generator_touch(d, 1, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 420, 420);
421         input_generator_touch(d, 2, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, 520, 520);
422     } else {
423         input_generator_touch(d, idx, type, x, y);
424     }
425 }
426
427 static void
428 input_generator_mouse(struct display *d, int type, int x, int y, int button)
429 {
430     tizen_input_device_manager_generate_pointer(d->devicemgr, type, x, y, button);
431
432     while (d->request_notified == -1)
433         wl_display_dispatch_queue(d->display, d->queue);
434
435     if (d->request_notified == TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE) {
436         if (d->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, d->request_notified);
441     }
442
443     d->request_notified = -1;
444 }
445
446 static void
447 mouse_generate(struct display *d, int btn, int type, int x, int y)
448 {
449     if (!d->init) {
450         printf("Input generator is not initialized\n");
451         return;
452     }
453
454     if (type == POINTER_ALL) {
455         input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN, -1, -1, 1);
456         input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1);
457         input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1);
458         input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE, 10, 10, 1);
459         input_generator_mouse(d, TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END, -1, -1, 1);
460
461     } else {
462         input_generator_mouse(d, type, x, y, btn);
463     }
464 }
465
466 static void
467 stdin_read(struct display *d)
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(d, TIZEN_INPUT_DEVICE_MANAGER_CLAS_KEYBOARD);
496                         else if (!strncmp("touch", tmp, MAX_STR-1))
497                             init_input_generator(d, TIZEN_INPUT_DEVICE_MANAGER_CLAS_TOUCHSCREEN);
498                         else if (!strncmp("mouse", tmp, MAX_STR-1))
499                             init_input_generator(d, 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(d);
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(d, 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(d, 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(d, 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 (d->enable_log)
593             printf("request key() key_idx:%u, key_type:%u\n", idx, key_type);
594
595         layout = get_current_layout(d);
596         if (key_type == KEY_ALL) {
597             request_key(d, time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_PRESSED);
598             request_key(d, time++, &layout->keys[idx], WL_KEYBOARD_KEY_STATE_RELEASED);
599         }
600         else
601             request_key(d, time++, &layout->keys[idx], key_type);
602     } else if (!strncmp(buf, "q", MAX_STR) || !strncmp(buf, "quit", MAX_STR)) {
603         d->run = 0;
604     } else if (!strncmp(buf, "help", MAX_STR)) {
605         usage();
606     } else if (!strncmp(buf, "log", MAX_STR)) {
607         if (d->enable_log)
608             printf("Disable detailed logs\n");
609         else
610             printf("Enable detailed logs\n");
611
612         d->enable_log = !d->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     struct display *d = (struct display *)data;
625
626     if (d->enable_log)
627         printf("errorcode: %d\n", errorcode);
628     d->request_notified = errorcode;
629 }
630
631 static const struct tizen_input_device_manager_listener _input_device_manager_listener =
632 {
633     .device_add = NULL,
634     .device_remove = NULL,
635     .error = input_device_manager_handle_error,
636     .block_expired = NULL,
637 };
638
639 static const struct layout *
640 get_current_layout(struct display *d)
641 {
642     switch (d->content_purpose) {
643         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
644         case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
645             return &numeric_layout;
646         default:
647             return &normal_layout;
648     }
649 }
650
651 static const char *
652 prev_utf8_char(const char *s, const char *p)
653 {
654     for (--p; p >= s; --p) {
655         if ((*p & 0xc0) != 0x80)
656             return p;
657     }
658     return NULL;
659 }
660
661 static void
662 delete_before_cursor(struct display *d)
663 {
664     const char *start, *end;
665
666     if (!d->surrounding_text) {
667         printf("delete_before_cursor: No surrounding text available\n");
668         return;
669     }
670
671     start = prev_utf8_char(d->surrounding_text,
672                    d->surrounding_text + d->surrounding_cursor);
673     if (!start) {
674         printf("delete_before_cursor: No previous character to delete\n");
675         return;
676     }
677
678     end = d->surrounding_text + d->surrounding_cursor;
679
680     zwp_input_method_context_v1_delete_surrounding_text(d->context,
681                                 (start - d->surrounding_text) - d->surrounding_cursor,
682                                 end - start);
683     zwp_input_method_context_v1_commit_string(d->context,
684                           d->serial,
685                           "");
686
687     /* Update surrounding text */
688     d->surrounding_cursor = start - d->surrounding_text;
689     d->surrounding_text[d->surrounding_cursor] = '\0';
690     if (*end)
691         memmove(d->surrounding_text + d->surrounding_cursor, end, strlen(end));
692 }
693
694 static char *
695 append(char *s1, const char *s2)
696 {
697     int len1, len2;
698     char *s = NULL;
699
700     len1 = strlen(s1);
701     len2 = strlen(s2);
702     s = realloc(s1, len1 + len2 + 1);
703     if (s == NULL) {
704         printf("alloc fail");
705         return NULL;
706     }
707     memcpy(s + len1, s2, len2);
708     s[len1 + len2] = '\0';
709
710     return s;
711 }
712
713 static void
714 request_preedit(struct display *d, int32_t cursor)
715 {
716     printf("request_preedit() preedit_string:%s\n", d->preedit_string);
717     uint32_t index = strlen(d->preedit_string);
718
719     if (!d->context) return;
720
721     if (d->preedit_style)
722         zwp_input_method_context_v1_preedit_styling(d->context,
723                                 0,
724                                 strlen(d->preedit_string),
725                                 d->preedit_style);
726     if (cursor > 0)
727         index = cursor;
728     zwp_input_method_context_v1_preedit_cursor(d->context,
729                            index);
730     zwp_input_method_context_v1_preedit_string(d->context,
731                            d->serial,
732                            d->preedit_string,
733                            d->preedit_string);
734 }
735
736 static char *
737 insert_text(const char *text, uint32_t offset, const char *insert)
738 {
739     int tlen = strlen(text), ilen = strlen(insert);
740     char *new_text = NULL;
741
742     new_text = malloc(tlen + ilen + 1);
743     if (new_text == NULL) {
744         printf("alloc fail");
745         return NULL;
746     }
747
748     memcpy(new_text, text, offset);
749     memcpy(new_text + offset, insert, ilen);
750     memcpy(new_text + offset + ilen, text + offset, tlen - offset);
751     new_text[tlen + ilen] = '\0';
752
753     return new_text;
754 }
755
756 static void
757 request_commit_string(struct display *d)
758 {
759     char *surrounding_text;
760
761     printf("request_commit_string()\n");
762
763     if (!d->preedit_string ||
764         strlen(d->preedit_string) == 0)
765         return;
766     printf("request_commit_string() preedit_string:%s\n", d->preedit_string);
767
768     if (!d->context) return;
769
770     zwp_input_method_context_v1_cursor_position(d->context,
771                             0, 0);
772     zwp_input_method_context_v1_commit_string(d->context,
773                           d->serial,
774                           d->preedit_string);
775
776     if (d->surrounding_text) {
777         surrounding_text = insert_text(d->surrounding_text,
778                            d->surrounding_cursor,
779                            d->preedit_string);
780         free(d->surrounding_text);
781         d->surrounding_text = surrounding_text;
782         d->surrounding_cursor += strlen(d->preedit_string);
783     } else {
784         d->surrounding_text = strdup(d->preedit_string);
785         d->surrounding_cursor = strlen(d->preedit_string);
786     }
787
788     free(d->preedit_string);
789     d->preedit_string = strdup("");
790 }
791
792 static void
793 request_key(struct display *d, uint32_t time, const struct key *key, enum wl_keyboard_key_state state)
794 {
795     const char *label = NULL;
796     static uint32_t serial = 9999;
797
798     switch(d->state) {
799     case KEYBOARD_STATE_DEFAULT :
800         label = key->label;
801         break;
802     case KEYBOARD_STATE_UPPERCASE :
803         label = key->uppercase;
804         break;
805     case KEYBOARD_STATE_SYMBOLS :
806         label = key->symbol;
807         break;
808     default :
809         label = key->label;
810         break;
811     }
812
813     xkb_mod_mask_t mod_mask = d->state == KEYBOARD_STATE_DEFAULT ? 0 : d->keysym.shift_mask;
814     uint32_t key_state = (state == WL_KEYBOARD_KEY_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED;
815
816     printf("request_key() d->state:%d, key->key_type:%d, pressed:%u, label:%s\n", d->state, key->key_type, key_state, label);
817     switch (key->key_type) {
818         case keytype_default:
819             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
820                 break;
821
822             printf("request_key() keytype_default. append label(%s) to preedit_string(%s)\n", label, d->preedit_string);
823             d->preedit_string =
824                 append(d->preedit_string,
825                        label);
826             request_preedit(d, -1);
827             break;
828         case keytype_backspace:
829             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
830                 break;
831
832             if (strlen(d->preedit_string) == 0) {
833                 delete_before_cursor(d);
834             } else {
835                 d->preedit_string[strlen(d->preedit_string) - 1] = '\0';
836                 request_preedit(d, -1);
837             }
838             break;
839         case keytype_enter:
840             request_commit_string(d);
841
842             if (!d->context) break;
843             zwp_input_method_context_v1_keysym(d->context,
844                                serial++,
845                                time,
846                                XKB_KEY_Return, key_state, mod_mask);
847             break;
848         case keytype_space:
849             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
850                 break;
851             d->preedit_string =
852                 append(d->preedit_string, " ");
853             request_commit_string(d);
854             break;
855         case keytype_switch:
856             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
857                 break;
858             switch(d->state) {
859             case KEYBOARD_STATE_DEFAULT:
860                 d->state = KEYBOARD_STATE_UPPERCASE;
861                 break;
862             case KEYBOARD_STATE_UPPERCASE:
863                 d->state = KEYBOARD_STATE_DEFAULT;
864                 break;
865             case KEYBOARD_STATE_SYMBOLS:
866                 d->state = KEYBOARD_STATE_UPPERCASE;
867                 break;
868             }
869             break;
870         case keytype_symbols:
871             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
872                 break;
873             switch(d->state) {
874             case KEYBOARD_STATE_DEFAULT:
875                 d->state = KEYBOARD_STATE_SYMBOLS;
876                 break;
877             case KEYBOARD_STATE_UPPERCASE:
878                 d->state = KEYBOARD_STATE_SYMBOLS;
879                 break;
880             case KEYBOARD_STATE_SYMBOLS:
881                 d->state = KEYBOARD_STATE_DEFAULT;
882                 break;
883             }
884             break;
885         case keytype_tab:
886             request_commit_string(d);
887             if (!d->context) break;
888             zwp_input_method_context_v1_keysym(d->context,
889                                serial++,
890                                time,
891                                XKB_KEY_Tab, key_state, mod_mask);
892             break;
893         case keytype_arrow_up:
894             request_commit_string(d);
895             if (!d->context) break;
896             zwp_input_method_context_v1_keysym(d->context,
897                                serial++,
898                                time,
899                                XKB_KEY_Up, key_state, mod_mask);
900             break;
901         case keytype_arrow_left:
902             request_commit_string(d);
903             if (!d->context) break;
904             zwp_input_method_context_v1_keysym(d->context,
905                                serial++,
906                                time,
907                                XKB_KEY_Left, key_state, mod_mask);
908             break;
909         case keytype_arrow_right:
910             request_commit_string(d);
911             if (!d->context) break;
912             zwp_input_method_context_v1_keysym(d->context,
913                                serial++,
914                                time,
915                                XKB_KEY_Right, key_state, mod_mask);
916             break;
917         case keytype_arrow_down:
918             request_commit_string(d);
919             if (!d->context) break;
920             zwp_input_method_context_v1_keysym(d->context,
921                                serial++,
922                                time,
923                                XKB_KEY_Down, key_state, mod_mask);
924             break;
925         case keytype_style:
926             if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
927                 break;
928             d->preedit_style = (d->preedit_style + 1) % 8; /* TODO */
929             request_preedit(d, -1);
930             break;
931     }
932 }
933
934 static void
935 im_context_cb_surrounding_text (void *data, struct zwp_input_method_context_v1 *im_ctx, const char *text, uint32_t cursor, uint32_t anchor)
936 {
937     struct display *d = (struct display *)data;
938
939     printf("im_context_cb_surrounding_text\n");
940     free(d->surrounding_text);
941
942     d->surrounding_text = strdup(text);
943     d->surrounding_cursor = cursor;
944 }
945
946 static void
947 im_context_cb_reset (void *data, struct zwp_input_method_context_v1 *im_ctx)
948 {
949     struct display *d = (struct display *)data;
950
951     printf("im_context_cb_reset\n");
952
953     if (strlen(d->preedit_string)) {
954         free(d->preedit_string);
955         d->preedit_string = strdup("");
956     }
957 }
958
959 static void
960 im_context_cb_content_type (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t hint, uint32_t purpose)
961 {
962     struct display *d = (struct display *)data;
963
964     printf("im_context_cb_content_type\n");
965
966     d->content_hint = hint;
967     d->content_purpose = purpose;
968 }
969
970 static void
971 im_context_cb_invoke_action (void *data, struct zwp_input_method_context_v1 *im_ctx, uint32_t button, uint32_t index)
972 {
973     struct display *d = (struct display *)data;
974
975     printf("im_context_cb_invoke_action\n");
976
977     //if (button != BTN_LEFT)
978     //    return;
979
980     request_preedit(d, index);
981 }
982
983 static void
984 im_context_cb_commit_state (void *data, struct zwp_input_method_context_v1 *context, uint32_t serial)
985 {
986     struct display *d = (struct display *)data;
987     const struct layout *layout;
988
989     printf("im_context_cb_commit_state\n");
990     d->serial = serial;
991
992     layout = get_current_layout(d);
993
994     if (d->surrounding_text)
995         printf("Surrounding text updated: %s\n", d->surrounding_text);
996
997     if (!context) return;
998     zwp_input_method_context_v1_language(context,
999                          d->serial,
1000                          layout->language);
1001     zwp_input_method_context_v1_text_direction(context,
1002                            d->serial,
1003                            layout->text_direction);
1004 }
1005
1006 static void
1007 im_context_cb_preferred_language (void *data, struct zwp_input_method_context_v1 *context, const char *language)
1008 {
1009     struct display *d = (struct display *)data;
1010
1011     printf("im_context_cb_preferred_language\n");
1012
1013     if (d->preferred_language)
1014         free(d->preferred_language);
1015
1016     d->preferred_language = NULL;
1017
1018     if (language)
1019         d->preferred_language = strdup(language);
1020 }
1021
1022 static const struct zwp_input_method_context_v1_listener input_method_context_cb_listener = {
1023     .surrounding_text = im_context_cb_surrounding_text,
1024     .reset = im_context_cb_reset,
1025     .content_type = im_context_cb_content_type,
1026     .invoke_action = im_context_cb_invoke_action,
1027     .commit_state = im_context_cb_commit_state,
1028     .preferred_language = im_context_cb_preferred_language,
1029     //for tizen only
1030     .return_key_type = NULL,
1031     .return_key_disabled = NULL,
1032     .input_panel_data = NULL,
1033     .bidi_direction = NULL,
1034     .cursor_position = NULL,
1035     .process_input_device_event = NULL,
1036     .filter_key_event = NULL,
1037     .capital_mode = NULL,
1038     .prediction_hint = NULL,
1039     .mime_type = NULL,
1040     .finalized_content = NULL,
1041     .prediction_hint_data = NULL,
1042     .input_panel_enabled = NULL,
1043 };
1044
1045 static void
1046 keysym_modifiers_add(struct wl_array *modifiers_map,
1047              const char *name)
1048 {
1049     size_t len = strlen(name) + 1;
1050     char *p;
1051
1052     p = wl_array_add(modifiers_map, len);
1053
1054     if (p == NULL)
1055         return;
1056
1057     strncpy(p, name, len);
1058 }
1059
1060 static xkb_mod_index_t
1061 keysym_modifiers_get_index(struct wl_array *modifiers_map,
1062                const char *name)
1063 {
1064     xkb_mod_index_t index = 0;
1065     char *p = modifiers_map->data;
1066
1067     while ((const char *)p < (const char *)(modifiers_map->data + modifiers_map->size)) {
1068         if (strcmp(p, name) == 0)
1069             return index;
1070
1071         index++;
1072         p += strlen(p) + 1;
1073     }
1074
1075     return XKB_MOD_INVALID;
1076 }
1077
1078 static xkb_mod_mask_t
1079 keysym_modifiers_get_mask(struct wl_array *modifiers_map,
1080               const char *name)
1081 {
1082     xkb_mod_index_t index = keysym_modifiers_get_index(modifiers_map, name);
1083
1084     if (index == XKB_MOD_INVALID)
1085         return XKB_MOD_INVALID;
1086
1087     return 1 << index;
1088 }
1089
1090 static void
1091 im_cb_activate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *context)
1092 {
1093     struct display *d = (struct display *)data;
1094
1095     printf("im_cb_activate\n");
1096
1097     struct wl_array modifiers_map;
1098     const struct layout *layout;
1099
1100     if (d->context)
1101         zwp_input_method_context_v1_destroy(d->context);
1102
1103     if (d->preedit_string)
1104         free(d->preedit_string);
1105
1106     d->preedit_style = 0;
1107     d->preedit_string = strdup("");
1108     d->content_hint = 0;
1109     d->content_purpose = 0;
1110     free(d->preferred_language);
1111     d->preferred_language = NULL;
1112     free(d->surrounding_text);
1113     d->surrounding_text = NULL;
1114
1115     d->serial = 0;
1116
1117     d->context = context;
1118     zwp_input_method_context_v1_add_listener(context,
1119                          &input_method_context_cb_listener,
1120                          d);
1121
1122     wl_array_init(&modifiers_map);
1123     keysym_modifiers_add(&modifiers_map, "Shift");
1124     keysym_modifiers_add(&modifiers_map, "Control");
1125     keysym_modifiers_add(&modifiers_map, "Mod1");
1126     zwp_input_method_context_v1_modifiers_map(context, &modifiers_map);
1127     d->keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift");
1128     wl_array_release(&modifiers_map);
1129
1130     layout = get_current_layout(d);
1131
1132     zwp_input_method_context_v1_language(context,
1133                          d->serial,
1134                          layout->language);
1135     zwp_input_method_context_v1_text_direction(context,
1136                            d->serial,
1137                            layout->text_direction);
1138 }
1139 static void
1140 im_cb_deactivate (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
1141 {
1142     struct display *d = (struct display *)data;
1143
1144     printf("im_cb_deactivate\n");
1145
1146     if (!d->context)
1147         return;
1148
1149     zwp_input_method_context_v1_destroy(d->context);
1150     d->context = NULL;
1151 }
1152
1153 static void
1154 im_cb_destroy (void *data, struct zwp_input_method_v1 *input_method, struct zwp_input_method_context_v1 *im_ctx)
1155 {
1156     struct display *d = (struct display *)data;
1157
1158     printf("im_cb_destroy\n");
1159     zwp_input_method_v1_destroy(d->input_method);
1160     d->input_method = NULL;
1161 }
1162
1163 static const struct zwp_input_method_v1_listener input_method_cb_listener = {
1164     .activate = im_cb_activate,
1165     .deactivate = im_cb_deactivate,
1166     //for tizen only
1167     .destroy = im_cb_destroy,
1168     .show_input_panel = NULL,
1169     .hide_input_panel = NULL,
1170     .open_connection = NULL,
1171     .close_connection = NULL,
1172     .set_text_input_id = NULL,
1173 };
1174
1175 static void
1176 registry_handle_global(void * data, struct wl_registry * registry, uint32_t id,
1177         const char * interface, uint32_t version)
1178 {
1179     struct display *d = (struct display *)data;
1180
1181     if (strcmp(interface, "wl_compositor") == 0) {
1182         d->compositor = wl_registry_bind(registry, id,
1183                 &wl_compositor_interface, version);
1184         if (!d->compositor) {
1185             printf("Failed to bind compositor.\n");
1186             return;
1187         }
1188         if (d->enable_log)
1189             printf("Success to bind compositor.\n");
1190     } else if (strcmp(interface, "tizen_input_device_manager") == 0) {
1191         d->devicemgr = wl_registry_bind(registry, id,
1192                 &tizen_input_device_manager_interface, version);
1193         if (!d->devicemgr) {
1194             printf("Failed to bind input device manager");
1195             return;
1196         }
1197         if (d->enable_log)
1198             printf("Success to bind tizen input device manager.");
1199         tizen_input_device_manager_add_listener(d->devicemgr,
1200             &_input_device_manager_listener, d);
1201     } else if (!strcmp(interface, "zwp_input_method_manager_v1")) {
1202         d->input_method_mgr = wl_registry_bind(registry, id,
1203                 &zwp_input_method_manager_v1_interface, version);
1204     } else if (!strcmp(interface, "zwp_input_method_v1")) {
1205         d->input_method = wl_registry_bind(registry, id,
1206                 &zwp_input_method_v1_interface, version);
1207         zwp_input_method_v1_add_listener(d->input_method,
1208                          &input_method_cb_listener,
1209                          d);
1210
1211         //TODO: delte this code. this job should be done in cb_activate
1212         d->preedit_string = strdup("");
1213         d->content_hint = 0;
1214         d->content_purpose = 0;
1215         free(d->preferred_language);
1216         d->preferred_language = NULL;
1217         free(d->surrounding_text);
1218         d->surrounding_text = NULL;
1219         d->serial = 0;
1220     }
1221 }
1222
1223 static void
1224 registry_handle_global_remove(void * data, struct wl_registry * registry, uint32_t id)
1225 {
1226     struct display *d = (struct display *)data;
1227
1228     if (d->enable_log)
1229         printf("registry is removed. id: %d !\n", id);
1230 }
1231
1232 static const struct wl_registry_listener _registry_listener = {
1233     registry_handle_global,
1234     registry_handle_global_remove
1235 };
1236
1237 static int
1238 wayland_init(struct display *d)
1239 {
1240     memset(d, 0, sizeof(struct display));
1241     d->request_notified = -1;
1242
1243     d->display = wl_display_connect(NULL);
1244     if (!d->display) {
1245         printf("Failed to connect wayland display\n");
1246         return 0;
1247     }
1248
1249     d->queue = wl_display_create_queue(d->display);
1250     if (!d->queue) {
1251         printf("Failed to create queue\n");
1252         return 0;
1253     }
1254
1255     d->registry = wl_display_get_registry(d->display);
1256     if (!d->registry) {
1257         printf("Failed to get registry\n");
1258         return 0;
1259     }
1260
1261     wl_proxy_set_queue((struct wl_proxy*)d->registry, d->queue);
1262     wl_registry_add_listener(d->registry, &_registry_listener, d);
1263
1264     if (wl_display_dispatch_queue(d->display, d->queue) == -1) {
1265         printf("Failed to dispatch display\n");
1266         return 0;
1267     }
1268     if (wl_display_roundtrip_queue(d->display, d->queue) == -1) {
1269         printf("Failed to roundtrip display\n");
1270         return 0;
1271     }
1272
1273     return 1;
1274 }
1275
1276 static void
1277 wayland_deinit(struct display *d)
1278 {
1279     if (d->enable_log)
1280         printf("Shutdown wayland system\n");
1281
1282     if (d->init) deinit_input_generator(d);
1283
1284     if (d->queue) wl_event_queue_destroy(d->queue);
1285     if (d->devicemgr) tizen_input_device_manager_destroy(d->devicemgr);
1286     if (d->display) {
1287         if (d->input_method)
1288             zwp_input_method_v1_destroy(d->input_method);
1289         zwp_input_method_manager_v1_destroy(d->input_method_mgr);
1290         wl_registry_destroy(d->registry);
1291         wl_display_flush(d->display);
1292         wl_display_disconnect(d->display);
1293     }
1294 }
1295
1296 static int
1297 epoll_init(struct display *d)
1298 {
1299     struct epoll_event ep[2];
1300
1301     d->fd_epoll = epoll_create(SIZE_EPOLL);
1302     if (d->fd_epoll <= 0) {
1303         printf("Failed to epoll create: %d\n", SIZE_EPOLL);
1304         return 0;
1305     }
1306
1307     d->fd_display = wl_display_get_fd(d->display);
1308
1309     memset(ep, 0, sizeof(struct epoll_event)*2);
1310
1311     ep[0].events = EPOLLIN | EPOLLERR | EPOLLHUP;
1312     ep[0].data.fd = d->fd_display;
1313     epoll_ctl(d->fd_epoll, EPOLL_CTL_ADD, d->fd_display, &ep[0]);
1314     ep[1].events = EPOLLIN | EPOLLERR | EPOLLHUP;
1315     ep[1].data.fd = STDIN_FILENO;
1316     epoll_ctl(d->fd_epoll, EPOLL_CTL_ADD, 0, &ep[1]);
1317
1318     return 1;
1319 }
1320
1321 static void
1322 mainloop(struct display *d)
1323 {
1324     struct epoll_event ep[SIZE_EPOLL];
1325     int res, count, i;
1326
1327     res = epoll_init(d);
1328     if (!res) {
1329         printf("Failed to init epoll\n");
1330         return;
1331     }
1332
1333     d->run = 1;
1334     while (d->run) {
1335         res = wl_display_dispatch_queue_pending(d->display, d->queue);
1336         if (res < 0) {
1337             printf("Failed to dispatch pending. result: %d\n", res);
1338             d->run = 0;
1339             break;
1340         }
1341         res = wl_display_flush(d->display);
1342         if (res < 0) {
1343             printf("Failed to flush display. result: %d\n", res);
1344             d->run = 0;
1345             break;
1346         }
1347
1348         count = epoll_wait(d->fd_epoll, ep, SIZE_EPOLL, -1);
1349         for (i = 0; i < count; i++) {
1350             if (ep[i].events & EPOLLIN) {
1351                 if (ep[i].data.fd == d->fd_display) {
1352                     wl_display_dispatch_queue(d->display, d->queue);
1353                 } else {
1354                     stdin_read(d);
1355                 }
1356             }
1357             if (ep[i].events & EPOLLERR) {
1358                 d->run = 0;
1359             }
1360             if (ep[i].events & EPOLLHUP) {
1361                 d->run = 0;
1362             }
1363         }
1364     }
1365 }
1366
1367 int
1368 main(int argc, char **argv)
1369 {
1370     int res;
1371     struct display *d = &data_wl;
1372
1373     res = wayland_init(d);
1374     if (!res) return 0;
1375
1376     mainloop(d);
1377
1378     wayland_deinit(d);
1379
1380     return 0;
1381 }