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