Reduce the duplicate code
[platform/core/uifw/isf.git] / ism / extras / wayland_immodule / wayland_imcontext.c
1 /*
2  * Copyright © 2012, 2013 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include "scim_private.h"
24 #include <unistd.h>
25
26 #include <Ecore.h>
27 #include <Ecore_Evas.h>
28 #include <Ecore_Input.h>
29 #include <Ecore_Wayland.h>
30 #include <dlog.h>
31 #include <wctype.h>
32 #ifdef HAVE_VCONF
33 #include <vconf.h>
34 #endif
35 #include "isf_debug.h"
36
37 #include "wayland_imcontext.h"
38
39 #ifdef LOG_TAG
40 # undef LOG_TAG
41 #endif
42 #define LOG_TAG "IMMODULE"
43
44 #define IME_DEVICE_NAME "ime"
45
46 #define HIDE_TIMER_INTERVAL     0.05
47 #define WAIT_FOR_FILTER_DONE_SECOND 2
48
49 #define MOD_SHIFT_MASK      0x01
50 #define MOD_CAPS_MASK       0x02
51 #define MOD_CONTROL_MASK    0x04
52 #define MOD_ALT_MASK        0x08
53 #define MOD_NUM_MASK        0x100
54 #define MOD_Mod5_MASK       0x80
55
56 #define VCONFKEY_AUTOPERIOD_ALLOW_BOOL  "file/private/isf/autoperiod_allow"
57 #define VCONFKEY_AUTOCAPITAL_ALLOW_BOOL "file/private/isf/autocapital_allow"
58
59 typedef enum {
60     INPUT_LANG_URDU,
61     INPUT_LANG_HINDI,
62     INPUT_LANG_BENGALI_IN,
63     INPUT_LANG_BENGALI_BD,
64     INPUT_LANG_ASSAMESE,
65     INPUT_LANG_PUNJABI,
66     INPUT_LANG_NEPALI,
67     INPUT_LANG_ORIYA,
68     INPUT_LANG_MAITHILI,
69     INPUT_LANG_ARMENIAN,
70     INPUT_LANG_CN,
71     INPUT_LANG_CN_HK,
72     INPUT_LANG_CN_TW,
73     INPUT_LANG_JAPANESE,
74     INPUT_LANG_KHMER,
75     INPUT_LANG_KOREAN,
76     INPUT_LANG_BURMESE,
77     INPUT_LANG_OTHER
78 } Input_Language;
79
80 const double DOUBLE_SPACE_INTERVAL = 1.0;
81
82 static Eina_Bool _clear_hide_timer();
83 static Ecore_Timer *_hide_timer  = NULL;
84
85 #ifndef ENABLE_HIDE_PANEL_KEY
86 static const char *_ecore_imf_event_empty = "";
87 #endif
88
89 // TIZEN_ONLY(20150708): Support back key
90 #define BACK_KEY "XF86Back"
91 #define OLD_BACK_KEY "XF86Stop"
92
93 static Eina_Bool             will_hide = EINA_FALSE;
94 static Eina_Bool             ignore_hide = EINA_FALSE;
95
96 static Ecore_Event_Filter   *_ecore_event_filter_handler = NULL;
97 static Ecore_IMF_Context    *_focused_ctx                = NULL;
98 static Ecore_IMF_Context    *_show_req_ctx               = NULL;
99 static Ecore_IMF_Context    *_hide_req_ctx               = NULL;
100 static Ecore_IMF_Context    *_focus_req_ctx              = NULL;
101 static Ecore_IMF_Context    *_input_panel_ctx            = NULL;
102
103 static Eina_Rectangle        _keyboard_geometry = {0, 0, 0, 0};
104
105 static Ecore_IMF_Input_Panel_State _input_panel_state    = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
106 static Ecore_Event_Handler *_win_focus_out_handler       = NULL;
107 static Ecore_Event_Handler *_conformant_change_handler   = NULL;
108
109 static Eina_Bool             _custom_conformant_event     = EINA_FALSE;
110 static Eina_Bool             _received_will_hide_event    = EINA_FALSE;
111 static Eina_Bool             _conformant_reset_done       = EINA_FALSE;
112 static Eina_Bool             _conformant_reset_started    = EINA_FALSE;
113 static Evas                 *_active_context_canvas       = NULL;
114 static unsigned int          _active_context_window_id    = 0;
115
116 static Ecore_Device         *_ime_device = NULL;
117
118 static double                space_key_time               = 0.0;
119 static Eina_Bool             autoperiod_allow             = EINA_FALSE;
120 static Eina_Bool             autocap_allow                = EINA_FALSE;
121 static Eina_Bool             hw_keyboard_mode             = EINA_FALSE;
122
123 static Input_Language        input_lang                   = INPUT_LANG_OTHER;
124 //
125
126 typedef struct __LanguageInfo {
127     const char *code;
128     Input_Language lang;
129     Eina_Unicode punc_code;
130     Eina_Bool auto_capital_valid;
131 } LanguageInfo;
132
133 static LanguageInfo __language_infos [] = {
134     { "ur_PK",  INPUT_LANG_URDU,        0x06D4, EINA_TRUE },
135     { "hi_IN",  INPUT_LANG_HINDI,       0x0964, EINA_FALSE },
136     { "bn_IN",  INPUT_LANG_BENGALI_IN,  0x0964, EINA_TRUE },
137     { "bn_BD",  INPUT_LANG_BENGALI_BD,  0x0964, EINA_TRUE },
138     { "as_IN",  INPUT_LANG_ASSAMESE,    0x0964, EINA_TRUE },
139     { "pa_IN",  INPUT_LANG_PUNJABI,     0x0964, EINA_TRUE },
140     { "ne_NP",  INPUT_LANG_NEPALI,      0x0964, EINA_TRUE },
141     { "or_IN",  INPUT_LANG_ORIYA,       0x0964, EINA_TRUE },
142     { "mai_IN", INPUT_LANG_MAITHILI,    0x0964, EINA_TRUE },
143     { "hy_AM",  INPUT_LANG_ARMENIAN,    0x0589, EINA_TRUE },
144     { "zh_CN",  INPUT_LANG_CN,          0x3002, EINA_FALSE },
145     { "zh_HK",  INPUT_LANG_CN_HK,       0x3002, EINA_FALSE },
146     { "zh_TW",  INPUT_LANG_CN_TW,       0x3002, EINA_FALSE },
147     { "ja_JP",  INPUT_LANG_JAPANESE,    0x3002, EINA_FALSE },
148     { "km_KH",  INPUT_LANG_KHMER,       0x17D4, EINA_TRUE },
149     { "ko_KR",  INPUT_LANG_KOREAN,      0x002E, EINA_FALSE },
150 };
151
152 struct _WaylandIMContext
153 {
154     Ecore_IMF_Context *ctx;
155
156     struct wl_text_input_manager *text_input_manager;
157     struct wl_text_input *text_input;
158
159     Ecore_Wl_Window *window;
160     Ecore_Wl_Input  *input;
161     Evas            *canvas;
162
163     char *preedit_text;
164     char *preedit_commit;
165     char *language;
166     Eina_List *preedit_attrs;
167     int32_t preedit_cursor;
168
169     struct
170     {
171         Eina_List *attrs;
172         int32_t cursor;
173     } pending_preedit;
174
175     int32_t cursor_position;
176
177     struct
178     {
179         int x;
180         int y;
181         int width;
182         int height;
183     } cursor_location;
184
185     xkb_mod_mask_t control_mask;
186     xkb_mod_mask_t alt_mask;
187     xkb_mod_mask_t shift_mask;
188     xkb_mod_mask_t caps_mask;
189     xkb_mod_mask_t num_mask;
190
191     uint32_t serial;
192     uint32_t content_purpose;
193     uint32_t content_hint;
194     Ecore_IMF_Input_Panel_Layout input_panel_layout;
195
196     // TIZEN_ONLY(20150716): Support return key type
197     uint32_t return_key_type;
198
199     Eina_Bool return_key_disabled;
200
201     void *imdata;
202     uint32_t imdata_size;
203
204     uint32_t bidi_direction;
205
206     void *input_panel_data;
207     uint32_t input_panel_data_length;
208
209     struct
210     {
211         uint32_t serial;
212         uint32_t state;
213     } last_key_event_filter;
214     Eina_List *keysym_list;
215
216     uint32_t reset_serial;
217
218     Eina_Bool has_conformant;
219     //
220 };
221
222 // TIZEN_ONLY(20150708): Support back key
223 static void _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant);
224 static Eina_Bool show_input_panel(Ecore_IMF_Context *ctx);
225
226 static void
227 _device_info_free (void *data EINA_UNUSED, void *ev)
228 {
229     Ecore_Event_Device_Info *e;
230
231     e = ev;
232     eina_stringshare_del (e->name);
233     eina_stringshare_del (e->identifier);
234     eina_stringshare_del (e->seatname);
235
236     free (e);
237 }
238
239 void
240 _device_info_send (unsigned int window, Eina_Bool flag)
241 {
242     Ecore_Event_Device_Info *e;
243
244     if (!(e = calloc (1, sizeof (Ecore_Event_Device_Info)))) return;
245
246     e->name = eina_stringshare_ref (IME_DEVICE_NAME);
247     e->identifier = eina_stringshare_ref (IME_DEVICE_NAME);
248     e->seatname = eina_stringshare_ref (IME_DEVICE_NAME);
249     e->clas = ECORE_DEVICE_CLASS_KEYBOARD;
250     e->window = window;
251
252     if (flag)
253         ecore_event_add (ECORE_EVENT_DEVICE_ADD, e, _device_info_free, NULL);
254     else
255         ecore_event_add (ECORE_EVENT_DEVICE_DEL, e, _device_info_free, NULL);
256 }
257
258 static void
259 get_input_language ()
260 {
261     unsigned int i;
262     char *input_lang_str = vconf_get_str (VCONFKEY_ISF_INPUT_LANGUAGE);
263     if (!input_lang_str) return;
264     LOGD ("language %s", input_lang_str);
265     input_lang = INPUT_LANG_OTHER;
266
267     for (i = 0; i < (sizeof (__language_infos) / sizeof (__language_infos[0])); i++) {
268         if (strcmp (input_lang_str, __language_infos[i].code) == 0) {
269             input_lang = __language_infos[i].lang;
270             break;
271         }
272     }
273
274     free (input_lang_str);
275 }
276
277 static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
278 {
279     autoperiod_allow = vconf_keynode_get_bool (key);
280 }
281
282 static void autocapital_allow_changed_cb (keynode_t *key, void* data)
283 {
284     autocap_allow = vconf_keynode_get_bool (key);
285 }
286
287 static void input_language_changed_cb (keynode_t *key, void* data)
288 {
289     get_input_language ();
290 }
291
292 static Eina_Bool
293 check_symbol (Eina_Unicode ucode, Eina_Unicode symbols[], int symbol_num)
294 {
295     int i;
296     for (i = 0; i < symbol_num; i++) {
297         // Check symbol
298         if (ucode == symbols[i])
299             return EINA_TRUE;
300     }
301
302     return EINA_FALSE;
303 }
304
305 static Eina_Bool
306 check_space_symbol (Eina_Unicode uchar)
307 {
308     Eina_Unicode space_symbols[] = {' ', 0x00A0 /* no-break space */, 0x3000 /* ideographic space */};
309     const int symbol_num = sizeof (space_symbols) / sizeof (space_symbols[0]);
310
311     return check_symbol (uchar, space_symbols, symbol_num);
312 }
313
314 static void
315 autoperiod_insert (Ecore_IMF_Context *ctx)
316 {
317     char *plain_str = NULL;
318     int cursor_pos = 0;
319     Eina_Unicode *ustr = NULL;
320     Ecore_IMF_Event_Delete_Surrounding ev;
321     char *fullstop_mark = NULL;
322     size_t ulen = 0;
323     int del_chars = 0;
324     WaylandIMContext *imcontext = NULL;
325
326     if (autoperiod_allow == EINA_FALSE)
327         return;
328
329     if (!ctx) return;
330
331     Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
332     if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
333         return;
334
335     if ((ecore_time_get () - space_key_time) > DOUBLE_SPACE_INTERVAL)
336         goto done;
337
338     imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
339     if (!imcontext) return;
340
341     ecore_imf_context_surrounding_get (ctx, &plain_str, NULL);
342     if (!plain_str) goto done;
343
344     cursor_pos = imcontext->cursor_position;
345
346     // Convert string from UTF-8 to unicode
347     ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
348     if (!ustr) goto done;
349
350     ulen = eina_unicode_strlen (ustr);
351
352     if (cursor_pos < 2 || cursor_pos > (int)ulen) {
353         LOGD ("invalid range. cursor pos : %d, length : %d\n", cursor_pos, ulen);
354         goto done;
355     }
356
357     if (check_space_symbol (ustr[cursor_pos-1])) {
358         // any character (except space & punctuation) + press space key twice in short time
359         if (!(iswpunct (ustr[cursor_pos-2]) || check_space_symbol (ustr[cursor_pos-2])) &&
360             iswprint(ustr[cursor_pos-2])) {
361             del_chars = 1;
362         }
363         // any character (except space & punctuation) + space + press space key twice in short time
364         else if (cursor_pos >= 3 &&
365                  check_space_symbol (ustr[cursor_pos-2]) &&
366                  !(iswpunct (ustr[cursor_pos-3]) || check_space_symbol (ustr[cursor_pos-3])) &&
367                  iswprint(ustr[cursor_pos-3])) {
368             del_chars = 2;
369         }
370
371         if (del_chars > 0) {
372             ev.ctx = ctx;
373             ev.n_chars = del_chars;
374             ev.offset = del_chars * -1;
375
376             ecore_imf_context_delete_surrounding_event_add (ctx, ev.offset, ev.n_chars);
377             ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
378
379             if (input_lang == INPUT_LANG_OTHER) {
380                 fullstop_mark = strdup (".");
381             }
382             else {
383                 Eina_Unicode wbuf[2] = {0};
384                 wbuf[0] = __language_infos[input_lang].punc_code;
385
386                 fullstop_mark = eina_unicode_unicode_to_utf8 (wbuf, NULL);
387             }
388
389             ecore_imf_context_commit_event_add (ctx, fullstop_mark);
390             ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)fullstop_mark);
391
392             if (fullstop_mark) {
393                 free (fullstop_mark);
394                 fullstop_mark = NULL;
395             }
396         }
397     }
398
399 done:
400     if (plain_str) free (plain_str);
401     if (ustr) free (ustr);
402     space_key_time = ecore_time_get ();
403 }
404
405 static Eina_Bool
406 check_except_autocapital (Eina_Unicode *ustr, int cursor_pos)
407 {
408     const char *except_str[] = {"e.g.", "E.g."};
409     unsigned int i = 0, j = 0, len = 0;
410     for (i = 0; i < (sizeof (except_str) / sizeof (except_str[0])); i++) {
411         len = strlen (except_str[i]);
412         if (cursor_pos < (int)len)
413             continue;
414
415         for (j = len; j > 0; j--) {
416             if (ustr[cursor_pos-j] != except_str[i][len-j])
417                 break;
418         }
419
420         if (j == 0) return EINA_TRUE;
421     }
422
423     return EINA_FALSE;
424 }
425
426 static Eina_Bool
427 analyze_surrounding_text (Ecore_IMF_Context *ctx)
428 {
429     char *plain_str = NULL;
430     Eina_Unicode puncs[] = {'\n','.', '!', '?', 0x00BF /* ¿ */, 0x00A1 /* ¡ */,
431                             0x3002 /* 。 */, 0x06D4 /* Urdu */, 0x0964 /* Hindi */,
432                             0x0589 /* Armenian */, 0x17D4 /* Khmer */, 0x104A /* Myanmar */};
433     Eina_Unicode *ustr = NULL;
434     Eina_Bool ret = EINA_FALSE;
435     Eina_Bool detect_space = EINA_FALSE;
436     int cursor_pos = 0;
437     int i = 0;
438     const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
439     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
440     if (!imcontext) return EINA_FALSE;
441
442     switch (ecore_imf_context_autocapital_type_get (ctx)) {
443         case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
444             return EINA_FALSE;
445         case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
446             return EINA_TRUE;
447         default:
448             break;
449     }
450
451     if (imcontext->preedit_text && strcmp (imcontext->preedit_text, "") != 0)
452         return EINA_FALSE;
453
454     if (imcontext->cursor_position == 0)
455         return EINA_TRUE;
456
457     ecore_imf_context_surrounding_get (ctx, &plain_str, &cursor_pos);
458
459     if (!plain_str) goto done;
460
461     if (cursor_pos == 0) {
462         ret = EINA_TRUE;
463         goto done;
464     }
465
466     // Convert string from UTF-8 to unicode
467     ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
468     if (!ustr) goto done;
469
470     if (eina_unicode_strlen (ustr) < (size_t)cursor_pos) goto done;
471
472     if (cursor_pos >= 1) {
473         if (ecore_imf_context_autocapital_type_get (ctx) == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
474             // Check space or no-break space
475             if (check_space_symbol (ustr[cursor_pos-1])) {
476                 ret = EINA_TRUE;
477                 goto done;
478             }
479         }
480
481         // Check paragraph separator <PS> or carriage return  <br>
482         if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
483             ret = EINA_TRUE;
484             goto done;
485         }
486
487         for (i = cursor_pos; i > 0; i--) {
488             // Check space or no-break space
489             if (check_space_symbol (ustr[i-1])) {
490                 detect_space = EINA_TRUE;
491                 continue;
492             }
493
494             // Check punctuation and following the continuous space(s)
495             if (detect_space && check_symbol (ustr[i-1], puncs, punc_num)) {
496                 if (check_except_autocapital (ustr, i))
497                     ret = EINA_FALSE;
498                 else
499                     ret = EINA_TRUE;
500
501                 goto done;
502             } else {
503                 ret = EINA_FALSE;
504                 goto done;
505             }
506         }
507
508         if ((i == 0) && (detect_space == EINA_TRUE)) {
509             // continuous space(s) without any character
510             ret = EINA_TRUE;
511             goto done;
512         }
513     }
514
515 done:
516     if (ustr) free (ustr);
517     if (plain_str) free (plain_str);
518
519     return ret;
520 }
521
522 static void
523 set_autocapital (Ecore_IMF_Context *ctx)
524 {
525     Eina_Bool uppercase = EINA_FALSE;
526
527     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
528     if (!imcontext || !imcontext->text_input || !imcontext->input) return;
529
530     if (hw_keyboard_mode) return;
531
532     if (input_lang != INPUT_LANG_OTHER && (!__language_infos[input_lang].auto_capital_valid))
533         return;
534
535     if (ecore_imf_context_input_panel_layout_get (ctx) != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
536         return;
537
538     // Check autocapital type
539     if (ecore_imf_context_input_panel_caps_lock_mode_get (ctx)) {
540         uppercase = EINA_TRUE;
541     } else {
542         if (autocap_allow == EINA_FALSE)
543             return;
544
545         uppercase = analyze_surrounding_text (ctx);
546     }
547
548     SECURE_LOGD ("ctx : %p, auto capital : %d\n", ctx, uppercase);
549     wl_text_input_set_capital_mode (imcontext->text_input, uppercase);
550 }
551
552 static Ecore_IMF_Context *
553 get_using_ctx ()
554 {
555     return (_show_req_ctx ? _show_req_ctx : _focused_ctx);
556 }
557
558 static Eina_Bool
559 check_hide_key(const char *keyname)
560 {
561     if (!keyname) return EINA_FALSE;
562
563     if (strcmp(keyname, "Escape") == 0 ||
564         strcmp(keyname, BACK_KEY) == 0 ||
565         strcmp(keyname, OLD_BACK_KEY) == 0)
566         return EINA_TRUE;
567     else
568         return EINA_FALSE;
569 }
570
571 #ifndef ENABLE_HIDE_PANEL_KEY
572 static unsigned int
573 _ecore_key_modifiers_to_ecore_imf_locks(unsigned int modifiers)
574 {
575     unsigned int locks = 0;
576
577     if (modifiers & ECORE_EVENT_LOCK_SCROLL)
578         locks |= ECORE_IMF_KEYBOARD_LOCK_SCROLL;
579
580     if (modifiers & ECORE_EVENT_LOCK_CAPS)
581         locks |= ECORE_IMF_KEYBOARD_LOCK_CAPS;
582
583     if (modifiers & ECORE_EVENT_LOCK_NUM)
584         locks |= ECORE_IMF_KEYBOARD_LOCK_NUM;
585
586     return locks;
587 }
588
589 static unsigned int
590 _ecore_key_modifiers_to_ecore_imf_modifiers(unsigned int modifiers)
591 {
592    unsigned int mask = 0;
593
594     /**< "Control" is pressed */
595     if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
596         mask |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
597
598     /**< "Alt" is pressed */
599     if (modifiers & ECORE_EVENT_MODIFIER_ALT)
600         mask |=  ECORE_IMF_KEYBOARD_MODIFIER_ALT;
601
602     /**< "Shift" is pressed */
603     if (modifiers & ECORE_EVENT_MODIFIER_SHIFT)
604         mask |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT;
605
606     /**< "Win" (between "Ctrl" and "Alt") is pressed */
607     if (modifiers & ECORE_EVENT_MODIFIER_WIN)
608         mask |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
609
610     /**< "AltGr" is pressed */
611     if (modifiers & ECORE_EVENT_MODIFIER_ALTGR)
612         mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
613
614     return mask;
615 }
616
617 static void
618 _ecore_event_to_ecore_imf_key_down_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Down *imf_event)
619 {
620     if (!ecore_event || !imf_event)
621         return;
622
623     imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
624     imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
625     imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
626     imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
627     imf_event->timestamp = ecore_event->timestamp;
628
629     if (ecore_event->dev) {
630         imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
631         imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
632         imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
633     }
634     else {
635         imf_event->dev_name = _ecore_imf_event_empty;
636         imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
637         imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
638     }
639
640     imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
641     imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
642 }
643
644 static void
645 _ecore_event_to_ecore_imf_key_up_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Up *imf_event)
646 {
647     if (!ecore_event || !imf_event)
648         return;
649
650     imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
651     imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
652     imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
653     imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
654     imf_event->timestamp = ecore_event->timestamp;
655
656     if (ecore_event->dev) {
657         imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
658         imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
659         imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
660     }
661     else {
662         imf_event->dev_name = _ecore_imf_event_empty;
663         imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
664         imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
665     }
666
667     imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
668     imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
669 }
670 #endif
671
672 static Eina_Bool
673 key_down_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
674 {
675     Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
676     if (!ev || !ev->keyname) return EINA_TRUE; /* the event is kept */
677
678     Ecore_IMF_Context *active_ctx = get_using_ctx ();
679
680     if (!active_ctx) return EINA_TRUE; /* the event is kept */
681
682     if ((_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW ||
683         _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW) &&
684         check_hide_key(ev->keyname)) {
685
686         LOGD ("%s key is pressed.\n", ev->keyname);
687
688 #ifdef ENABLE_HIDE_PANEL_KEY
689         return EINA_FALSE; /* the event is removed from the queue */
690 #else
691         Ecore_IMF_Event_Key_Down imf_event;
692         Eina_Bool filter_ret = EINA_FALSE;
693
694         _ecore_event_to_ecore_imf_key_down_event(ev, &imf_event);
695
696         if (_focused_ctx)
697             filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_DOWN, (Ecore_IMF_Event *)&imf_event);
698         else
699             LOGD("no focus\n");
700
701         LOGD ("%s key is pressed. ret : %d\n", ev->keyname, filter_ret);
702         if (filter_ret) {
703             return EINA_FALSE; /* the event is removed from the queue */
704         }
705
706 #ifdef _TV
707         return EINA_TRUE; /* the event is kept */
708 #else
709         return EINA_FALSE; /* the event is removed from the queue */
710 #endif /* _TV */
711 #endif /* ENABLE_HIDE_PANEL_KEY */
712     }
713     return EINA_TRUE; /* the event is kept */
714 }
715
716 static Eina_Bool
717 key_up_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
718 {
719     Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
720     if (!ev || !ev->keyname) return EINA_TRUE; /* the event is kept */
721
722     Ecore_IMF_Context *active_ctx = get_using_ctx ();
723
724     if (!active_ctx) return EINA_TRUE; /* the event is kept */
725
726     if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE ||
727         !check_hide_key(ev->keyname))
728         return EINA_TRUE; /* the event is kept */
729
730     LOGD ("%s key is released.\n", ev->keyname);
731
732 #ifdef ENABLE_HIDE_PANEL_KEY
733     ecore_imf_context_reset(active_ctx);
734     _input_panel_hide(active_ctx, EINA_TRUE);
735
736     return EINA_FALSE; /* the event is removed from the queue */
737 #else
738     Ecore_IMF_Event_Key_Up imf_event;
739     Eina_Bool filter_ret = EINA_FALSE;
740
741     _ecore_event_to_ecore_imf_key_up_event(ev, &imf_event);
742
743     if (_focused_ctx)
744         filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_UP, (Ecore_IMF_Event *)&imf_event);
745     else
746         LOGD("no focus\n");
747
748     LOGD ("%s key is released. ret : %d\n", ev->keyname, filter_ret);
749     if (filter_ret) {
750         return EINA_FALSE; /* the event is removed from the queue */
751     }
752     else {
753         ecore_imf_context_reset(active_ctx);
754
755 #ifdef _TV
756         return EINA_TRUE; /* the event is kept */
757 #else
758         _input_panel_hide(active_ctx, EINA_TRUE);
759
760         return EINA_FALSE; /* the event is removed from the queue */
761 #endif /* _TV */
762     }
763 #endif /* ENABLE_HIDE_PANEL_KEY */
764 }
765
766 #ifdef _WEARABLE
767 static Eina_Bool
768 rotary_event_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
769 {
770     Ecore_Event_Detent_Rotate *ev = event;
771     if (!ev) return EINA_TRUE;
772
773     Ecore_IMF_Context *active_ctx = NULL;
774     if (_show_req_ctx)
775         active_ctx = _show_req_ctx;
776     else if (_focused_ctx)
777         active_ctx = _focused_ctx;
778
779     if (!active_ctx) return EINA_TRUE;
780
781     if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
782         return EINA_TRUE;
783
784     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(active_ctx);
785     if (imcontext && imcontext->input && imcontext->text_input) {
786         wl_text_input_process_input_device_event(imcontext->text_input,
787             (unsigned int)ECORE_EVENT_DETENT_ROTATE, (char*)event, sizeof(Ecore_Event_Detent_Rotate));
788     }
789
790     return EINA_FALSE;
791 }
792 #endif
793
794 static Eina_Bool
795 _ecore_event_filter_cb(void *data, void *loop_data EINA_UNUSED, int type, void *event)
796 {
797     if (type == ECORE_EVENT_KEY_DOWN) {
798         return key_down_filter_cb(data, type, event);
799     }
800     else if (type == ECORE_EVENT_KEY_UP) {
801         return key_up_filter_cb(data, type, event);
802     }
803 #ifdef _WEARABLE
804     /* The IME needs to process Rotary event prior to client application */
805     else if (type == ECORE_EVENT_DETENT_ROTATE) {
806         return rotary_event_cb(data, type, event);
807     }
808 #endif
809
810     return EINA_TRUE;
811 }
812
813 static void
814 register_key_handler()
815 {
816     if (!_ecore_event_filter_handler)
817         _ecore_event_filter_handler = ecore_event_filter_add(NULL, _ecore_event_filter_cb, NULL, NULL);
818 }
819
820 static void
821 unregister_key_handler()
822 {
823     if (_ecore_event_filter_handler) {
824         ecore_event_filter_del(_ecore_event_filter_handler);
825         _ecore_event_filter_handler = NULL;
826     }
827
828     _clear_hide_timer();
829 }
830 //
831
832 static Eina_Bool
833 _clear_hide_timer()
834 {
835     if (_hide_timer) {
836         ecore_timer_del(_hide_timer);
837         _hide_timer = NULL;
838         return EINA_TRUE;
839     }
840
841     return EINA_FALSE;
842 }
843
844 static void _win_focus_out_handler_del ()
845 {
846     if (_win_focus_out_handler) {
847         ecore_event_handler_del (_win_focus_out_handler);
848         _win_focus_out_handler = NULL;
849     }
850 }
851
852 static void _conformant_change_handler_del()
853 {
854     if (_conformant_change_handler) {
855         ecore_event_handler_del(_conformant_change_handler);
856         _conformant_change_handler = NULL;
857     }
858 }
859
860 static void
861 _send_input_panel_hide_request(Ecore_IMF_Context *ctx)
862 {
863     LOGD ("");
864     if (!ctx) return;
865
866     // TIZEN_ONLY(20150708): Support back key
867     _hide_req_ctx = NULL;
868     //
869
870     _win_focus_out_handler_del ();
871
872     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
873     if (imcontext && imcontext->text_input) {
874         wl_text_input_hide_input_panel(imcontext->text_input);
875     } else {
876         LOGD("creating temporary context for sending hide request\n");
877         const char *ctx_id = ecore_imf_context_default_id_get();
878         Ecore_IMF_Context *temp_context = ecore_imf_context_add(ctx_id);
879         if (temp_context) {
880             imcontext = (WaylandIMContext *)ecore_imf_context_data_get(temp_context);
881             if (imcontext && imcontext->text_input)
882                 wl_text_input_hide_input_panel(imcontext->text_input);
883
884             ecore_imf_context_del(temp_context);
885         }
886     }
887 }
888
889 static void _conformant_area_free (void *data EINA_UNUSED, void *ev)
890 {
891     Ecore_Wl_Event_Conformant_Change *e = ev;
892     free(e);
893     e = NULL;
894 }
895
896 static void add_conformant_change_event(Ecore_Wl_Window *window)
897 {
898     Ecore_Wl_Event_Conformant_Change *ev;
899     ev = calloc(1, sizeof(Ecore_Wl_Event_Conformant_Change));
900     if (ev) {
901         ev->win = ecore_wl_window_id_get(window);
902         ev->part_type = 1;
903         ev->state = 0;
904         ecore_event_add(ECORE_WL_EVENT_CONFORMANT_CHANGE, ev, _conformant_area_free, NULL);
905     }
906 }
907
908 static Eina_Rectangle _conformant_area_backup = { 0, 0, 0, 0 };
909 static Eina_Bool reset_conformant_area(Ecore_IMF_Context *ctx)
910 {
911     Eina_Bool reset = EINA_FALSE;
912     Eina_Bool has_conformant = EINA_FALSE;
913     Ecore_Wl_Window *window = NULL;
914
915     if (!ctx) return EINA_FALSE;
916
917     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
918     if (imcontext) {
919         window = imcontext->window;
920         has_conformant = imcontext->has_conformant;
921     }
922
923     if (window) {
924         int x = 0, y = 0, w = 0, h = 0;
925         Eina_Bool result = ecore_wl_window_keyboard_geometry_get(window, &x, &y, &w, &h);
926
927         if (result) {
928             if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w != 0 || h != 0)) {
929                 reset = EINA_TRUE;
930                 _conformant_area_backup.x = x;
931                 _conformant_area_backup.y = y;
932                 _conformant_area_backup.w = w;
933                 _conformant_area_backup.h = h;
934             }
935         }
936     }
937     LOGD("reset %d", reset);
938     if (reset) {
939         ecore_wl_window_keyboard_geometry_set(window, 0, 0, 0, 0);
940
941         add_conformant_change_event(window);
942
943         _conformant_reset_started = EINA_TRUE;
944     }
945
946     return reset;
947 }
948
949 static void restore_conformant_area(Ecore_IMF_Context *ctx)
950 {
951     Eina_Bool restore = EINA_FALSE;
952     Eina_Bool has_conformant = EINA_FALSE;
953     Ecore_Wl_Window *window = NULL;
954
955     if (!ctx) return;
956
957     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
958     if (imcontext) {
959         window = imcontext->window;
960         has_conformant = imcontext->has_conformant;
961     }
962
963     if (window) {
964         int x = 0, y = 0, w = 0, h = 0;
965         Eina_Bool result = ecore_wl_window_keyboard_geometry_get(window, &x, &y, &w, &h);
966
967         if (result) {
968             if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w == 0 || h == 0)) {
969                 restore = EINA_TRUE;
970             }
971         }
972     }
973     LOGD("restore %d", restore);
974     if (restore) {
975         ecore_wl_window_keyboard_geometry_set(window,
976             _conformant_area_backup.x, _conformant_area_backup.y,
977             _conformant_area_backup.w, _conformant_area_backup.h);
978
979         add_conformant_change_event(window);
980
981        _conformant_reset_started = EINA_FALSE;
982     }
983 }
984
985 static void
986 _send_will_hide_ack(WaylandIMContext *imcontext)
987 {
988     if (!imcontext) return;
989     if (!(imcontext->text_input)) return;
990
991     LOGD("");
992     const char *szWillHideAck = "WILL_HIDE_ACK";
993     wl_text_input_set_input_panel_data(imcontext->text_input, szWillHideAck, strlen(szWillHideAck));
994     _received_will_hide_event = EINA_FALSE;
995 }
996
997 static Eina_Bool
998 _hide_timer_handler(void *data)
999 {
1000     Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1001     _send_input_panel_hide_request(ctx);
1002
1003     if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1004         LOGD("No need to reset conformant, sending ACK right away");
1005         _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1006     }
1007
1008     _hide_timer = NULL;
1009     return ECORE_CALLBACK_CANCEL;
1010 }
1011
1012 static void
1013 _input_panel_hide_timer_start(void *data)
1014 {
1015     if (!_hide_timer)
1016         _hide_timer = ecore_timer_add(HIDE_TIMER_INTERVAL, _hide_timer_handler, data);
1017 }
1018
1019 static void
1020 _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant)
1021 {
1022     LOGD ("ctx : %p", ctx);
1023
1024     if (!ctx) return;
1025
1026     will_hide = EINA_TRUE;
1027     _conformant_reset_started = EINA_FALSE;
1028
1029     if (instant || (_hide_timer && ecore_timer_pending_get(_hide_timer) <= 0.0)) {
1030         _clear_hide_timer();
1031         _send_input_panel_hide_request(ctx);
1032
1033         if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1034             LOGD("No need to reset conformant, sending ACK right away");
1035             _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1036         }
1037     } else {
1038         _input_panel_hide_timer_start(ctx);
1039         // TIZEN_ONLY(20150708): Support back key
1040         _hide_req_ctx = ctx;
1041         //
1042     }
1043 }
1044
1045 static unsigned int
1046 utf8_offset_to_characters(const char *str, int offset)
1047 {
1048     int index = 0;
1049     unsigned int i = 0;
1050
1051     for (; index < offset; i++) {
1052         if (eina_unicode_utf8_next_get(str, &index) == 0)
1053             break;
1054     }
1055
1056     return i;
1057 }
1058
1059 static void
1060 send_cursor_location(WaylandIMContext *imcontext)
1061 {
1062     Ecore_Evas *ee = NULL;
1063     int canvas_x = 0, canvas_y = 0;
1064
1065     if (imcontext->canvas) {
1066         ee = ecore_evas_ecore_evas_get(imcontext->canvas);
1067         if (ee)
1068             ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
1069     }
1070
1071     if (imcontext->input && imcontext->text_input) {
1072         wl_text_input_set_cursor_rectangle(imcontext->text_input,
1073                 imcontext->cursor_location.x + canvas_x,
1074                 imcontext->cursor_location.y + canvas_y,
1075                 imcontext->cursor_location.width,
1076                 imcontext->cursor_location.height);
1077     }
1078 }
1079
1080 static void
1081 update_state(WaylandIMContext *imcontext)
1082 {
1083     if (!imcontext->ctx)
1084         return;
1085
1086     send_cursor_location (imcontext);
1087
1088     if (imcontext->input && imcontext->text_input) {
1089         wl_text_input_commit_state(imcontext->text_input, ++imcontext->serial);
1090     }
1091 }
1092
1093 static Eina_Bool
1094 check_serial(WaylandIMContext *imcontext, uint32_t serial)
1095 {
1096 #ifdef _TV
1097     return EINA_TRUE;
1098 #endif
1099     Ecore_IMF_Preedit_Attr *attr;
1100
1101     if ((imcontext->serial - serial) >
1102         (imcontext->serial - imcontext->reset_serial)) {
1103         LOGD("outdated serial: %u, current: %u, reset: %u",
1104                 serial, imcontext->serial, imcontext->reset_serial);
1105
1106         imcontext->pending_preedit.cursor = 0;
1107
1108         if (imcontext->pending_preedit.attrs) {
1109             EINA_LIST_FREE(imcontext->pending_preedit.attrs, attr) free(attr);
1110             imcontext->pending_preedit.attrs = NULL;
1111         }
1112
1113         return EINA_FALSE;
1114     }
1115
1116     return EINA_TRUE;
1117 }
1118
1119 static void
1120 clear_preedit_text(WaylandIMContext *imcontext)
1121 {
1122     Ecore_IMF_Preedit_Attr *attr = NULL;
1123
1124     imcontext->preedit_cursor = 0;
1125
1126     if (imcontext->preedit_text) {
1127         free(imcontext->preedit_text);
1128         imcontext->preedit_text = NULL;
1129     }
1130
1131     if (imcontext->preedit_attrs) {
1132         EINA_LIST_FREE(imcontext->preedit_attrs, attr)
1133             free(attr);
1134     }
1135
1136     imcontext->preedit_attrs = NULL;
1137 }
1138
1139 static void
1140 clear_preedit(WaylandIMContext *imcontext)
1141 {
1142     clear_preedit_text(imcontext);
1143
1144     if (imcontext->preedit_commit) {
1145         free(imcontext->preedit_commit);
1146         imcontext->preedit_commit = NULL;
1147     }
1148 }
1149
1150 static Eina_Bool
1151 check_preedit_empty(WaylandIMContext *imcontext)
1152 {
1153     if (!imcontext) return EINA_TRUE;
1154
1155     if (imcontext->preedit_text) return EINA_FALSE;
1156     if (imcontext->preedit_attrs) return EINA_FALSE;
1157     if (imcontext->preedit_cursor != 0) return EINA_FALSE;
1158     if (imcontext->preedit_commit) return EINA_FALSE;
1159
1160     return EINA_TRUE;
1161 }
1162
1163 static void
1164 text_input_commit_string(void                 *data,
1165                          struct wl_text_input *text_input EINA_UNUSED,
1166                          uint32_t              serial,
1167                          const char           *text)
1168 {
1169     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1170     Eina_Bool old_preedit = EINA_FALSE;
1171
1172     SECURE_LOGD("ctx : %p, commit event (text: '%s', current pre-edit: '%s')",
1173                 imcontext->ctx,
1174                 text,
1175                 imcontext->preedit_text ? imcontext->preedit_text : "");
1176
1177     if (!imcontext->ctx)
1178         return;
1179
1180     old_preedit =
1181         imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1182
1183     if (!check_serial(imcontext, serial))
1184         return;
1185
1186     if (old_preedit) {
1187         ecore_imf_context_preedit_end_event_add(imcontext->ctx);
1188         ecore_imf_context_event_callback_call(imcontext->ctx,
1189                 ECORE_IMF_CALLBACK_PREEDIT_END,
1190                 NULL);
1191     }
1192
1193     clear_preedit(imcontext);
1194
1195     if (!text)
1196         return;
1197
1198     Eina_Unicode *ustr = eina_unicode_utf8_to_unicode (text, NULL);
1199
1200     if (ustr) {
1201         if (eina_unicode_strcmp (ustr, L" ") == 0 ||
1202             eina_unicode_strcmp (ustr, L" ") == 0)
1203             autoperiod_insert (imcontext->ctx);
1204
1205         free(ustr);
1206     }
1207
1208     ecore_imf_context_commit_event_add(imcontext->ctx, text);
1209     ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)text);
1210 }
1211
1212 static void
1213 commit_preedit(WaylandIMContext *imcontext)
1214 {
1215     LOGD("");
1216     if (!imcontext->preedit_commit)
1217         return;
1218
1219     if (!imcontext->ctx)
1220         return;
1221
1222     clear_preedit_text(imcontext);
1223
1224     size_t commit_len = strlen(imcontext->preedit_commit);
1225
1226     if (commit_len == 0) {
1227         ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
1228         ecore_imf_context_event_callback_call(imcontext->ctx,
1229                 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1230                 NULL);
1231     }
1232
1233     ecore_imf_context_preedit_end_event_add(imcontext->ctx);
1234     ecore_imf_context_event_callback_call(imcontext->ctx,
1235             ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
1236
1237     if (commit_len > 0) {
1238         ecore_imf_context_commit_event_add(imcontext->ctx,
1239                 imcontext->preedit_commit);
1240         ecore_imf_context_event_callback_call(imcontext->ctx,
1241                 ECORE_IMF_CALLBACK_COMMIT,
1242                 (void *)imcontext->preedit_commit);
1243     }
1244 }
1245
1246 static Eina_Bool
1247 set_focus(Ecore_IMF_Context *ctx)
1248 {
1249     LOGD("ctx : %p", ctx);
1250     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1251     if (!imcontext) return EINA_FALSE;
1252
1253     if (!imcontext->window) {
1254         LOGW("window is not given\n");
1255         return EINA_FALSE;
1256     }
1257
1258     Ecore_Wl_Input *input = ecore_wl_window_keyboard_get(imcontext->window);
1259     if (!input) {
1260         LOGW("ctx : %p, Can't get Wl_Input\n", ctx);
1261         return EINA_FALSE;
1262     }
1263
1264     struct wl_seat *seat = ecore_wl_input_seat_get(input);
1265     if (!seat) {
1266         LOGW("ctx : %p, Can't get Wl_seat\n", ctx);
1267         return EINA_FALSE;
1268     }
1269
1270     imcontext->input = input;
1271     _focused_ctx = ctx;
1272
1273     wl_text_input_activate(imcontext->text_input, seat,
1274             ecore_wl_window_surface_get(imcontext->window));
1275
1276     return EINA_TRUE;
1277 }
1278
1279 static void
1280 set_focus_out(Ecore_IMF_Context *ctx)
1281 {
1282     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1283     if (!imcontext || !imcontext->input) return;
1284
1285     // deactivate
1286     if (imcontext->text_input)
1287         wl_text_input_deactivate(imcontext->text_input,
1288                                  ecore_wl_input_seat_get(imcontext->input));
1289
1290     if (ctx == _focused_ctx)
1291         _focused_ctx = NULL;
1292
1293     imcontext->input = NULL;
1294 }
1295
1296 // TIZEN_ONLY(20160217): ignore the duplicate show request
1297 static Eina_Bool _compare_context(Ecore_IMF_Context *ctx1, Ecore_IMF_Context *ctx2)
1298 {
1299     if (!ctx1 || !ctx2) return EINA_FALSE;
1300
1301     if ((ecore_imf_context_autocapital_type_get(ctx1) == ecore_imf_context_autocapital_type_get(ctx2)) &&
1302         (ecore_imf_context_input_panel_layout_get(ctx1) == ecore_imf_context_input_panel_layout_get(ctx2)) &&
1303         (ecore_imf_context_input_panel_layout_variation_get(ctx1) == ecore_imf_context_input_panel_layout_variation_get(ctx2)) &&
1304         (ecore_imf_context_input_panel_language_get(ctx1) == ecore_imf_context_input_panel_language_get(ctx2)) &&
1305         (ecore_imf_context_input_panel_return_key_type_get(ctx1) == ecore_imf_context_input_panel_return_key_type_get(ctx2)) &&
1306         (ecore_imf_context_input_panel_return_key_disabled_get(ctx1) == ecore_imf_context_input_panel_return_key_disabled_get(ctx2)) &&
1307         (ecore_imf_context_input_panel_caps_lock_mode_get(ctx1) == ecore_imf_context_input_panel_caps_lock_mode_get(ctx2)))
1308         return EINA_TRUE;
1309
1310     return EINA_FALSE;
1311 }
1312 //
1313
1314 static void send_get_hide_permission(WaylandIMContext *imcontext)
1315 {
1316     if (imcontext->text_input) {
1317         ignore_hide = EINA_FALSE;
1318         wl_text_input_get_hide_permission(imcontext->text_input);
1319     }
1320 }
1321
1322 static Eina_Bool _client_window_focus_out_cb(void *data, int ev_type, void *ev)
1323 {
1324     Ecore_Wl_Event_Focus_Out *e = (Ecore_Wl_Event_Focus_Out *)ev;
1325     Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1326     if (!ctx || !e) return ECORE_CALLBACK_PASS_ON;
1327
1328     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
1329     if (!imcontext || !imcontext->window) return ECORE_CALLBACK_PASS_ON;
1330
1331     unsigned int client_win_id = ecore_wl_window_id_get (imcontext->window);
1332
1333     LOGD ("ctx : %p, client_window id : %#x, focus-out win : %#x\n", ctx, client_win_id, e->win);
1334
1335     if (client_win_id > 0) {
1336         if (e->win == client_win_id) {
1337             LOGD ("window focus out\n");
1338
1339             if (_focused_ctx == ctx) {
1340                 wayland_im_context_focus_out (ctx);
1341             }
1342
1343             if (_show_req_ctx == ctx) {
1344                 send_get_hide_permission(imcontext);
1345             }
1346         }
1347     }
1348     else {
1349         send_get_hide_permission(imcontext);
1350     }
1351
1352     return ECORE_CALLBACK_PASS_ON;
1353 }
1354
1355 static void send_will_hide_ack(Ecore_IMF_Context *ctx)
1356 {
1357     Eina_Bool need_temporary_context = EINA_FALSE;
1358     Eina_Bool has_conformant = EINA_FALSE;
1359     WaylandIMContext *imcontext = NULL;
1360
1361     if (!ctx) {
1362         LOGD("ctx is NULL\n");
1363         need_temporary_context = EINA_TRUE;
1364     } else {
1365         imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1366         if (!imcontext) {
1367             LOGD("imcontext is NULL :%p\n", ctx);
1368             need_temporary_context = EINA_TRUE;
1369         } else {
1370             has_conformant = imcontext->has_conformant;
1371         }
1372     }
1373
1374     /* When the RENDER_POST event is emitted, it is possible that our IMF_Context is already deleted,
1375        meaning that there is no connection available for communicating with the window manager.
1376        So we are creating a temporary context for sending WILL_HIDE_ACK message */
1377     if (need_temporary_context) {
1378         LOGD("creating temporary context for sending WILL_HIDE_ACK\n");
1379         const char *ctx_id = ecore_imf_context_default_id_get();
1380         ctx = ecore_imf_context_add(ctx_id);
1381         if (ctx) {
1382             imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1383         }
1384     }
1385
1386     if (ctx && imcontext) {
1387         if (ecore_imf_context_client_canvas_get(ctx) && has_conformant) {
1388             if (_conformant_reset_done && _received_will_hide_event) {
1389                 LOGD("Send will hide ack, _conformant_reset_done = 1, received_will_hide_event = 1\n");
1390                 _send_will_hide_ack(imcontext);
1391                 _conformant_reset_done = EINA_FALSE;
1392                 _received_will_hide_event = EINA_FALSE;
1393             } else {
1394                 LOGD ("_conformant_reset_done=%d, received_will_hide_event=%d\n",
1395                     _conformant_reset_done, _received_will_hide_event);
1396             }
1397         } else {
1398             LOGD("Send will hide ack right away, since there is no conformant available : %p %d\n",
1399                 ecore_imf_context_client_canvas_get(ctx), has_conformant);
1400             _send_will_hide_ack (imcontext);
1401         }
1402     }
1403
1404     if (need_temporary_context) {
1405         if (ctx) {
1406             ecore_imf_context_del(ctx);
1407         }
1408     }
1409 }
1410
1411 static void _render_post_cb(void *data, Evas *e, void *event_info)
1412 {
1413     void *callback = evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1414     _conformant_reset_done = EINA_TRUE;
1415     _conformant_reset_started = EINA_FALSE;
1416     LOGD("[_render_post_cb], _conformant_reset_done = 1 , %p\n", callback);
1417     send_will_hide_ack(NULL);
1418 }
1419
1420 static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
1421 {
1422     Ecore_Wl_Event_Conformant_Change *e = (Ecore_Wl_Event_Conformant_Change *)ev;
1423     Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1424     if (!e || !ctx) return ECORE_CALLBACK_PASS_ON;
1425
1426     LOGD ("CONFORMANT changed!! part type : %d, state : %d, win : %d", e->part_type, e->state, e->win);
1427
1428     if (_active_context_window_id != e->win)
1429         return ECORE_CALLBACK_PASS_ON;
1430
1431     Ecore_Wl_Window *window = ecore_wl_window_find(e->win);
1432     if (!window) return ECORE_CALLBACK_PASS_ON;
1433
1434     if (!(e->state)) {
1435         LOGD("_conformant_reset_done = 0, registering _render_post_cb : %p %p\n", _active_context_canvas, window);
1436         _conformant_reset_done = EINA_FALSE;
1437         if (_active_context_canvas && ecore_wl_window_conformant_get(window) && !_custom_conformant_event) {
1438             evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1439             evas_event_callback_add(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb, ctx);
1440         }
1441     } else {
1442         _conformant_reset_done = EINA_FALSE;
1443         if (_active_context_canvas) {
1444             evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1445         }
1446         /* Since the input_panel_geometry is not delivered right at the moment, we use conformant geometry instead */
1447         int x = 0, y = 0, w = 0, h = 0;
1448         Eina_Bool result = ecore_wl_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1449         if (result) {
1450             Evas_Coord scr_w = 0, scr_h = 0;
1451             ecore_wl_sync();
1452             ecore_wl_screen_size_get(&scr_w, &scr_h);
1453             int rot = ecore_wl_window_rotation_get(window);
1454             /* Assume we are using keyboard that has the same width to the screen width*/
1455             switch (rot) {
1456             case 90:
1457                 _keyboard_geometry.h = w;
1458                 _keyboard_geometry.w = h;
1459                 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1460                 _keyboard_geometry.x = 0;
1461                 break;
1462             case 180:
1463                 _keyboard_geometry.w = w;
1464                 _keyboard_geometry.h = h;
1465                 _keyboard_geometry.x = 0;
1466                 _keyboard_geometry.y = scr_h - _keyboard_geometry.h;
1467                 break;
1468             case 270:
1469                 _keyboard_geometry.h = w;
1470                 _keyboard_geometry.w = h;
1471                 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1472                 _keyboard_geometry.x = 0;
1473                 break;
1474             default:
1475                 _keyboard_geometry.x = x;
1476                 _keyboard_geometry.y = y;
1477                 _keyboard_geometry.w = w;
1478                 _keyboard_geometry.h = h;
1479             }
1480             LOGD("[KEYPAD]: scr %dx%d, rot %d, orig (%d,%d, %dx%d)", scr_w, scr_h, rot, x, y, w, h);
1481             LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d\n", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
1482             ecore_imf_context_input_panel_event_callback_call(ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
1483         }
1484     }
1485
1486     return ECORE_CALLBACK_PASS_ON;
1487 }
1488
1489 static uint32_t
1490 get_purpose(Ecore_IMF_Context *ctx)
1491 {
1492     int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1493     uint32_t new_purpose = 0;
1494
1495     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1496     if (!imcontext)
1497         return new_purpose;
1498
1499     switch (imcontext->content_purpose) {
1500         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
1501             if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED)
1502                 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED;
1503             else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL)
1504                 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL;
1505             else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL)
1506                 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL;
1507             else
1508                 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
1509             break;
1510         case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
1511             if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY)
1512                 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS;
1513             else
1514                 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
1515             break;
1516         case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
1517             if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME)
1518                 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME;
1519             else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME)
1520                 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NAME;
1521             else
1522                 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
1523             break;
1524         default :
1525             new_purpose = imcontext->content_purpose;
1526             break;
1527     }
1528
1529     return new_purpose;
1530 }
1531
1532 static void _canvas_focus_in_cb(void *data, Evas *e, void *event_info)
1533 {
1534     LOGD("ctx : %p", _focus_req_ctx);
1535
1536     if (_focus_req_ctx) {
1537         set_focus(_focus_req_ctx);
1538         show_input_panel(_focus_req_ctx);
1539
1540         WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(_focus_req_ctx);
1541         if (imcontext && imcontext->canvas)
1542             evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1543         _focus_req_ctx = NULL;
1544     }
1545 }
1546
1547 static Eina_Bool
1548 show_input_panel(Ecore_IMF_Context *ctx)
1549 {
1550     LOGD("ctx : %p", ctx);
1551     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1552
1553     char *surrounding = NULL;
1554     int cursor_pos;
1555
1556     if ((!imcontext) || (!imcontext->text_input))
1557         return EINA_FALSE;
1558
1559     if (!imcontext->input) {
1560         set_focus(ctx);
1561         if (!imcontext->input) {
1562             _focus_req_ctx = ctx;
1563             if (imcontext->canvas) {
1564                 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1565                 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
1566             }
1567         }
1568     }
1569
1570     _clear_hide_timer ();
1571
1572     _win_focus_out_handler_del ();
1573
1574     if (!imcontext->input)
1575         return EINA_FALSE;
1576
1577     ignore_hide = EINA_TRUE;
1578
1579     _win_focus_out_handler = ecore_event_handler_add (ECORE_WL_EVENT_FOCUS_OUT, _client_window_focus_out_cb, ctx);
1580     _conformant_change_handler_del ();
1581     _conformant_change_handler = ecore_event_handler_add(ECORE_WL_EVENT_CONFORMANT_CHANGE, _conformant_change_cb, ctx);
1582
1583     // TIZEN_ONLY(20160217): ignore the duplicate show request
1584     if ((_show_req_ctx == ctx) && _compare_context(_show_req_ctx, ctx) && (!will_hide)) {
1585         if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW ||
1586             _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
1587             LOGD("already show. ctx : %p", ctx);
1588
1589             return EINA_FALSE;
1590         }
1591     }
1592
1593     will_hide = EINA_FALSE;
1594     _show_req_ctx = ctx;
1595     _input_panel_ctx = ctx;
1596     _active_context_canvas = ecore_imf_context_client_canvas_get(ctx);
1597
1598     if (imcontext->window) {
1599         _active_context_window_id = ecore_wl_window_id_get(imcontext->window);
1600         imcontext->has_conformant = ecore_wl_window_conformant_get(imcontext->window);
1601     } else {
1602         imcontext->has_conformant = EINA_FALSE;
1603     }
1604     //
1605
1606     // TIZEN_ONLY(20150715): Support input_panel_state_get
1607     _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
1608     int layout = ecore_imf_context_input_panel_layout_get (ctx);
1609     int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1610     //
1611
1612     if (layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
1613         imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
1614
1615     wl_text_input_set_content_type(imcontext->text_input,
1616             imcontext->content_hint,
1617             get_purpose(ctx));
1618
1619     if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos)) {
1620         SECURE_LOGD ("surrounding text : %s\n", surrounding);
1621         if (surrounding)
1622             free (surrounding);
1623
1624         imcontext->cursor_position = cursor_pos;
1625         wl_text_input_set_cursor_position(imcontext->text_input, cursor_pos);
1626     }
1627     // TIZEN_ONLY(20150716): Support return key type
1628     wl_text_input_set_return_key_type(imcontext->text_input,
1629             imcontext->return_key_type);
1630
1631     wl_text_input_set_return_key_disabled(imcontext->text_input,
1632             imcontext->return_key_disabled);
1633
1634     if (imcontext->imdata_size > 0)
1635         wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
1636
1637     set_autocapital (ctx);
1638
1639     SECURE_LOGD ("ctx : %p, layout : %d, layout variation : %d\n", ctx,
1640             layout, layout_variation);
1641     SECURE_LOGD ("language : %d, cursor position : %d\n",
1642             ecore_imf_context_input_panel_language_get (ctx),
1643             cursor_pos);
1644     SECURE_LOGD ("return key type : %d, return key disabled : %d, autocapital type : %d\n",
1645             ecore_imf_context_input_panel_return_key_type_get (ctx),
1646             ecore_imf_context_input_panel_return_key_disabled_get (ctx),
1647             ecore_imf_context_autocapital_type_get (ctx));
1648     SECURE_LOGD ("client_window : %#x, password mode : %d, prediction_allow : %d\n",
1649             ecore_imf_context_client_window_get (ctx),
1650             (imcontext->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) ? 1 : 0,
1651             ecore_imf_context_prediction_allow_get (ctx));
1652     SECURE_LOGD ("input hint : %#x, bidi direction : %d\n", ecore_imf_context_input_hint_get (ctx), imcontext->bidi_direction);
1653
1654     if (_active_context_canvas && !evas_focus_state_get (_active_context_canvas)) {
1655         LOGW ("Canvas does not have focus!\n");
1656     }
1657     //
1658
1659     wl_text_input_show_input_panel(imcontext->text_input);
1660
1661     return EINA_TRUE;
1662 }
1663
1664 static void delete_surrounding_text(WaylandIMContext *imcontext, int index, int length)
1665 {
1666     Ecore_IMF_Event_Delete_Surrounding ev;
1667     LOGD("delete surrounding text (index: %d, length: %u)",
1668             index, length);
1669
1670     ev.offset = index;
1671     ev.n_chars = length;
1672
1673     ecore_imf_context_delete_surrounding_event_add(imcontext->ctx, ev.offset, ev.n_chars);
1674     ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
1675 }
1676
1677 static void
1678 text_input_preedit_string(void                 *data,
1679                           struct wl_text_input *text_input EINA_UNUSED,
1680                           uint32_t              serial,
1681                           const char           *text,
1682                           const char           *commit)
1683 {
1684     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1685     Eina_Bool old_preedit = EINA_FALSE;
1686     Eina_Bool preedit_changed = EINA_FALSE;
1687
1688     SECURE_LOGD("ctx : %p, preedit event (text: '%s', current pre-edit: '%s')",
1689                 imcontext->ctx,
1690                 text,
1691                 imcontext->preedit_text ? imcontext->preedit_text : "");
1692
1693     if (!check_serial(imcontext, serial))
1694         return;
1695
1696     old_preedit =
1697         imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1698
1699     if (imcontext->preedit_text)
1700         preedit_changed = (strcmp(imcontext->preedit_text, text) != 0);
1701     else
1702         preedit_changed = (strlen(text) != 0);
1703
1704     clear_preedit(imcontext);
1705
1706     imcontext->preedit_text = strdup(text);
1707     imcontext->preedit_commit = (strlen(text) > 0 ? strdup(commit) : NULL);
1708     imcontext->preedit_cursor =
1709         utf8_offset_to_characters(text, imcontext->pending_preedit.cursor);
1710     imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
1711
1712     imcontext->pending_preedit.attrs = NULL;
1713
1714     if (preedit_changed) {
1715         if (!old_preedit) {
1716             ecore_imf_context_preedit_start_event_add(imcontext->ctx);
1717             ecore_imf_context_event_callback_call(imcontext->ctx,
1718                     ECORE_IMF_CALLBACK_PREEDIT_START,
1719                     NULL);
1720         }
1721
1722         ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
1723         ecore_imf_context_event_callback_call(imcontext->ctx,
1724                 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1725                 NULL);
1726
1727         if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
1728             ecore_imf_context_preedit_end_event_add(imcontext->ctx);
1729             ecore_imf_context_event_callback_call(imcontext->ctx,
1730                     ECORE_IMF_CALLBACK_PREEDIT_END,
1731                     NULL);
1732         }
1733     }
1734 }
1735
1736 static void
1737 text_input_delete_surrounding_text(void                 *data,
1738                                    struct wl_text_input *text_input EINA_UNUSED,
1739                                    int32_t               index,
1740                                    uint32_t              length)
1741 {
1742     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1743     delete_surrounding_text(imcontext, index, length);
1744 }
1745
1746 static void
1747 text_input_cursor_position(void                 *data EINA_UNUSED,
1748                            struct wl_text_input *text_input EINA_UNUSED,
1749                            int32_t               index,
1750                            int32_t               anchor)
1751 {
1752     LOGD("cursor_position for next commit (index: %d, anchor: %d)",
1753             index, anchor);
1754 }
1755
1756 static void
1757 text_input_preedit_styling(void                 *data,
1758                            struct wl_text_input *text_input EINA_UNUSED,
1759                            uint32_t              index,
1760                            uint32_t              length,
1761                            uint32_t              style)
1762 {
1763     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1764     Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
1765
1766     switch (style)
1767     {
1768         case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
1769             attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1770             break;
1771         case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
1772             attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1773             break;
1774         case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT:
1775             break;
1776         case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
1777             attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
1778             break;
1779         case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE:
1780             break;
1781         case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE:
1782             break;
1783         case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION:
1784             attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1785             break;
1786         default:
1787             attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1788             break;
1789     }
1790
1791     attr->start_index = index;
1792     attr->end_index = index + length;
1793
1794     imcontext->pending_preedit.attrs =
1795         eina_list_append(imcontext->pending_preedit.attrs, attr);
1796 }
1797
1798 static void
1799 text_input_preedit_cursor(void                 *data,
1800                           struct wl_text_input *text_input EINA_UNUSED,
1801                           int32_t               index)
1802 {
1803     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1804
1805     imcontext->pending_preedit.cursor = index;
1806 }
1807
1808 static xkb_mod_index_t
1809 modifiers_get_index(struct wl_array *modifiers_map, const char *name)
1810 {
1811     xkb_mod_index_t index = 0;
1812     char *p = modifiers_map->data;
1813
1814     while ((const char *)p < ((const char *)modifiers_map->data + modifiers_map->size))
1815     {
1816         if (strcmp(p, name) == 0)
1817             return index;
1818
1819         index++;
1820         p += strlen(p) + 1;
1821     }
1822
1823     return XKB_MOD_INVALID;
1824 }
1825
1826 static xkb_mod_mask_t
1827 modifiers_get_mask(struct wl_array *modifiers_map,
1828         const char *name)
1829 {
1830     xkb_mod_index_t index = modifiers_get_index(modifiers_map, name);
1831
1832     if (index == XKB_MOD_INVALID)
1833         return XKB_MOD_INVALID;
1834
1835     return 1 << index;
1836 }
1837
1838 static void
1839 text_input_modifiers_map(void                 *data,
1840                          struct wl_text_input *text_input EINA_UNUSED,
1841                          struct wl_array      *map)
1842 {
1843     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1844     LOGD ("");
1845     imcontext->shift_mask = modifiers_get_mask(map, "Shift");
1846     imcontext->control_mask = modifiers_get_mask(map, "Control");
1847     imcontext->alt_mask = modifiers_get_mask(map, "Mod1");
1848     imcontext->caps_mask = modifiers_get_mask(map, "Lock");
1849     imcontext->num_mask = modifiers_get_mask(map, "Mod2");
1850 }
1851
1852 static void
1853 _ecore_keyevent_free (void *data EINA_UNUSED, void *ev)
1854 {
1855     Ecore_Event_Key *e = ev;
1856     free(e);
1857     e = NULL;
1858 }
1859
1860 static void
1861 text_input_keysym(void                 *data,
1862                   struct wl_text_input *text_input EINA_UNUSED,
1863                   uint32_t              serial EINA_UNUSED,
1864                   uint32_t              time,
1865                   uint32_t              sym,
1866                   uint32_t              state,
1867                   uint32_t              modifiers)
1868 {
1869     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1870     char string[32], key[32], keyname[32];
1871     Ecore_Event_Key *e;
1872
1873     memset(key, 0, sizeof(key));
1874     xkb_keysym_get_name(sym, key, sizeof(key));
1875
1876     memset(keyname, 0, sizeof(keyname));
1877     xkb_keysym_get_name(sym, keyname, sizeof(keyname));
1878     if (keyname[0] == '\0')
1879         snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
1880
1881     memset(string, 0, sizeof(string));
1882     xkb_keysym_to_utf8(sym, string, 32);
1883
1884     SECURE_LOGD("key event (key: %s)", keyname);
1885
1886     e = calloc(1, sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) +
1887             strlen(string) + 3);
1888     if (!e) return;
1889
1890     e->keyname = (char *)(e + 1);
1891     e->key = e->keyname + strlen(keyname) + 1;
1892     e->string = e->key + strlen(key) + 1;
1893     e->compose = e->string;
1894
1895     strncpy((char *)e->keyname, keyname, strlen(keyname));
1896     strncpy((char *)e->key, key, strlen(key));
1897     strncpy((char *)e->string, string, strlen(string));
1898
1899     e->window = (Ecore_Window)ecore_wl_window_id_get(imcontext->window);
1900     e->event_window = (Ecore_Window)ecore_wl_window_id_get(imcontext->window);
1901     e->dev = _ime_device;
1902     e->timestamp = 0; /* For distinguishing S/W keyboard event */
1903
1904     e->modifiers = 0;
1905     if (modifiers & imcontext->shift_mask)
1906         e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
1907
1908     if (modifiers & imcontext->control_mask)
1909         e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
1910
1911     if (modifiers & imcontext->alt_mask)
1912         e->modifiers |= ECORE_EVENT_MODIFIER_ALT;
1913
1914     if (modifiers & MOD_Mod5_MASK)
1915         e->modifiers |= MOD_Mod5_MASK;
1916
1917     if (modifiers & imcontext->caps_mask)
1918         e->modifiers |= ECORE_EVENT_LOCK_CAPS;
1919
1920     if (modifiers & imcontext->num_mask)
1921         e->modifiers |= ECORE_EVENT_LOCK_NUM;
1922
1923     //Save "wl_text_input::keysym" keysym to list if list is not empty,
1924     //if not, send keysym to ecore loop as key event.
1925     //This code let key event which will be filtered by IME one by one.
1926     if (eina_list_count(imcontext->keysym_list)) {
1927         e->data = (void *)(unsigned long int)(state ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP);
1928         imcontext->keysym_list = eina_list_prepend(imcontext->keysym_list, e);
1929     }
1930     else {
1931         if (state)
1932             ecore_event_add(ECORE_EVENT_KEY_DOWN, e, _ecore_keyevent_free, NULL);
1933         else
1934             ecore_event_add(ECORE_EVENT_KEY_UP, e, _ecore_keyevent_free, NULL);
1935     }
1936 }
1937
1938 static void
1939 text_input_enter(void                 *data,
1940                  struct wl_text_input *text_input EINA_UNUSED,
1941                  struct wl_surface    *surface EINA_UNUSED)
1942 {
1943     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1944
1945     update_state(imcontext);
1946
1947     imcontext->reset_serial = imcontext->serial;
1948 }
1949
1950 static void
1951 text_input_leave(void                 *data,
1952                  struct wl_text_input *text_input EINA_UNUSED)
1953 {
1954     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1955
1956     /* clear preedit */
1957     commit_preedit(imcontext);
1958     clear_preedit(imcontext);
1959 }
1960
1961 static void
1962 text_input_input_panel_state(void                 *data EINA_UNUSED,
1963                              struct wl_text_input *text_input EINA_UNUSED,
1964                              uint32_t              state EINA_UNUSED)
1965 {
1966     // TIZEN_ONLY(20150708): Support input panel state callback
1967     WaylandIMContext *imcontext = (WaylandIMContext *)data;
1968     LOGD("input panel state: %d", state);
1969     switch (state) {
1970         case WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE:
1971             _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
1972             if (imcontext->ctx == _show_req_ctx)
1973                 _show_req_ctx = NULL;
1974
1975             will_hide = EINA_FALSE;
1976
1977             _received_will_hide_event = EINA_TRUE;
1978             LOGD("_received_will_hide_event = 1\n");
1979             send_will_hide_ack(imcontext->ctx);
1980             break;
1981         case WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW:
1982             _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
1983             _received_will_hide_event = EINA_FALSE;
1984             if (!_show_req_ctx)
1985                 _show_req_ctx = imcontext->ctx;
1986             LOGD("_received_will_hide_event = 0\n");
1987             break;
1988         default:
1989             _input_panel_state = (Ecore_IMF_Input_Panel_State)state;
1990             break;
1991     }
1992
1993     ecore_imf_context_input_panel_event_callback_call(imcontext->ctx,
1994             ECORE_IMF_INPUT_PANEL_STATE_EVENT,
1995             _input_panel_state);
1996
1997     if (state == WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE) {
1998         static Evas_Coord scr_w = 0, scr_h = 0;
1999         if (scr_w == 0 || scr_h == 0) {
2000             ecore_wl_sync();
2001             ecore_wl_screen_size_get(&scr_w, &scr_h);
2002         }
2003         _keyboard_geometry.x = 0;
2004         _keyboard_geometry.y = scr_h;
2005         _keyboard_geometry.w = 0;
2006         _keyboard_geometry.h = 0;
2007         LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d\n", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2008         ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2009     }
2010     //
2011 }
2012
2013 // TIZEN_ONLY(20151221): Support input panel geometry
2014 static void
2015 text_input_input_panel_geometry(void                 *data EINA_UNUSED,
2016                                 struct wl_text_input *text_input EINA_UNUSED,
2017                                 uint32_t              x,
2018                                 uint32_t              y,
2019                                 uint32_t              w,
2020                                 uint32_t              h)
2021 {
2022     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2023
2024     if (_keyboard_geometry.x != (int)x || _keyboard_geometry.y != (int)y ||
2025         _keyboard_geometry.w != (int)w || _keyboard_geometry.h != (int)h)
2026     {
2027         _keyboard_geometry.x = x;
2028         _keyboard_geometry.y = y;
2029         _keyboard_geometry.w = w;
2030         _keyboard_geometry.h = h;
2031         LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d\n", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2032         ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2033     }
2034 }
2035 //
2036
2037 static void
2038 text_input_language(void                 *data,
2039                     struct wl_text_input *text_input EINA_UNUSED,
2040                     uint32_t              serial EINA_UNUSED,
2041                     const char           *language)
2042 {
2043     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2044     Eina_Bool changed = EINA_FALSE;
2045
2046     if (!imcontext || !language) return;
2047
2048     if (imcontext->language) {
2049         if (strcmp(imcontext->language, language) != 0) {
2050             changed = EINA_TRUE;
2051             free(imcontext->language);
2052         }
2053     }
2054     else {
2055         changed = EINA_TRUE;
2056     }
2057
2058     if (changed) {
2059         imcontext->language = strdup(language);
2060
2061         if (imcontext->ctx)
2062             ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, 0);
2063     }
2064 }
2065
2066 static void
2067 text_input_text_direction(void                 *data EINA_UNUSED,
2068                           struct wl_text_input *text_input EINA_UNUSED,
2069                           uint32_t              serial EINA_UNUSED,
2070                           uint32_t              direction EINA_UNUSED)
2071 {
2072 }
2073
2074 // TIZEN_ONLY(20150918): Support to set the selection region
2075 static void
2076 text_input_selection_region(void                 *data,
2077                             struct wl_text_input *text_input EINA_UNUSED,
2078                             uint32_t              serial EINA_UNUSED,
2079                             int32_t               start,
2080                             int32_t               end)
2081 {
2082     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2083     if (!imcontext || !imcontext->ctx) return;
2084
2085     Ecore_IMF_Event_Selection ev;
2086     ev.ctx = imcontext->ctx;
2087     ev.start = start;
2088     ev.end = end;
2089     ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_SELECTION_SET, &ev);
2090 }
2091
2092 static void
2093 text_input_private_command(void                 *data,
2094                            struct wl_text_input *text_input EINA_UNUSED,
2095                            uint32_t              serial EINA_UNUSED,
2096                            const char           *command)
2097 {
2098     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2099     if (!imcontext || !imcontext->ctx) return;
2100
2101     const char *szConformantReset = "CONFORMANT_RESET";
2102     const char *szConformantRestore = "CONFORMANT_RESTORE";
2103     LOGD("Checking command : %s", command);
2104
2105     if (strncmp(command, szConformantReset, strlen(szConformantReset)) == 0) {
2106         Ecore_Wl_Window *window = imcontext->window;
2107         if (!window) return;
2108
2109         if (!reset_conformant_area(imcontext->ctx) && !_conformant_reset_started) {
2110             LOGD("Could not reset conformant area, send will_hide_ack right away %d", _conformant_reset_started);
2111             _send_will_hide_ack(imcontext);
2112         } else if (_conformant_reset_done) {
2113             LOGD("Conformant reset has been already finished, send will_hide_ack right away");
2114             _send_will_hide_ack(imcontext);
2115         }
2116     } else if (strncmp(command, szConformantRestore, strlen(szConformantRestore)) == 0) {
2117         Ecore_Wl_Window *window = imcontext->window;
2118         if (!window) return;
2119
2120         restore_conformant_area(imcontext->ctx);
2121     } else {
2122         ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)command);
2123     }
2124 }
2125
2126 static void
2127 text_input_input_panel_data(void                 *data,
2128                             struct wl_text_input *text_input EINA_UNUSED,
2129                             uint32_t              serial EINA_UNUSED,
2130                             const char           *input_panel_data,
2131                             uint32_t              length)
2132 {
2133     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2134     if (!imcontext || !imcontext->ctx) return;
2135
2136     if (imcontext->input_panel_data)
2137         free (imcontext->input_panel_data);
2138
2139     imcontext->input_panel_data = calloc (1, length);
2140     memcpy (imcontext->input_panel_data, input_panel_data, length);
2141     imcontext->input_panel_data_length = length;
2142 }
2143
2144 static void
2145 text_input_get_selection_text (void                 *data,
2146                                struct wl_text_input *text_input EINA_UNUSED,
2147                                int32_t              fd)
2148 {
2149     char *selection = NULL;
2150     LOGD ("%d", fd);
2151     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2152     if (!imcontext || !imcontext->ctx) {
2153         LOGD ("");
2154         close (fd);
2155         return;
2156     }
2157
2158     ecore_imf_context_selection_get (imcontext->ctx, &selection);
2159     if (imcontext->text_input) {
2160         SECURE_LOGD ("selection :%s", selection ? selection : "");
2161         if (selection) {
2162             char *_selection = selection;
2163             size_t len = strlen (selection);
2164             while (len) {
2165                 ssize_t ret = write (fd, _selection, len);
2166                 if (ret <= 0) {
2167                     if (errno == EINTR)
2168                         continue;
2169                     LOGW ("write pipe failed, errno: %d", errno);
2170                     break;
2171                 }
2172                 _selection += ret;
2173                 len -= ret;
2174             }
2175         }
2176     }
2177     if (selection)
2178         free (selection);
2179     close (fd);
2180 }
2181
2182 static void
2183 text_input_get_surrounding_text (void                 *data,
2184                                  struct wl_text_input *text_input EINA_UNUSED,
2185                                  uint32_t              maxlen_before,
2186                                  uint32_t              maxlen_after,
2187                                  int32_t              fd)
2188 {
2189     int cursor_pos;
2190     char *surrounding = NULL;
2191     LOGD("fd: %d maxlen_before: %d maxlen_after: %d", fd, maxlen_before, maxlen_after);
2192     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2193     if (!imcontext || !imcontext->ctx) {
2194         LOGD("");
2195         close(fd);
2196         return;
2197     }
2198
2199     /* cursor_pos is a byte index */
2200     if (ecore_imf_context_surrounding_get (imcontext->ctx, &surrounding, &cursor_pos)) {
2201         SECURE_LOGD ("surrounding : '%s', cursor: %d", surrounding ? surrounding : "", cursor_pos);
2202         if (imcontext->text_input) {
2203             Eina_Unicode *wide_surrounding = eina_unicode_utf8_to_unicode (surrounding, NULL);
2204             size_t wlen = eina_unicode_strlen (wide_surrounding);
2205
2206             if (cursor_pos > (int)wlen || cursor_pos < 0)
2207                 cursor_pos = 0;
2208
2209             if (maxlen_before > cursor_pos)
2210                 maxlen_before = 0;
2211             else
2212                 maxlen_before = cursor_pos - maxlen_before;
2213
2214             if (maxlen_after > wlen - cursor_pos)
2215                 maxlen_after = wlen;
2216             else
2217                 maxlen_after = cursor_pos + maxlen_after;
2218
2219             char *req_surrounding = eina_unicode_unicode_to_utf8_range (wide_surrounding + maxlen_before, maxlen_after - maxlen_before, NULL);
2220
2221             ssize_t ret = write(fd, &cursor_pos, sizeof(cursor_pos));
2222             if (ret <= 0) {
2223                 LOGW ("write pipe failed, errno: %d", errno);
2224             } else if (req_surrounding) {
2225                 char *_surrounding = req_surrounding;
2226                 size_t len = strlen(req_surrounding);
2227                 while (len) {
2228                     ssize_t ret = write(fd, _surrounding, len);
2229                     if (ret <= 0) {
2230                         if (errno == EINTR)
2231                             continue;
2232                         LOGW ("write pipe failed, errno: %d", errno);
2233                         break;
2234                     }
2235                     _surrounding += ret;
2236                     len -= ret;
2237                 }
2238             }
2239
2240             if (req_surrounding)
2241                 free (req_surrounding);
2242
2243             if (wide_surrounding)
2244                 free (wide_surrounding);
2245         }
2246
2247         if (surrounding)
2248             free (surrounding);
2249     }
2250     close(fd);
2251 }
2252
2253 static void
2254 text_input_filter_key_event_done(void                 *data,
2255                                  struct wl_text_input *text_input EINA_UNUSED,
2256                                  uint32_t              serial,
2257                                  uint32_t              state)
2258 {
2259     LOGD("serial: %d, state: %d", serial, state);
2260     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2261     if (!imcontext) return;
2262
2263     imcontext->last_key_event_filter.serial = serial;
2264     imcontext->last_key_event_filter.state = state;
2265 }
2266
2267 static void
2268 text_input_hide_permission(void                 *data,
2269                            struct wl_text_input *text_input EINA_UNUSED,
2270                            uint32_t              permission)
2271 {
2272     LOGD("permission : %d", permission);
2273     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2274     if (!imcontext || !imcontext->ctx || ignore_hide)
2275         return;
2276
2277     if (permission)
2278         ecore_imf_context_input_panel_hide(imcontext->ctx);
2279 }
2280
2281 static void
2282 text_input_recapture_string(void                 *data,
2283                             struct wl_text_input *text_input EINA_UNUSED,
2284                             uint32_t              serial,
2285                             int32_t               index,
2286                             uint32_t              length,
2287                             const char           *preedit,
2288                             const char           *preedit_commit,
2289                             const char           *commit)
2290 {
2291     WaylandIMContext *imcontext = (WaylandIMContext *)data;
2292     Eina_Bool old_preedit = EINA_FALSE;
2293     Eina_Bool preedit_changed = EINA_FALSE;
2294
2295     SECURE_LOGD("ctx : %p, preedit event (preedit: '%s', current pre-edit: '%s')",
2296                 imcontext->ctx,
2297                 preedit,
2298                 imcontext->preedit_text ? imcontext->preedit_text : "");
2299
2300     if (!check_serial(imcontext, serial))
2301         return;
2302
2303     old_preedit =
2304         imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
2305
2306     if (imcontext->preedit_text)
2307         preedit_changed = (strcmp(imcontext->preedit_text, preedit) != 0);
2308     else
2309         preedit_changed = (strlen(preedit) != 0);
2310
2311     clear_preedit(imcontext);
2312
2313     // send transaction start
2314     ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_START");
2315
2316     // delete surrounding text
2317     delete_surrounding_text(imcontext, index, length);
2318
2319     // update preedit string
2320     imcontext->preedit_text = strdup(preedit);
2321     imcontext->preedit_commit = (strlen(preedit) > 0 ? strdup(preedit_commit) : NULL);
2322     imcontext->preedit_cursor =
2323         utf8_offset_to_characters(preedit, imcontext->pending_preedit.cursor);
2324     imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
2325
2326     imcontext->pending_preedit.attrs = NULL;
2327
2328     if (preedit_changed) {
2329         if (!old_preedit) {
2330             ecore_imf_context_preedit_start_event_add(imcontext->ctx);
2331             ecore_imf_context_event_callback_call(imcontext->ctx,
2332                     ECORE_IMF_CALLBACK_PREEDIT_START,
2333                     NULL);
2334         }
2335
2336         ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
2337         ecore_imf_context_event_callback_call(imcontext->ctx,
2338                 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
2339                 NULL);
2340
2341         if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
2342             ecore_imf_context_preedit_end_event_add(imcontext->ctx);
2343             ecore_imf_context_event_callback_call(imcontext->ctx,
2344                     ECORE_IMF_CALLBACK_PREEDIT_END,
2345                     NULL);
2346         }
2347     }
2348
2349     // commit string
2350     if (commit && strlen(commit) != 0) {
2351         ecore_imf_context_commit_event_add(imcontext->ctx, commit);
2352         ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)commit);
2353     }
2354
2355     // send transaction end
2356     ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_END");
2357 }
2358 //
2359
2360 static const struct wl_text_input_listener text_input_listener =
2361 {
2362     text_input_enter,
2363     text_input_leave,
2364     text_input_modifiers_map,
2365     text_input_input_panel_state,
2366     text_input_preedit_string,
2367     text_input_preedit_styling,
2368     text_input_preedit_cursor,
2369     text_input_commit_string,
2370     text_input_cursor_position,
2371     text_input_delete_surrounding_text,
2372     text_input_keysym,
2373     text_input_language,
2374     text_input_text_direction,
2375     // TIZEN_ONLY(20150918): Support to set the selection region
2376     text_input_selection_region,
2377     text_input_private_command,
2378     text_input_input_panel_geometry,
2379     text_input_input_panel_data,
2380     text_input_get_selection_text,
2381     text_input_get_surrounding_text,
2382     text_input_filter_key_event_done,
2383     text_input_hide_permission,
2384     text_input_recapture_string
2385     //
2386 };
2387
2388 #ifdef HAVE_VCONF
2389 static void
2390 keyboard_mode_changed_cb (keynode_t *key, void* data)
2391 {
2392     hw_keyboard_mode = vconf_keynode_get_bool (key);
2393     Ecore_IMF_Context *active_ctx = get_using_ctx ();
2394     if (active_ctx) {
2395         LOGD ("ctx : %p, input detect : %d\n", active_ctx, hw_keyboard_mode);
2396
2397         Ecore_IMF_Input_Panel_Keyboard_Mode input_mode = hw_keyboard_mode ? ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE : ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE;
2398         ecore_imf_context_input_panel_event_callback_call (active_ctx, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, input_mode);
2399
2400         if ((input_mode == ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE) && _focused_ctx && (active_ctx == _focused_ctx)) {
2401             if (ecore_imf_context_input_panel_enabled_get (active_ctx)) {
2402                 ecore_imf_context_input_panel_show (active_ctx);
2403             }
2404         }
2405     }
2406 }
2407
2408 #ifdef _TV
2409 static Eina_Bool read_devices = EINA_FALSE;
2410 char ** device_names = NULL;
2411
2412 static Eina_Bool
2413 filter_devices (const char *dev_name)
2414 {
2415     int i;
2416     LOGD("");
2417
2418     if (!dev_name)
2419         return EINA_FALSE;
2420
2421     if (read_devices == EINA_FALSE) {
2422         char *devices = getenv("ISF_REMOTE_CONTROL_DEVICES");
2423         if (devices) {
2424             device_names = eina_str_split(devices, ",", 0);
2425         }
2426         read_devices = EINA_TRUE;
2427     }
2428
2429      if (device_names == NULL) {
2430         return EINA_FALSE;
2431     }
2432
2433     for (i = 0; device_names[i]; i++) {
2434         if (!strcmp (dev_name, device_names[i])) {
2435             return EINA_TRUE;
2436         }
2437     }
2438
2439     return EINA_FALSE;
2440 }
2441 #endif
2442 #endif
2443
2444 void wayland_im_initialize ()
2445 {
2446     register_key_handler ();
2447
2448     /* get input language vconf value */
2449     get_input_language ();
2450
2451 #ifdef HAVE_VCONF
2452     /* get autoperiod allow vconf value */
2453     int val;
2454     if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
2455         if (val == EINA_TRUE)
2456             autoperiod_allow = EINA_TRUE;
2457     }
2458
2459     /* get autocapital allow vconf value */
2460     if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
2461         if (val == EINA_TRUE)
2462             autocap_allow = EINA_TRUE;
2463     }
2464
2465     /* get hardware keyboard input detected vconf value */
2466     if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
2467         if (val == EINA_TRUE)
2468             hw_keyboard_mode = EINA_TRUE;
2469     }
2470
2471     vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL);
2472     vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL);
2473     vconf_notify_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb, NULL);
2474     vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
2475 #endif
2476
2477     _ime_device = ecore_device_add();
2478     if (_ime_device) {
2479         ecore_device_name_set (_ime_device, IME_DEVICE_NAME);
2480         ecore_device_description_set (_ime_device, IME_DEVICE_NAME);
2481         ecore_device_identifier_set (_ime_device, IME_DEVICE_NAME);
2482         ecore_device_class_set (_ime_device, ECORE_DEVICE_CLASS_KEYBOARD);
2483     }
2484 }
2485
2486 void wayland_im_uninitialize ()
2487 {
2488     unregister_key_handler ();
2489
2490     _win_focus_out_handler_del ();
2491     _conformant_change_handler_del ();
2492
2493 #ifdef HAVE_VCONF
2494     vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
2495     vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
2496     vconf_ignore_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb);
2497     vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
2498
2499 #ifdef _TV
2500     if (device_names) {
2501         if (device_names[0])
2502             free (device_names[0]);
2503         free (device_names);
2504         device_names = NULL;
2505     }
2506 #endif
2507 #endif
2508
2509     if (_ime_device) {
2510         ecore_device_del (_ime_device);
2511         _ime_device = NULL;
2512     }
2513 }
2514
2515 void
2516 wayland_im_context_add(Ecore_IMF_Context *ctx)
2517 {
2518     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2519
2520     LOGD("ctx : %p", ctx);
2521
2522     if (!imcontext) return;
2523
2524     imcontext->ctx = ctx;
2525     imcontext->input_panel_layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2526     imcontext->keysym_list = NULL;
2527
2528     imcontext->shift_mask = MOD_SHIFT_MASK;
2529     imcontext->control_mask = MOD_CONTROL_MASK;
2530     imcontext->alt_mask = MOD_ALT_MASK;
2531     imcontext->caps_mask = MOD_CAPS_MASK;
2532     imcontext->num_mask = MOD_NUM_MASK;
2533
2534     imcontext->text_input =
2535         wl_text_input_manager_create_text_input(imcontext->text_input_manager);
2536
2537     if (imcontext->text_input)
2538         wl_text_input_add_listener(imcontext->text_input,
2539                                    &text_input_listener, imcontext);
2540 }
2541
2542 void
2543 wayland_im_context_del (Ecore_IMF_Context *ctx)
2544 {
2545     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2546
2547     Ecore_Event_Key *ev;
2548     LOGD ("ctx : %p, focused_ctx : %p, show_req_ctx : %p", ctx, _focused_ctx, _show_req_ctx);
2549
2550     if (!imcontext) return;
2551
2552     if (_ime_device && imcontext->window)
2553         _device_info_send (ecore_wl_window_id_get (imcontext->window), EINA_FALSE);
2554
2555     // TIZEN_ONLY(20150708): Support back key
2556     if (_input_panel_ctx == ctx) {
2557         _clear_hide_timer();
2558         _input_panel_hide(ctx, EINA_TRUE);
2559         _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2560         _input_panel_ctx = NULL;
2561     }
2562
2563     if (_focused_ctx == ctx)
2564         _focused_ctx = NULL;
2565
2566     if (_show_req_ctx == ctx)
2567         _show_req_ctx = NULL;
2568
2569     if (_focus_req_ctx == ctx) {
2570         if (imcontext->canvas)
2571             evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
2572
2573         _focus_req_ctx = NULL;
2574     }
2575     //
2576
2577     if (imcontext->language) {
2578         free (imcontext->language);
2579         imcontext->language = NULL;
2580     }
2581
2582     // TIZEN_ONLY(20150922): Support to set input panel data
2583     if (imcontext->imdata) {
2584         free (imcontext->imdata);
2585         imcontext->imdata = NULL;
2586         imcontext->imdata_size = 0;
2587     }
2588
2589     if (imcontext->input_panel_data) {
2590         free (imcontext->input_panel_data);
2591         imcontext->input_panel_data = NULL;
2592         imcontext->input_panel_data_length = 0;
2593     }
2594     //
2595
2596     if (imcontext->text_input)
2597         wl_text_input_destroy (imcontext->text_input);
2598
2599     clear_preedit (imcontext);
2600
2601     EINA_LIST_FREE(imcontext->keysym_list, ev) {
2602         free(ev);
2603     }
2604
2605     free(imcontext);
2606 }
2607
2608 void
2609 wayland_im_context_reset(Ecore_IMF_Context *ctx)
2610 {
2611     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2612
2613     LOGD("ctx : %p", ctx);
2614
2615     if (!imcontext) return;
2616
2617     Eina_Bool preedit_empty = check_preedit_empty(imcontext);
2618
2619     commit_preedit (imcontext);
2620     clear_preedit(imcontext);
2621
2622     if (!imcontext->input) return;
2623
2624     if (imcontext->text_input && !preedit_empty) {
2625         wl_text_input_reset(imcontext->text_input);
2626     }
2627     update_state(imcontext);
2628
2629     imcontext->reset_serial = imcontext->serial;
2630 }
2631
2632 void
2633 wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
2634 {
2635
2636     LOGD ("ctx : %p. enable : %d, on demand : %d\n", ctx,
2637           ecore_imf_context_input_panel_enabled_get(ctx),
2638           ecore_imf_context_input_panel_show_on_demand_get (ctx));
2639
2640     if (!set_focus(ctx)) {
2641         LOGW("ctx : %p. Fail to set focus!", ctx);
2642         return;
2643     }
2644
2645     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2646     if (imcontext && imcontext->input && imcontext->text_input)
2647         wl_text_input_set_return_key_disabled(imcontext->text_input,
2648                 imcontext->return_key_disabled);
2649
2650     if (ecore_imf_context_input_panel_enabled_get(ctx))
2651         if (!ecore_imf_context_input_panel_show_on_demand_get (ctx))
2652             show_input_panel(ctx);
2653         else
2654             LOGD ("ctx : %p input panel on demand mode : TRUE\n", ctx);
2655     else
2656         LOGD ("ctx : %p input panel enable : FALSE\n", ctx);
2657 }
2658
2659 void
2660 wayland_im_context_focus_out(Ecore_IMF_Context *ctx)
2661 {
2662     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2663
2664     LOGD("ctx : %p", ctx);
2665
2666     if (_focus_req_ctx == ctx)
2667         _focus_req_ctx = NULL;
2668
2669     if (!imcontext || !imcontext->input) return;
2670
2671     if (ecore_imf_context_input_panel_enabled_get(ctx)) {
2672         ecore_imf_context_input_panel_hide(ctx);
2673     }
2674
2675     set_focus_out(ctx);
2676 }
2677
2678 void
2679 wayland_im_context_preedit_string_get(Ecore_IMF_Context  *ctx,
2680                                       char              **str,
2681                                       int                *cursor_pos)
2682 {
2683     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2684     if (!imcontext) return;
2685
2686     SECURE_LOGD("pre-edit string requested (preedit: '%s')",
2687                 imcontext->preedit_text ? imcontext->preedit_text : "");
2688
2689     if (str)
2690         *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
2691
2692     if (cursor_pos)
2693         *cursor_pos = imcontext->preedit_cursor;
2694 }
2695
2696 void
2697 wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context  *ctx,
2698                                                       char              **str,
2699                                                       Eina_List         **attrs,
2700                                                       int                *cursor_pos)
2701 {
2702     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2703     if (!imcontext) return;
2704
2705     SECURE_LOGD("pre-edit string with attributes requested (preedit: '%s')",
2706                 imcontext->preedit_text ? imcontext->preedit_text : "");
2707
2708     if (str)
2709         *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
2710
2711     if (attrs) {
2712         Eina_List *l;
2713         Ecore_IMF_Preedit_Attr *a, *attr;
2714
2715         if (imcontext->preedit_attrs) {
2716             EINA_LIST_FOREACH(imcontext->preedit_attrs, l, a) {
2717                 attr = malloc(sizeof(*attr));
2718                 attr = memcpy(attr, a, sizeof(*attr));
2719                 *attrs = eina_list_append(*attrs, attr);
2720             }
2721         }
2722         else {
2723             if (imcontext->preedit_text) {
2724                 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
2725                 // use REVERSE style as default
2726                 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
2727                 attr->start_index = 0;
2728                 attr->end_index = strlen(imcontext->preedit_text);
2729                 *attrs = eina_list_append(*attrs, attr);
2730             }
2731         }
2732     }
2733
2734     if (cursor_pos)
2735         *cursor_pos = imcontext->preedit_cursor;
2736 }
2737
2738 void
2739 wayland_im_context_cursor_position_set (Ecore_IMF_Context *ctx,
2740                                        int                cursor_pos)
2741 {
2742     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2743     if (!imcontext) return;
2744
2745     if (imcontext->cursor_position != cursor_pos) {
2746         imcontext->cursor_position = cursor_pos;
2747
2748         if (imcontext->input && imcontext->text_input) {
2749             LOGD ("ctx : %p, cursor pos : %d\n", ctx, cursor_pos);
2750
2751             set_autocapital (ctx);
2752
2753             if (!imcontext->preedit_text || strlen(imcontext->preedit_text) == 0)
2754                 wl_text_input_set_cursor_position (imcontext->text_input, cursor_pos);
2755         }
2756     }
2757 }
2758
2759 void
2760 wayland_im_context_use_preedit_set(Ecore_IMF_Context *ctx EINA_UNUSED,
2761                                    Eina_Bool          use_preedit EINA_UNUSED)
2762 {
2763 }
2764
2765 void
2766 wayland_im_context_client_window_set(Ecore_IMF_Context *ctx,
2767                                      void              *window)
2768 {
2769     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2770
2771     LOGD("client window set (window: %p)", window);
2772
2773     if (imcontext && window) {
2774         imcontext->window = ecore_wl_window_find((Ecore_Window)window);
2775
2776         if (_ime_device && imcontext->window)
2777             _device_info_send (ecore_wl_window_id_get (imcontext->window), EINA_TRUE);
2778     }
2779 }
2780
2781 void
2782 wayland_im_context_client_canvas_set(Ecore_IMF_Context *ctx,
2783                                      void              *canvas)
2784 {
2785     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2786
2787     LOGD("client canvas set (canvas: %p)", canvas);
2788
2789     if (imcontext && canvas) {
2790         imcontext->canvas = canvas;
2791
2792         if (!imcontext->window)
2793             imcontext->window = ecore_wl_window_find(ecore_evas_window_get(ecore_evas_ecore_evas_get(canvas)));
2794
2795         if (_ime_device && imcontext->window)
2796             _device_info_send (ecore_wl_window_id_get (imcontext->window), EINA_TRUE);
2797     }
2798 }
2799
2800 void
2801 wayland_im_context_show(Ecore_IMF_Context *ctx)
2802 {
2803     LOGD("ctx : %p", ctx);
2804
2805     show_input_panel(ctx);
2806 }
2807
2808 void
2809 wayland_im_context_hide(Ecore_IMF_Context *ctx)
2810 {
2811     LOGD("ctx : %p", ctx);
2812
2813     if (!get_using_ctx()) {
2814         LOGW("Can't hide input_panel because there is no using context!!");
2815         return;
2816     }
2817
2818     _input_panel_hide(ctx, EINA_FALSE);
2819 }
2820
2821 #if !(ENABLE_GRAB_KEYBOARD)
2822 static unsigned int
2823 _ecore_imf_lock_to_ecore_key_modifier(unsigned int locks)
2824 {
2825    unsigned int mask = 0;
2826
2827     if (locks & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
2828         mask |= ECORE_EVENT_LOCK_SCROLL;
2829
2830     if (locks & ECORE_IMF_KEYBOARD_LOCK_CAPS)
2831         mask |= ECORE_EVENT_LOCK_CAPS;
2832
2833     if (locks & ECORE_IMF_KEYBOARD_LOCK_NUM)
2834         mask |= ECORE_EVENT_LOCK_NUM;
2835
2836    return mask;
2837 }
2838
2839 static unsigned int
2840 _ecore_imf_modifier_to_ecore_key_modifier(Ecore_IMF_Keyboard_Modifiers modifiers)
2841 {
2842    unsigned int mask = 0;
2843
2844    /**< "Control" is pressed */
2845    if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
2846      mask |= ECORE_EVENT_MODIFIER_CTRL;
2847
2848    /**< "Alt" is pressed */
2849    if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
2850      mask |= ECORE_EVENT_MODIFIER_ALT;
2851
2852    /**< "Shift" is pressed */
2853    if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
2854      mask |= ECORE_EVENT_MODIFIER_SHIFT;
2855
2856    /**< "Win" (between "Ctrl" and "Alt") is pressed */
2857    if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
2858      mask |= ECORE_EVENT_MODIFIER_WIN;
2859
2860    /**< "AltGr" is pressed */
2861    if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
2862      mask |= ECORE_EVENT_MODIFIER_ALTGR;
2863
2864    return mask;
2865 }
2866 #endif
2867
2868 Eina_Bool
2869 wayland_im_context_filter_event(Ecore_IMF_Context    *ctx,
2870                                 Ecore_IMF_Event_Type  type,
2871                                 Ecore_IMF_Event      *imf_event)
2872 {
2873
2874 #if !(ENABLE_GRAB_KEYBOARD)
2875     Eina_Bool ret = EINA_FALSE;
2876     Ecore_Event_Key ecore_key_ev;
2877     char *key_dev_name = NULL;
2878     uint32_t key_dev_class = 0;
2879     uint32_t key_dev_subclass = 0;
2880 #endif
2881     if (type == ECORE_IMF_EVENT_MOUSE_UP) {
2882         if (ecore_imf_context_input_panel_enabled_get(ctx)) {
2883             LOGD ("[Mouse-up event] ctx : %p\n", ctx);
2884             if (ctx == _focused_ctx) {
2885                 ecore_imf_context_input_panel_show(ctx);
2886             }
2887             else
2888                 LOGE ("Can't show IME because there is no focus. ctx : %p\n", ctx);
2889         }
2890     }
2891 #if !(ENABLE_GRAB_KEYBOARD)
2892     else if (type == ECORE_IMF_EVENT_KEY_UP) {
2893         Ecore_IMF_Event_Key_Up *key_ev = (Ecore_IMF_Event_Key_Up *)imf_event;
2894         ecore_key_ev.keyname = key_ev->keyname;
2895         ecore_key_ev.key = key_ev->key;
2896         ecore_key_ev.string = key_ev->string;
2897         ecore_key_ev.compose = key_ev->compose;
2898         ecore_key_ev.timestamp = key_ev->timestamp;
2899         ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
2900         ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
2901         key_dev_name = (char *)key_ev->dev_name;
2902         key_dev_class = key_ev->dev_class;
2903         key_dev_subclass = key_ev->dev_subclass;
2904     }
2905     else if (type == ECORE_IMF_EVENT_KEY_DOWN) {
2906         Ecore_IMF_Event_Key_Down *key_ev = (Ecore_IMF_Event_Key_Down *)imf_event;
2907         ecore_key_ev.keyname = key_ev->keyname;
2908         ecore_key_ev.key = key_ev->key;
2909         ecore_key_ev.string = key_ev->string;
2910         ecore_key_ev.compose = key_ev->compose;
2911         ecore_key_ev.timestamp = key_ev->timestamp;
2912         ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
2913         ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
2914         key_dev_name = (char *)key_ev->dev_name;
2915         key_dev_class = key_ev->dev_class;
2916         key_dev_subclass = key_ev->dev_subclass;
2917     }
2918
2919     if (type == ECORE_IMF_EVENT_KEY_UP || type == ECORE_IMF_EVENT_KEY_DOWN) {
2920         WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2921         if (!imcontext || !imcontext->input || !imcontext->text_input)
2922             return EINA_FALSE;
2923
2924         if (!_focused_ctx) {
2925             LOGD ("no focus\n");
2926             return EINA_FALSE;
2927         }
2928
2929 #ifdef _TV
2930         if (strcmp (ecore_key_ev.keyname, "Return") == 0 && type == ECORE_IMF_EVENT_KEY_DOWN && filter_devices (key_dev_name) && hw_keyboard_mode == EINA_TRUE) {
2931             LOGD ("Changed keyboard mode from H/W to S/W ");
2932             hw_keyboard_mode = EINA_FALSE;
2933             vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
2934
2935             if (ecore_imf_context_input_panel_enabled_get (ctx)) {
2936                 ecore_imf_context_input_panel_show (ctx);
2937             }
2938             return EINA_TRUE;
2939         }
2940 #endif
2941
2942         do {
2943             if (!ecore_key_ev.timestamp && (ecore_key_ev.modifiers & MOD_Mod5_MASK)) {
2944                 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
2945                     if (strcmp (ecore_key_ev.key, "space") == 0 ||
2946                         strcmp (ecore_key_ev.key, "KP_Space") == 0 ) {
2947                         autoperiod_insert (ctx);
2948                     }
2949                 }
2950
2951                 LOGD("Return! This is SW keyboard fake event!");
2952                 break;
2953             }
2954
2955             int serial = imcontext->serial++;
2956             double start_time = ecore_time_get();
2957
2958             /* xkb_mod_mask */
2959             uint32_t modifiers = 0;
2960             if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_SHIFT)
2961                 modifiers |= imcontext->shift_mask;
2962             if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_CTRL)
2963                 modifiers |= imcontext->control_mask;
2964             if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_ALT)
2965                 modifiers |= imcontext->alt_mask;
2966             if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_CAPS)
2967                 modifiers |= imcontext->caps_mask;
2968             if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_NUM)
2969                 modifiers |= imcontext->num_mask;
2970
2971             SECURE_LOGD ("ev:modifiers=0x%x, modifiers=0x%x, shift_mask=0x%x, control_mask=0x%0x, alt_mask=0x%x, caps_mask=0x%x, num_mask=0x%x", ecore_key_ev.modifiers, modifiers, imcontext->shift_mask, imcontext->control_mask, imcontext->alt_mask, imcontext->caps_mask, imcontext->num_mask);
2972             //Send key event to IME.
2973             wl_text_input_filter_key_event(imcontext->text_input, serial, ecore_key_ev.timestamp, ecore_key_ev.key,
2974                                            type == ECORE_IMF_EVENT_KEY_UP? WL_KEYBOARD_KEY_STATE_RELEASED : WL_KEYBOARD_KEY_STATE_PRESSED,
2975                                            modifiers, (key_dev_name ? key_dev_name : ""), key_dev_class, key_dev_subclass);
2976             //Waiting for filter_key_event_done from IME.
2977             //This function should return IME filtering result with boolean type.
2978             struct wl_display *display = ecore_wl_display_get();
2979             if (display) {
2980                 while (ecore_time_get() - start_time < WAIT_FOR_FILTER_DONE_SECOND && wl_display_roundtrip(display) != -1) {
2981                     if (imcontext->last_key_event_filter.serial == serial) {
2982                         ret = imcontext->last_key_event_filter.state;
2983                         break;
2984                     } else if (imcontext->last_key_event_filter.serial > serial)
2985                         break;
2986                 }
2987             }
2988             LOGD ("elapsed : %.3f ms, serial (last, require) : (%d, %d)", (ecore_time_get() - start_time)*1000, imcontext->last_key_event_filter.serial, serial);
2989         } while (0);
2990
2991         if (type == ECORE_IMF_EVENT_KEY_DOWN) {
2992             if (ret == EINA_FALSE) {
2993                 if (strcmp (ecore_key_ev.key, "space") == 0 ||
2994                     strcmp (ecore_key_ev.key, "KP_Space") == 0) {
2995                     autoperiod_insert (ctx);
2996                 }
2997             }
2998         }
2999
3000         //Deal with the next key event in list.
3001         Ecore_Event_Key *ev = NULL;
3002         if (eina_list_count (imcontext->keysym_list)) {
3003             Eina_List *n = eina_list_last(imcontext->keysym_list);
3004             ev = (Ecore_Event_Key *)eina_list_data_get(n);
3005             int type = (unsigned long int)ev->data;
3006
3007             ev->data = NULL;
3008             ecore_event_add(type, ev, NULL, NULL);
3009             imcontext->keysym_list = eina_list_remove_list(imcontext->keysym_list, n);
3010         }
3011     }
3012
3013     return ret;
3014 #else
3015     return EINA_FALSE;
3016 #endif
3017 }
3018
3019 void
3020 wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int width, int height)
3021 {
3022     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3023     if (!imcontext) return;
3024
3025     if ((imcontext->cursor_location.x != x) ||
3026         (imcontext->cursor_location.y != y) ||
3027         (imcontext->cursor_location.width != width) ||
3028         (imcontext->cursor_location.height != height)) {
3029         imcontext->cursor_location.x = x;
3030         imcontext->cursor_location.y = y;
3031         imcontext->cursor_location.width = width;
3032         imcontext->cursor_location.height = height;
3033
3034         if (_focused_ctx == ctx)
3035             send_cursor_location (imcontext);
3036     }
3037 }
3038
3039 void wayland_im_context_autocapital_type_set(Ecore_IMF_Context *ctx,
3040                                                   Ecore_IMF_Autocapital_Type autocapital_type)
3041 {
3042     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3043     if (!imcontext) return;
3044
3045     imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
3046                                  // TIZEN_ONLY(20160201): Add autocapitalization word
3047                                  WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION |
3048                                  //
3049                                  WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
3050                                  WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE);
3051
3052     if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE)
3053         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION;
3054     // TIZEN_ONLY(20160201): Add autocapitalization word
3055     else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD)
3056         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
3057     //
3058     else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER)
3059         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE;
3060     else
3061         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE;
3062
3063     if (imcontext->input && imcontext->text_input) {
3064         LOGD ("ctx : %p. set autocapital type : %d\n", ctx, autocapital_type);
3065         wl_text_input_set_content_type(imcontext->text_input,
3066                 imcontext->content_hint,
3067                 get_purpose(ctx));
3068     }
3069 }
3070
3071 void
3072 wayland_im_context_input_panel_layout_set(Ecore_IMF_Context *ctx,
3073                                           Ecore_IMF_Input_Panel_Layout layout)
3074 {
3075     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3076     if (!imcontext) return;
3077
3078     imcontext->input_panel_layout = layout;
3079
3080     switch (layout) {
3081         case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER:
3082             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
3083             break;
3084         case ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL:
3085             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL;
3086             break;
3087         case ECORE_IMF_INPUT_PANEL_LAYOUT_URL:
3088             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_URL;
3089             break;
3090         case ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER:
3091             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE;
3092             break;
3093         case ECORE_IMF_INPUT_PANEL_LAYOUT_IP:
3094             // TIZEN_ONLY(20150710): Support IP and emoticon layout
3095             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_IP;
3096             //
3097             break;
3098         case ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH:
3099             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATE;
3100             break;
3101         case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY:
3102             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
3103             break;
3104         case ECORE_IMF_INPUT_PANEL_LAYOUT_HEX:
3105             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_HEX;
3106             break;
3107         case ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL:
3108             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL;
3109             break;
3110         case ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD:
3111             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
3112             imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3113             break;
3114         case ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME:
3115             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME;
3116             break;
3117             // TIZEN_ONLY(20150710): Support IP and emoticon layout
3118         case ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON:
3119             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON;
3120             break;
3121             //
3122         case ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE:
3123             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE;
3124             break;
3125         default:
3126             imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
3127             break;
3128     }
3129
3130     if (imcontext->input && imcontext->text_input) {
3131         LOGD ("ctx : %p, layout type : %d\n", ctx, layout);
3132         wl_text_input_set_content_type(imcontext->text_input,
3133                 imcontext->content_hint,
3134                 get_purpose(ctx));
3135     }
3136 }
3137
3138 Ecore_IMF_Input_Panel_Layout
3139 wayland_im_context_input_panel_layout_get(Ecore_IMF_Context *ctx)
3140 {
3141     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3142     if (!imcontext) return ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
3143
3144     return imcontext->input_panel_layout;
3145 }
3146
3147 void
3148 wayland_im_context_input_mode_set(Ecore_IMF_Context *ctx,
3149                                   Ecore_IMF_Input_Mode input_mode)
3150 {
3151     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3152     if (!imcontext) return;
3153
3154     if (input_mode & ECORE_IMF_INPUT_MODE_INVISIBLE)
3155         imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3156     else
3157         imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3158
3159     if (imcontext->input && imcontext->text_input) {
3160         LOGD ("ctx : %p, input mode : %d\n", ctx, input_mode);
3161         wl_text_input_set_content_type(imcontext->text_input,
3162                 imcontext->content_hint,
3163                 get_purpose(ctx));
3164     }
3165 }
3166
3167 void
3168 wayland_im_context_input_hint_set(Ecore_IMF_Context *ctx,
3169                                   Ecore_IMF_Input_Hints input_hints)
3170 {
3171     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3172     if (!imcontext) return;
3173
3174     if (input_hints & ECORE_IMF_INPUT_HINT_AUTO_COMPLETE)
3175         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3176     else
3177         imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3178
3179     if (input_hints & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA)
3180         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3181     else
3182         imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3183
3184     if (input_hints & ECORE_IMF_INPUT_HINT_MULTILINE)
3185         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3186     else
3187         imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3188
3189     if (imcontext->input && imcontext->text_input) {
3190         LOGD("ctx : %p, input hint : %#x\n", ctx, input_hints);
3191         wl_text_input_set_content_type(imcontext->text_input,
3192                 imcontext->content_hint,
3193                 get_purpose(ctx));
3194     }
3195 }
3196
3197 void
3198 wayland_im_context_input_panel_language_set(Ecore_IMF_Context *ctx,
3199                                             Ecore_IMF_Input_Panel_Lang lang)
3200 {
3201     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3202     if (!imcontext) return;
3203
3204     if (lang == ECORE_IMF_INPUT_PANEL_LANG_ALPHABET)
3205         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3206     else
3207         imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3208
3209     if (imcontext->input && imcontext->text_input)
3210         wl_text_input_set_content_type(imcontext->text_input,
3211                 imcontext->content_hint,
3212                 get_purpose(ctx));
3213 }
3214
3215 // TIZEN_ONLY(20150708): Support input_panel_state_get
3216 Ecore_IMF_Input_Panel_State
3217 wayland_im_context_input_panel_state_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3218 {
3219     return _input_panel_state;
3220 }
3221
3222 void
3223 wayland_im_context_input_panel_return_key_type_set(Ecore_IMF_Context *ctx,
3224                                                    Ecore_IMF_Input_Panel_Return_Key_Type return_key_type)
3225 {
3226     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3227     if (!imcontext) return;
3228
3229     imcontext->return_key_type = return_key_type;
3230
3231     if (imcontext->input && imcontext->text_input)
3232         wl_text_input_set_return_key_type(imcontext->text_input,
3233                 imcontext->return_key_type);
3234 }
3235
3236 void
3237 wayland_im_context_input_panel_return_key_disabled_set(Ecore_IMF_Context *ctx,
3238                                                        Eina_Bool disabled)
3239 {
3240     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3241     if (!imcontext) return;
3242
3243     imcontext->return_key_disabled = disabled;
3244
3245     if (imcontext->input && imcontext->text_input)
3246         wl_text_input_set_return_key_disabled(imcontext->text_input,
3247                 imcontext->return_key_disabled);
3248 }
3249 //
3250
3251 void
3252 wayland_im_context_input_panel_language_locale_get(Ecore_IMF_Context *ctx,
3253                                                    char **locale)
3254 {
3255     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3256     if (!imcontext) return;
3257
3258     if (locale)
3259         *locale = strdup(imcontext->language ? imcontext->language : "");
3260 }
3261
3262 void
3263 wayland_im_context_prediction_allow_set(Ecore_IMF_Context *ctx,
3264                                         Eina_Bool prediction)
3265 {
3266     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3267     if (!imcontext) return;
3268
3269     if (prediction)
3270         imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3271     else
3272         imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3273
3274     if (imcontext->input && imcontext->text_input)
3275         wl_text_input_set_content_type(imcontext->text_input,
3276                 imcontext->content_hint,
3277                 get_purpose(ctx));
3278 }
3279
3280 // TIZEN_ONLY(20151221): Support input panel geometry
3281 void
3282 wayland_im_context_input_panel_geometry_get(Ecore_IMF_Context *ctx EINA_UNUSED,
3283                                             int *x, int *y, int *w, int *h)
3284 {
3285     if (x)
3286         *x = _keyboard_geometry.x;
3287     if (y)
3288         *y = _keyboard_geometry.y;
3289     if (w)
3290         *w = _keyboard_geometry.w;
3291     if (h)
3292         *h = _keyboard_geometry.h;
3293 }
3294
3295 void
3296 wayland_im_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *data, int length)
3297 {
3298     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3299     if (!imcontext) return;
3300
3301     if (data && length > 0) {
3302         const char *custom_conformant_enabled = "conformant:custom,enabled";
3303         const char *custom_conformant_disabled = "conformant:custom,disabled";
3304         const char *custom_conformant_finished = "conformant:custom,finished";
3305
3306         if(strncmp(data, custom_conformant_enabled, strlen(custom_conformant_enabled)) == 0) {
3307             _custom_conformant_event = EINA_TRUE;
3308             return;
3309         }
3310         if(strncmp(data, custom_conformant_disabled, strlen(custom_conformant_disabled)) == 0) {
3311             _custom_conformant_event = EINA_FALSE;
3312             return;
3313         }
3314         if(strncmp(data, custom_conformant_finished, strlen(custom_conformant_finished)) == 0) {
3315             if (_custom_conformant_event) {
3316                 _conformant_reset_done = EINA_TRUE;
3317                 LOGD("[conformant:custom,finished], _conformant_reset_done = 1\n");
3318                 send_will_hide_ack(NULL);
3319             }
3320             return;
3321         }
3322     }
3323
3324     if (imcontext->imdata)
3325         free(imcontext->imdata);
3326
3327     imcontext->imdata = calloc(1, length);
3328     memcpy(imcontext->imdata, data, length);
3329     imcontext->imdata_size = length;
3330
3331     if (imcontext->input && imcontext->text_input && (imcontext->imdata_size > 0))
3332         wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
3333 }
3334
3335 void
3336 wayland_im_context_input_panel_imdata_get(Ecore_IMF_Context *ctx, void *data, int *length)
3337 {
3338     if (!ctx) return;
3339     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3340
3341     if (imcontext && imcontext->input_panel_data && (imcontext->input_panel_data_length > 0)) {
3342         if (data)
3343             memcpy(data, imcontext->input_panel_data, imcontext->input_panel_data_length);
3344
3345         if (length)
3346             *length = imcontext->input_panel_data_length;
3347     }
3348     else
3349         if (length)
3350             *length = 0;
3351 }
3352 //
3353
3354 // TIZEN_ONLY(20160218): Support BiDi direction
3355 void
3356 wayland_im_context_bidi_direction_set(Ecore_IMF_Context *ctx, Ecore_IMF_BiDi_Direction bidi_direction)
3357 {
3358     WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3359     if (!imcontext) return;
3360
3361     imcontext->bidi_direction = bidi_direction;
3362
3363     if (imcontext->input && imcontext->text_input) {
3364         LOGD ("ctx : %p, bidi direction : %#x\n", ctx, bidi_direction);
3365         wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
3366     }
3367 }
3368 //
3369
3370 WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager)
3371 {
3372     WaylandIMContext *context = calloc(1, sizeof(WaylandIMContext));
3373
3374     LOGD("new context created");
3375     context->text_input_manager = text_input_manager;
3376
3377     return context;
3378 }