2 * Copyright © 2012, 2013 Intel Corporation
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.
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.
23 #include "scim_private.h"
27 #include <Ecore_Evas.h>
28 #include <Ecore_Input.h>
29 #define EFL_BETA_API_SUPPORT
30 #include <Ecore_Wl2.h>
33 #include <app_common.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
45 #include "isf_debug.h"
46 #include "wayland_imcontext.h"
47 #include "tizen_profile.h"
48 #include "isf_device_event.h"
53 #define LOG_TAG "IMMODULE"
55 #define IME_DEVICE_NAME "ime"
57 #define HIDE_TIMER_INTERVAL 0.05
58 #define WAIT_FOR_FILTER_DONE_SECOND 2
60 #define MOD_SHIFT_MASK 0x01
61 #define MOD_CAPS_MASK 0x02
62 #define MOD_CONTROL_MASK 0x04
63 #define MOD_ALT_MASK 0x08
64 #define MOD_NUM_MASK 0x100
65 #define MOD_Mod5_MASK 0x80
67 #define VCONFKEY_AUTOPERIOD_ALLOW_BOOL "file/private/isf/autoperiod_allow"
68 #define VCONFKEY_AUTOCAPITAL_ALLOW_BOOL "file/private/isf/autocapital_allow"
69 #define SOCK_PATH "/run/.isf/scim-panel-socket"
74 INPUT_LANG_BENGALI_IN,
75 INPUT_LANG_BENGALI_BD,
90 INPUT_LANG_ASSAMESE_BN,
91 INPUT_LANG_BENGALI_AS,
95 INPUT_LANG_MANIPURI_AS,
96 INPUT_LANG_MANIPURI_BN,
101 const double DOUBLE_SPACE_INTERVAL = 1.0;
103 static Eina_Bool _clear_hide_timer();
104 static Ecore_Timer *_hide_timer = NULL;
106 static const char *_ecore_imf_event_empty = "";
108 // TIZEN_ONLY(20150708): Support back key
109 #define BACK_KEY "XF86Back"
110 #define OLD_BACK_KEY "XF86Stop"
112 static Eina_Bool will_hide = EINA_FALSE;
113 static Eina_Bool ignore_hide = EINA_FALSE;
115 static Ecore_Event_Filter *_ecore_event_filter_handler = NULL;
116 static Ecore_IMF_Context *_focused_ctx = NULL;
117 static Ecore_IMF_Context *_show_req_ctx = NULL;
118 static Ecore_IMF_Context *_hide_req_ctx = NULL;
119 static Ecore_IMF_Context *_focus_req_ctx = NULL;
120 static Ecore_IMF_Context *_input_panel_ctx = NULL;
121 static Eina_Bool _focus_req_only = EINA_TRUE;
123 static Eina_Rectangle _keyboard_geometry = {0, 0, 0, 0};
125 static Ecore_IMF_Input_Panel_State _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
126 static Ecore_Event_Handler *_win_focus_out_handler = NULL;
127 static Ecore_Event_Handler *_conformant_change_handler = NULL;
129 static Eina_Bool _custom_conformant_event = EINA_FALSE;
130 static Eina_Bool _received_will_hide_event = EINA_FALSE;
131 static Eina_Bool _conformant_reset_done = EINA_FALSE;
132 static Eina_Bool _conformant_reset_started = EINA_FALSE;
133 static Evas *_active_context_canvas = NULL;
134 static unsigned int _active_context_window_id = 0;
136 static Ecore_Device *_ime_device = NULL;
138 static double space_key_time = 0.0;
139 static Eina_Bool autoperiod_allow = EINA_FALSE;
140 static Eina_Bool autocap_allow = EINA_FALSE;
141 static Eina_Bool hw_keyboard_mode = EINA_FALSE;
142 static Eina_Bool _preedit_cursor_changed = EINA_FALSE;
144 static Input_Language input_lang = INPUT_LANG_OTHER;
145 static Evas_Coord g_scr_w = 0, g_scr_h = 0;
147 static void set_autocapital (Ecore_IMF_Context *ctx);
149 static Eina_Bool g_key_rate_checked = EINA_FALSE, g_focused = EINA_FALSE;
150 static double g_original_key_rate = 0.0, g_original_key_delay = 0.0, g_desired_key_rate = 0.0;
153 typedef struct __LanguageInfo {
156 Eina_Unicode punc_code;
159 static LanguageInfo __language_infos [] = {
160 { "ur_PK", INPUT_LANG_URDU, 0x06D4 },
161 { "hi_IN", INPUT_LANG_HINDI, 0x0964 },
162 { "bn_IN", INPUT_LANG_BENGALI_IN, 0x0964 },
163 { "bn_BD", INPUT_LANG_BENGALI_BD, 0x0964 },
164 { "as_IN", INPUT_LANG_ASSAMESE, 0x0964 },
165 { "pa_IN", INPUT_LANG_PUNJABI, 0x0964 },
166 { "ne_NP", INPUT_LANG_NEPALI, 0x0964 },
167 { "or_IN", INPUT_LANG_ORIYA, 0x0964 },
168 { "mai_IN", INPUT_LANG_MAITHILI, 0x0964 },
169 { "hy_AM", INPUT_LANG_ARMENIAN, 0x0589 },
170 { "zh_CN", INPUT_LANG_CN, 0x3002 },
171 { "zh_HK", INPUT_LANG_CN_HK, 0x3002 },
172 { "zh_TW", INPUT_LANG_CN_TW, 0x3002 },
173 { "ja_JP", INPUT_LANG_JAPANESE, 0x3002 },
174 { "km_KH", INPUT_LANG_KHMER, 0x17D4 },
175 { "ko_KR", INPUT_LANG_KOREAN, 0x002E },
176 { "asb_IN", INPUT_LANG_ASSAMESE_BN, 0x0964 },
177 { "bna_IN", INPUT_LANG_BENGALI_AS, 0x0964 },
178 { "brx_IN", INPUT_LANG_BODO, 0x0964 },
179 { "doi_IN", INPUT_LANG_DOGRI, 0x0964 },
180 { "mni_IN", INPUT_LANG_MANIPURI, 0xabeb },
181 { "mnia_IN",INPUT_LANG_MANIPURI_AS, 0x0964 },
182 { "mnib_IN",INPUT_LANG_MANIPURI_BN, 0x0964 },
183 { "kok_IN", INPUT_LANG_KONKANI, 0x0964 },
184 { "sd_IN", INPUT_LANG_SINDHI, 0x0964 },
187 struct _WaylandIMContext
189 Ecore_IMF_Context *ctx;
191 struct wl_text_input_manager *text_input_manager;
192 struct wl_text_input *text_input;
194 Ecore_Wl2_Window *window;
195 Ecore_Wl2_Input *input;
199 char *preedit_commit;
201 Eina_List *preedit_attrs;
202 int32_t preedit_cursor;
210 int32_t cursor_position;
220 xkb_mod_mask_t control_mask;
221 xkb_mod_mask_t alt_mask;
222 xkb_mod_mask_t shift_mask;
223 xkb_mod_mask_t caps_mask;
224 xkb_mod_mask_t num_mask;
227 uint32_t content_purpose;
228 uint32_t content_hint;
229 Ecore_IMF_Input_Panel_Layout input_panel_layout;
231 // TIZEN_ONLY(20150716): Support return key type
232 uint32_t return_key_type;
234 Eina_Bool return_key_disabled;
237 uint32_t imdata_size;
239 uint32_t bidi_direction;
241 void *input_panel_data;
242 uint32_t input_panel_data_length;
248 } last_key_event_filter;
249 Eina_List *keysym_list;
251 uint32_t reset_serial;
253 Eina_Bool has_conformant;
254 char *prediction_hint;
261 } input_panel_position;
266 Ecore_IMF_Context *ctx;
267 WaylandIMContext *imcontext;
268 } Ecore_Imf_Wayland_Imcontext_Pair;
269 Eina_List *_ecore_imf_wayland_imcontext_pair_list = NULL;
271 static void _ecore_imf_wayland_imcontext_pair_add (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
273 Ecore_Imf_Wayland_Imcontext_Pair *pair = malloc (sizeof (Ecore_Imf_Wayland_Imcontext_Pair));
276 pair->imcontext = imcontext;
278 _ecore_imf_wayland_imcontext_pair_list = eina_list_append (_ecore_imf_wayland_imcontext_pair_list, pair);
282 static Ecore_Imf_Wayland_Imcontext_Pair* _ecore_imf_wayland_imcontext_pair_find (Ecore_IMF_Context *ctx)
285 Ecore_Imf_Wayland_Imcontext_Pair *pair;
286 EINA_LIST_FOREACH (_ecore_imf_wayland_imcontext_pair_list, l, pair)
287 if (pair->ctx == ctx) {
290 LOGE("The Ecore_Imf %p if not found in Ecore_IMF-WaylandIMContext pair list!!", ctx);
294 static void _ecore_imf_wayland_imcontext_pair_del (Ecore_IMF_Context *ctx)
298 Ecore_Imf_Wayland_Imcontext_Pair *pair;
300 EINA_LIST_FOREACH_SAFE (_ecore_imf_wayland_imcontext_pair_list, l, l_next, pair)
301 if (ctx == pair->ctx) {
303 _ecore_imf_wayland_imcontext_pair_list = eina_list_remove_list (_ecore_imf_wayland_imcontext_pair_list, l);
307 static void _ecore_imf_wayland_imcontext_pair_destroy ()
309 if (_ecore_imf_wayland_imcontext_pair_list) {
310 Ecore_Imf_Wayland_Imcontext_Pair *pair;
311 EINA_LIST_FREE (_ecore_imf_wayland_imcontext_pair_list, pair)
313 _ecore_imf_wayland_imcontext_pair_list = NULL;
317 static int _ecore_imf_wayland_imcontext_pair_log ()
319 char buffer[255] = { '\0' };
322 Ecore_Imf_Wayland_Imcontext_Pair *pair;
323 EINA_LIST_FOREACH(_ecore_imf_wayland_imcontext_pair_list, l, pair) {
325 snprintf(buffer + strlen(buffer), 255 - strlen(buffer), "%s[%p/%p]", (count ? "," : ""), pair->ctx, pair->imcontext);
330 LOGD("No Ecore_Imf / Wayland_Imcontext pair found");
332 LOGD("%d Pair(s) : %s", count, buffer);
338 // TIZEN_ONLY(20150708): Support back key
339 static void _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant);
340 static Eina_Bool show_input_panel(Ecore_IMF_Context *ctx);
343 reset_keyboard_geometry ()
345 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
346 if (wl2_display && (g_scr_w == 0 || g_scr_h == 0)) {
348 ecore_wl2_display_screen_size_get(wl2_display, &g_scr_w, &g_scr_h);
350 _keyboard_geometry.x = 0;
351 _keyboard_geometry.y = g_scr_h;
352 _keyboard_geometry.w = 0;
353 _keyboard_geometry.h = 0;
357 _device_info_free (void *data EINA_UNUSED, void *ev)
359 Ecore_Event_Device_Info *e;
362 eina_stringshare_del (e->name);
363 eina_stringshare_del (e->identifier);
364 eina_stringshare_del (e->seatname);
370 _device_info_send (unsigned int window, Eina_Bool flag)
372 Ecore_Event_Device_Info *e;
374 if (!(e = calloc (1, sizeof (Ecore_Event_Device_Info)))) return;
376 e->name = eina_stringshare_ref (IME_DEVICE_NAME);
377 e->identifier = eina_stringshare_ref (IME_DEVICE_NAME);
378 e->seatname = eina_stringshare_ref (IME_DEVICE_NAME);
379 e->clas = ECORE_DEVICE_CLASS_KEYBOARD;
380 e->subclas = ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD;
384 ecore_event_add (ECORE_EVENT_DEVICE_ADD, e, _device_info_free, NULL);
386 ecore_event_add (ECORE_EVENT_DEVICE_DEL, e, _device_info_free, NULL);
390 set_input_language (const char *input_lang_str)
393 input_lang = INPUT_LANG_OTHER;
395 for (i = 0; i < (sizeof (__language_infos) / sizeof (__language_infos[0])); i++) {
396 if (strcmp (input_lang_str, __language_infos[i].code) == 0) {
397 input_lang = __language_infos[i].lang;
403 static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
405 autoperiod_allow = vconf_keynode_get_bool (key);
408 static void autocapital_allow_changed_cb (keynode_t *key, void* data)
410 autocap_allow = vconf_keynode_get_bool (key);
413 static void input_language_changed_cb (keynode_t *key, void* data)
415 char *input_lang = vconf_keynode_get_str (key);
417 set_input_language (input_lang);
418 LOGD("input lang : %s", input_lang);
423 check_symbol (Eina_Unicode ucode, Eina_Unicode symbols[], int symbol_num)
426 for (i = 0; i < symbol_num; i++) {
428 if (ucode == symbols[i])
436 check_space_symbol (Eina_Unicode uchar)
438 Eina_Unicode space_symbols[] = {' ', 0x00A0 /* no-break space */, 0x3000 /* ideographic space */};
439 const int symbol_num = sizeof (space_symbols) / sizeof (space_symbols[0]);
441 return check_symbol (uchar, space_symbols, symbol_num);
445 autoperiod_insert (Ecore_IMF_Context *ctx)
447 char *plain_str = NULL;
449 Eina_Unicode *ustr = NULL;
450 Ecore_IMF_Event_Delete_Surrounding ev;
451 char *fullstop_mark = NULL;
454 WaylandIMContext *imcontext = NULL;
456 if (autoperiod_allow == EINA_FALSE)
461 Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
462 if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
465 if ((ecore_time_get () - space_key_time) > DOUBLE_SPACE_INTERVAL)
468 imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
469 if (!imcontext) return;
471 ecore_imf_context_surrounding_get (ctx, &plain_str, NULL);
472 if (!plain_str) goto done;
474 cursor_pos = imcontext->cursor_position;
476 // Convert string from UTF-8 to unicode
477 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
478 if (!ustr) goto done;
480 ulen = eina_unicode_strlen (ustr);
482 if (cursor_pos < 2 || cursor_pos > (int)ulen) {
483 LOGD ("invalid range. cursor pos : %d, length : %zu", cursor_pos, ulen);
487 if (check_space_symbol (ustr[cursor_pos-1])) {
488 // any character (except space & punctuation) + press space key twice in short time
489 if (!(iswpunct (ustr[cursor_pos-2]) || check_space_symbol (ustr[cursor_pos-2])) &&
490 iswprint(ustr[cursor_pos-2])) {
493 // any character (except space & punctuation) + space + press space key twice in short time
494 else if (cursor_pos >= 3 &&
495 check_space_symbol (ustr[cursor_pos-2]) &&
496 !(iswpunct (ustr[cursor_pos-3]) || check_space_symbol (ustr[cursor_pos-3])) &&
497 iswprint(ustr[cursor_pos-3])) {
503 ev.n_chars = del_chars;
504 ev.offset = del_chars * -1;
506 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
508 if (input_lang == INPUT_LANG_OTHER) {
509 fullstop_mark = strdup (".");
512 Eina_Unicode wbuf[2] = {0};
513 wbuf[0] = __language_infos[input_lang].punc_code;
515 fullstop_mark = eina_unicode_unicode_to_utf8 (wbuf, NULL);
518 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)fullstop_mark);
521 free (fullstop_mark);
522 fullstop_mark = NULL;
528 if (plain_str) free (plain_str);
529 if (ustr) free (ustr);
530 space_key_time = ecore_time_get ();
534 check_except_autocapital (Eina_Unicode *ustr, int cursor_pos)
536 const char *except_str[] = {"e.g.", "E.g."};
537 unsigned int i = 0, j = 0, len = 0;
538 for (i = 0; i < (sizeof (except_str) / sizeof (except_str[0])); i++) {
539 len = strlen (except_str[i]);
540 if (cursor_pos < (int)len)
543 for (j = len; j > 0; j--) {
544 if (ustr[cursor_pos-j] != except_str[i][len-j])
548 if (j == 0) return EINA_TRUE;
555 analyze_surrounding_text (Ecore_IMF_Context *ctx)
557 char *plain_str = NULL;
558 Eina_Unicode puncs[] = {'\n','.', '!', '?', 0x00BF /* ¿ */, 0x00A1 /* ¡ */,
559 0x3002 /* 。 */, 0x06D4 /* Urdu */, 0x0964 /* Hindi */,
560 0x0589 /* Armenian */, 0x17D4 /* Khmer */, 0x104A /* Myanmar */};
561 Eina_Unicode *ustr = NULL;
562 Eina_Bool ret = EINA_FALSE;
563 Eina_Bool detect_space = EINA_FALSE;
566 const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
567 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
568 if (!imcontext) return EINA_FALSE;
570 switch (ecore_imf_context_autocapital_type_get (ctx)) {
571 case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
573 case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
579 if (imcontext->preedit_text && strcmp (imcontext->preedit_text, "") != 0)
582 if (imcontext->cursor_position == 0)
585 ecore_imf_context_surrounding_get (ctx, &plain_str, &cursor_pos);
587 if (!plain_str) goto done;
589 if (cursor_pos == 0) {
594 // Convert string from UTF-8 to unicode
595 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
596 if (!ustr) goto done;
598 if (eina_unicode_strlen (ustr) < (size_t)cursor_pos) goto done;
600 if (cursor_pos >= 1) {
601 if (ecore_imf_context_autocapital_type_get (ctx) == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
602 // Check space or no-break space
603 if (check_space_symbol (ustr[cursor_pos-1])) {
609 // Check paragraph separator <PS> or carriage return <br>
610 if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
615 for (i = cursor_pos; i > 0; i--) {
616 // Check space or no-break space
617 if (check_space_symbol (ustr[i-1])) {
618 detect_space = EINA_TRUE;
622 // Check punctuation and following the continuous space(s)
623 if (detect_space && check_symbol (ustr[i-1], puncs, punc_num)) {
624 if (check_except_autocapital (ustr, i))
636 if ((i == 0) && (detect_space == EINA_TRUE)) {
637 // continuous space(s) without any character
644 if (ustr) free (ustr);
645 if (plain_str) free (plain_str);
651 set_autocapital (Ecore_IMF_Context *ctx)
653 Eina_Bool uppercase = EINA_FALSE;
655 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
656 if (!imcontext || !imcontext->text_input || !imcontext->input) return;
658 if (hw_keyboard_mode) return;
660 if (ecore_imf_context_input_panel_layout_get (ctx) != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
663 // Check autocapital type
664 if (ecore_imf_context_input_panel_caps_lock_mode_get (ctx)) {
665 uppercase = EINA_TRUE;
667 if (autocap_allow == EINA_FALSE)
670 uppercase = analyze_surrounding_text (ctx);
673 LOGD ("ctx : %p, auto capital : %d", ctx, uppercase);
674 wl_text_input_set_capital_mode (imcontext->text_input, uppercase);
677 static Ecore_IMF_Context *
680 return (_show_req_ctx ? _show_req_ctx : _focused_ctx);
684 check_hide_key(const char *keyname)
686 if (!keyname) return EINA_FALSE;
688 if (strcmp(keyname, "Escape") == 0 ||
689 strcmp(keyname, BACK_KEY) == 0 ||
690 strcmp(keyname, OLD_BACK_KEY) == 0)
697 _ecore_key_modifiers_to_ecore_imf_locks(unsigned int modifiers)
699 unsigned int locks = 0;
701 if (modifiers & ECORE_EVENT_LOCK_SCROLL)
702 locks |= ECORE_IMF_KEYBOARD_LOCK_SCROLL;
704 if (modifiers & ECORE_EVENT_LOCK_CAPS)
705 locks |= ECORE_IMF_KEYBOARD_LOCK_CAPS;
707 if (modifiers & ECORE_EVENT_LOCK_NUM)
708 locks |= ECORE_IMF_KEYBOARD_LOCK_NUM;
714 _ecore_key_modifiers_to_ecore_imf_modifiers(unsigned int modifiers)
716 unsigned int mask = 0;
718 /**< "Control" is pressed */
719 if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
720 mask |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
722 /**< "Alt" is pressed */
723 if (modifiers & ECORE_EVENT_MODIFIER_ALT)
724 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
726 /**< "Shift" is pressed */
727 if (modifiers & ECORE_EVENT_MODIFIER_SHIFT)
728 mask |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT;
730 /**< "Win" (between "Ctrl" and "Alt") is pressed */
731 if (modifiers & ECORE_EVENT_MODIFIER_WIN)
732 mask |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
734 /**< "AltGr" is pressed */
735 if (modifiers & ECORE_EVENT_MODIFIER_ALTGR)
736 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
742 _ecore_event_to_ecore_imf_key_down_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Down *imf_event)
744 if (!ecore_event || !imf_event)
747 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
748 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
749 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
750 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
751 imf_event->timestamp = ecore_event->timestamp;
753 if (ecore_event->dev) {
754 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
755 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
756 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
759 imf_event->dev_name = _ecore_imf_event_empty;
760 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
761 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
764 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
765 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
769 _ecore_event_to_ecore_imf_key_up_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Up *imf_event)
771 if (!ecore_event || !imf_event)
774 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
775 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
776 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
777 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
778 imf_event->timestamp = ecore_event->timestamp;
780 if (ecore_event->dev) {
781 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
782 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
783 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
786 imf_event->dev_name = _ecore_imf_event_empty;
787 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
788 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
791 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
792 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
795 static Eina_Bool check_nograb_backkey()
797 char *nograb_backkey = getenv ("ISF_KEY_NOGRAB_BACKKEY");
798 if (nograb_backkey) {
799 if (atoi (nograb_backkey) != 0)
800 return EINA_TRUE; /* the event is kept */
807 key_down_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
809 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
810 if (!ev || !ev->keyname) return EINA_TRUE; /* the event is kept */
812 Ecore_IMF_Context *active_ctx = get_using_ctx ();
814 if (!active_ctx) return EINA_TRUE; /* the event is kept */
816 if (check_nograb_backkey()) return EINA_TRUE; /* the event is kept */
818 if ((_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW ||
819 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW) &&
820 check_hide_key(ev->keyname)) {
822 SECURE_LOGD ("%s key is pressed.", ev->keyname);
824 Ecore_IMF_Event_Key_Down imf_event;
825 Eina_Bool filter_ret = EINA_FALSE;
827 _ecore_event_to_ecore_imf_key_down_event(ev, &imf_event);
830 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_DOWN, (Ecore_IMF_Event *)&imf_event);
834 SECURE_LOGD ("%s key is pressed. ret : %d", ev->keyname, filter_ret);
835 return EINA_FALSE; /* the event is removed from the queue */
837 return EINA_TRUE; /* the event is kept */
841 key_up_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
843 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
844 if (!ev || !ev->keyname) return EINA_TRUE; /* the event is kept */
846 Ecore_IMF_Context *active_ctx = get_using_ctx ();
848 if (!active_ctx) return EINA_TRUE; /* the event is kept */
850 if (check_nograb_backkey()) return EINA_TRUE; /* the event is kept */
852 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE ||
853 !check_hide_key(ev->keyname))
854 return EINA_TRUE; /* the event is kept */
856 SECURE_LOGD ("%s key is released.", ev->keyname);
858 Ecore_IMF_Event_Key_Up imf_event;
859 Eina_Bool filter_ret = EINA_FALSE;
861 _ecore_event_to_ecore_imf_key_up_event(ev, &imf_event);
864 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_UP, (Ecore_IMF_Event *)&imf_event);
868 SECURE_LOGD ("%s key is released. ret : %d", ev->keyname, filter_ret);
870 return EINA_FALSE; /* the event is removed from the queue */
873 ecore_imf_context_reset(active_ctx);
874 _input_panel_hide(active_ctx, EINA_TRUE);
875 return EINA_FALSE; /* the event is removed from the queue */
880 rotary_event_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
882 Ecore_Event_Detent_Rotate *ev = event;
883 if (!ev) return EINA_TRUE;
885 Ecore_IMF_Context *active_ctx = NULL;
887 active_ctx = _show_req_ctx;
888 else if (_focused_ctx)
889 active_ctx = _focused_ctx;
891 if (!active_ctx) return EINA_TRUE;
893 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
896 ecore_imf_context_reset(active_ctx);
897 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(active_ctx);
898 if (imcontext && imcontext->input && imcontext->text_input) {
899 isf_device_type_e device_type = find_device_type_from_ecore_event(ECORE_EVENT_DETENT_ROTATE);
903 if (device_buffer_encode((const char*)(event), sizeof(Ecore_Event_Detent_Rotate), &buffer, &buflen) &&
904 buffer && buflen > 0) {
905 wl_text_input_process_input_device_event(imcontext->text_input,
906 (unsigned int)device_type, buffer, buflen);
908 if (buffer) free(buffer);
915 _ecore_event_filter_cb(void *data, void *loop_data EINA_UNUSED, int type, void *event)
917 if (type == ECORE_EVENT_KEY_DOWN) {
918 return key_down_filter_cb(data, type, event);
920 else if (type == ECORE_EVENT_KEY_UP) {
921 return key_up_filter_cb(data, type, event);
923 /* The IME needs to process Rotary event prior to client application */
924 else if (type == ECORE_EVENT_DETENT_ROTATE) {
925 return rotary_event_cb(data, type, event);
932 register_key_handler()
934 if (!_ecore_event_filter_handler)
935 _ecore_event_filter_handler = ecore_event_filter_add(NULL, _ecore_event_filter_cb, NULL, NULL);
939 unregister_key_handler()
941 if (_ecore_event_filter_handler) {
942 ecore_event_filter_del(_ecore_event_filter_handler);
943 _ecore_event_filter_handler = NULL;
954 LOGD("Delete hide timer");
955 ecore_timer_del(_hide_timer);
963 static void _win_focus_out_handler_del ()
965 if (_win_focus_out_handler) {
966 ecore_event_handler_del (_win_focus_out_handler);
967 _win_focus_out_handler = NULL;
971 static void _conformant_change_handler_del()
973 if (_conformant_change_handler) {
974 ecore_event_handler_del(_conformant_change_handler);
975 _conformant_change_handler = NULL;
980 _send_input_panel_hide_request(Ecore_IMF_Context *ctx)
984 // TIZEN_ONLY(20150708): Support back key
985 _hide_req_ctx = NULL;
988 _win_focus_out_handler_del ();
990 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
991 if (imcontext && imcontext->text_input) {
992 LOGD("Send IME hide request");
993 wl_text_input_hide_input_panel(imcontext->text_input);
995 LOGD("creating temporary context for sending hide request");
996 const char *ctx_id = ecore_imf_context_default_id_get();
997 Ecore_IMF_Context *temp_context = ecore_imf_context_add(ctx_id);
999 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(temp_context);
1000 if (imcontext && imcontext->text_input) {
1001 LOGD("Send IME hide request");
1002 wl_text_input_hide_input_panel(imcontext->text_input);
1005 ecore_imf_context_del(temp_context);
1010 static void _conformant_area_free (void *data EINA_UNUSED, void *ev)
1012 Ecore_Wl2_Event_Conformant_Change *e = ev;
1017 static void add_conformant_change_event(Ecore_Wl2_Window *window)
1019 Ecore_Wl2_Event_Conformant_Change *ev;
1020 ev = calloc(1, sizeof(Ecore_Wl2_Event_Conformant_Change));
1022 ev->win = ecore_wl2_window_id_get(window);
1025 ecore_event_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, ev, _conformant_area_free, NULL);
1029 static Eina_Rectangle _conformant_area_backup = { 0, 0, 0, 0 };
1030 static Eina_Bool reset_conformant_area(Ecore_IMF_Context *ctx)
1032 Eina_Bool reset = EINA_FALSE;
1033 Eina_Bool has_conformant = EINA_FALSE;
1034 Ecore_Wl2_Window *window = NULL;
1036 if (!ctx) return EINA_FALSE;
1038 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1040 window = imcontext->window;
1041 has_conformant = imcontext->has_conformant;
1045 int x = 0, y = 0, w = 0, h = 0;
1046 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1049 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w != 0 || h != 0)) {
1051 _conformant_area_backup.x = x;
1052 _conformant_area_backup.y = y;
1053 _conformant_area_backup.w = w;
1054 _conformant_area_backup.h = h;
1058 LOGD("reset %d", reset);
1060 ecore_wl2_window_keyboard_geometry_set(window, 0, 0, 0, 0);
1062 add_conformant_change_event(window);
1064 _conformant_reset_started = EINA_TRUE;
1070 static void restore_conformant_area(Ecore_IMF_Context *ctx)
1072 Eina_Bool restore = EINA_FALSE;
1073 Eina_Bool has_conformant = EINA_FALSE;
1074 Ecore_Wl2_Window *window = NULL;
1078 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1080 window = imcontext->window;
1081 has_conformant = imcontext->has_conformant;
1085 int x = 0, y = 0, w = 0, h = 0;
1086 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1089 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w == 0 || h == 0)) {
1090 restore = EINA_TRUE;
1094 LOGD("restore %d", restore);
1096 ecore_wl2_window_keyboard_geometry_set(window,
1097 _conformant_area_backup.x, _conformant_area_backup.y,
1098 _conformant_area_backup.w, _conformant_area_backup.h);
1100 add_conformant_change_event(window);
1102 _conformant_reset_started = EINA_FALSE;
1107 _send_will_hide_ack(WaylandIMContext *imcontext)
1109 if (!imcontext) return;
1110 if (!(imcontext->text_input)) return;
1112 const char *szWillHideAck = "WILL_HIDE_ACK";
1113 wl_text_input_set_input_panel_data(imcontext->text_input, szWillHideAck, strlen(szWillHideAck));
1114 _received_will_hide_event = EINA_FALSE;
1118 _hide_timer_handler(void *data)
1120 LOGD("Start hide timer");
1121 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1122 _send_input_panel_hide_request(ctx);
1124 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1125 LOGD("No need to reset conformant, sending ACK right away");
1126 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1130 reset_keyboard_geometry();
1133 return ECORE_CALLBACK_CANCEL;
1137 _input_panel_hide_timer_start(void *data)
1140 LOGD("Add timer to hide input panel");
1141 _hide_timer = ecore_timer_add(HIDE_TIMER_INTERVAL, _hide_timer_handler, data);
1146 _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant)
1148 LOGD ("ctx : %p", ctx);
1152 will_hide = EINA_TRUE;
1153 _conformant_reset_started = EINA_FALSE;
1155 if (instant || (_hide_timer && ecore_timer_pending_get(_hide_timer) <= 0.0)) {
1156 _clear_hide_timer();
1157 _send_input_panel_hide_request(ctx);
1159 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1160 LOGD("No need to reset conformant, sending ACK right away");
1161 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1165 reset_keyboard_geometry();
1167 _input_panel_hide_timer_start(ctx);
1168 // TIZEN_ONLY(20150708): Support back key
1169 _hide_req_ctx = ctx;
1175 utf8_offset_to_characters(const char *str, int offset)
1180 for (; index < offset; i++) {
1181 if (eina_unicode_utf8_next_get(str, &index) == 0)
1189 send_cursor_location(WaylandIMContext *imcontext)
1191 #if ENABLE_SEND_CURSOR_LOCATION
1192 Ecore_Evas *ee = NULL;
1193 int canvas_x = 0, canvas_y = 0;
1195 if (imcontext->canvas) {
1196 ee = ecore_evas_ecore_evas_get(imcontext->canvas);
1198 ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
1201 if (imcontext->input && imcontext->text_input) {
1202 wl_text_input_set_cursor_rectangle(imcontext->text_input,
1203 imcontext->cursor_location.x + canvas_x,
1204 imcontext->cursor_location.y + canvas_y,
1205 imcontext->cursor_location.width,
1206 imcontext->cursor_location.height);
1212 update_state(WaylandIMContext *imcontext)
1214 if (!imcontext->ctx)
1217 send_cursor_location (imcontext);
1219 if (imcontext->input && imcontext->text_input) {
1220 wl_text_input_commit_state(imcontext->text_input, ++imcontext->serial);
1225 check_serial(WaylandIMContext *imcontext, uint32_t serial)
1230 Ecore_IMF_Preedit_Attr *attr;
1232 if ((imcontext->serial - serial) >
1233 (imcontext->serial - imcontext->reset_serial)) {
1234 LOGD("outdated serial: %u, current: %u, reset: %u",
1235 serial, imcontext->serial, imcontext->reset_serial);
1237 imcontext->pending_preedit.cursor = 0;
1239 if (imcontext->pending_preedit.attrs) {
1240 EINA_LIST_FREE(imcontext->pending_preedit.attrs, attr) {
1244 imcontext->pending_preedit.attrs = NULL;
1255 clear_preedit_text(WaylandIMContext *imcontext)
1257 Ecore_IMF_Preedit_Attr *attr = NULL;
1259 imcontext->preedit_cursor = 0;
1261 if (imcontext->preedit_text) {
1262 free(imcontext->preedit_text);
1263 imcontext->preedit_text = NULL;
1266 if (imcontext->preedit_attrs) {
1267 EINA_LIST_FREE(imcontext->preedit_attrs, attr) {
1273 imcontext->preedit_attrs = NULL;
1277 clear_preedit(WaylandIMContext *imcontext)
1279 clear_preedit_text(imcontext);
1281 if (imcontext->preedit_commit) {
1282 free(imcontext->preedit_commit);
1283 imcontext->preedit_commit = NULL;
1288 text_input_commit_string(void *data,
1289 struct wl_text_input *text_input EINA_UNUSED,
1293 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1294 Eina_Bool old_preedit = EINA_FALSE;
1296 SECURE_LOGD("ctx : %p, commit event (text: '%s', current pre-edit: '%s')",
1299 imcontext->preedit_text ? imcontext->preedit_text : "");
1301 if (!imcontext->ctx)
1305 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1307 if (!check_serial(imcontext, serial))
1311 ecore_imf_context_event_callback_call(imcontext->ctx,
1312 ECORE_IMF_CALLBACK_PREEDIT_END,
1316 clear_preedit(imcontext);
1321 Eina_Unicode *ustr = eina_unicode_utf8_to_unicode (text, NULL);
1324 if (eina_unicode_strcmp (ustr, L" ") == 0 ||
1325 eina_unicode_strcmp (ustr, L" ") == 0)
1326 autoperiod_insert (imcontext->ctx);
1331 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)text);
1335 commit_preedit(WaylandIMContext *imcontext)
1337 if (!imcontext->preedit_commit)
1340 if (!imcontext->ctx)
1343 imcontext->pending_preedit.cursor = 0;
1344 clear_preedit_text(imcontext);
1346 size_t commit_len = strlen(imcontext->preedit_commit);
1348 if (commit_len == 0) {
1349 ecore_imf_context_event_callback_call(imcontext->ctx,
1350 ECORE_IMF_CALLBACK_PREEDIT_START,
1353 ecore_imf_context_event_callback_call(imcontext->ctx,
1354 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1357 ecore_imf_context_event_callback_call(imcontext->ctx,
1358 ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
1361 if (commit_len > 0) {
1362 char *commit_str = NULL;
1363 commit_str = strdup(imcontext->preedit_commit);
1364 clear_preedit(imcontext);
1365 ecore_imf_context_event_callback_call(imcontext->ctx,
1366 ECORE_IMF_CALLBACK_COMMIT,
1367 (void *)commit_str);
1373 set_focus(Ecore_IMF_Context *ctx)
1375 LOGD("ctx : %p", ctx);
1376 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1377 if (!imcontext) return EINA_FALSE;
1379 if (!imcontext->window) {
1380 LOGW("window is not given");
1384 Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
1386 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1390 struct wl_seat *seat = ecore_wl2_input_seat_get(input);
1392 LOGW("ctx : %p, Can't get Wl_seat", ctx);
1396 imcontext->input = input;
1399 wl_text_input_activate(imcontext->text_input, seat,
1400 ecore_wl2_window_surface_get(imcontext->window));
1402 if (g_key_rate_checked == EINA_FALSE && g_desired_key_rate == 0.0) {
1403 char *key_rate = getenv ("ISF_KEY_REPEAT_RATE");
1405 g_desired_key_rate = atof (key_rate);
1406 if (g_desired_key_rate > 0.0) {
1407 if (!ecore_wl2_input_keyboard_repeat_get (input, &g_original_key_rate, &g_original_key_delay)) {
1408 LOGE ("ecore_wl2_input_keyboard_repeat_get failed");
1411 LOGD ("ecore_wl2_input_keyboard_repeat_get original rate=%f, delay=%f. Desired rate=%f",
1412 g_original_key_rate, g_original_key_delay, g_desired_key_rate);
1416 g_key_rate_checked = EINA_TRUE;
1419 if (g_desired_key_rate > 0.0 && g_original_key_delay > 0.0 && !g_focused) {
1420 g_focused = EINA_TRUE;
1421 if (!ecore_wl2_input_keyboard_repeat_set (input, g_desired_key_rate, g_original_key_delay)) {
1422 LOGE ("ecore_wl2_input_keyboard_repeat_set failed");
1425 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_desired_key_rate, g_original_key_delay);
1433 set_focus_out(Ecore_IMF_Context *ctx)
1435 char *surrounding = NULL;
1438 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1439 if (!imcontext || !imcontext->input) return;
1441 if (ecore_imf_context_surrounding_get(ctx, &surrounding, &cursor_pos)) {
1443 wl_text_input_finalize_content(imcontext->text_input, surrounding, cursor_pos);
1449 if (imcontext->text_input)
1450 wl_text_input_deactivate(imcontext->text_input,
1451 ecore_wl2_input_seat_get(imcontext->input));
1453 if (ctx == _focused_ctx)
1454 _focused_ctx = NULL;
1456 imcontext->input = NULL;
1457 _preedit_cursor_changed = EINA_FALSE;
1459 if (g_desired_key_rate > 0.0 && g_focused) {
1460 g_focused = EINA_FALSE;
1462 Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
1464 if (!ecore_wl2_input_keyboard_repeat_set (input, g_original_key_rate, g_original_key_delay)) {
1465 LOGE ("ecore_wl2_input_keyboard_repeat_set failed.");
1468 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_original_key_rate, g_original_key_delay);
1472 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1477 // TIZEN_ONLY(20160217): ignore the duplicate show request
1478 static Eina_Bool _compare_context(Ecore_IMF_Context *ctx1, Ecore_IMF_Context *ctx2)
1480 if (!ctx1 || !ctx2) return EINA_FALSE;
1482 if ((ecore_imf_context_autocapital_type_get(ctx1) == ecore_imf_context_autocapital_type_get(ctx2)) &&
1483 (ecore_imf_context_input_panel_layout_get(ctx1) == ecore_imf_context_input_panel_layout_get(ctx2)) &&
1484 (ecore_imf_context_input_panel_layout_variation_get(ctx1) == ecore_imf_context_input_panel_layout_variation_get(ctx2)) &&
1485 (ecore_imf_context_input_panel_language_get(ctx1) == ecore_imf_context_input_panel_language_get(ctx2)) &&
1486 (ecore_imf_context_input_panel_return_key_type_get(ctx1) == ecore_imf_context_input_panel_return_key_type_get(ctx2)) &&
1487 (ecore_imf_context_input_panel_return_key_disabled_get(ctx1) == ecore_imf_context_input_panel_return_key_disabled_get(ctx2)) &&
1488 (ecore_imf_context_input_panel_caps_lock_mode_get(ctx1) == ecore_imf_context_input_panel_caps_lock_mode_get(ctx2)))
1495 static void send_get_hide_permission(WaylandIMContext *imcontext)
1497 if (imcontext->text_input) {
1498 ignore_hide = EINA_FALSE;
1499 wl_text_input_get_hide_permission(imcontext->text_input);
1503 static Eina_Bool _client_window_focus_out_cb(void *data, int ev_type, void *ev)
1505 Ecore_Wl2_Event_Focus_Out *e = (Ecore_Wl2_Event_Focus_Out *)ev;
1506 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1507 if (!ctx || !e) return ECORE_CALLBACK_PASS_ON;
1509 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
1510 if (!imcontext || !imcontext->window) return ECORE_CALLBACK_PASS_ON;
1512 unsigned int client_win_id = ecore_wl2_window_id_get (imcontext->window);
1514 LOGD ("ctx : %p, client_window id : %#x, focus-out win : %#x", ctx, client_win_id, e->window);
1516 if (client_win_id > 0) {
1517 if (e->window == client_win_id) {
1518 LOGD ("window focus out");
1520 if (_focused_ctx == ctx) {
1521 wayland_im_context_focus_out (ctx);
1524 if (_show_req_ctx == ctx) {
1525 send_get_hide_permission(imcontext);
1530 send_get_hide_permission(imcontext);
1533 return ECORE_CALLBACK_PASS_ON;
1536 static void send_will_hide_ack(Ecore_IMF_Context *ctx)
1538 Eina_Bool need_temporary_context = EINA_FALSE;
1539 Eina_Bool has_conformant = EINA_FALSE;
1540 WaylandIMContext *imcontext = NULL;
1543 LOGD("ctx is NULL");
1544 need_temporary_context = EINA_TRUE;
1546 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1548 LOGD("imcontext is NULL :%p", ctx);
1549 need_temporary_context = EINA_TRUE;
1551 has_conformant = imcontext->has_conformant;
1555 /* When the RENDER_POST event is emitted, it is possible that our IMF_Context is already deleted,
1556 meaning that there is no connection available for communicating with the window manager.
1557 So we are creating a temporary context for sending WILL_HIDE_ACK message */
1558 if (need_temporary_context) {
1559 LOGD("creating temporary context for sending WILL_HIDE_ACK");
1560 const char *ctx_id = ecore_imf_context_default_id_get();
1561 ctx = ecore_imf_context_add(ctx_id);
1563 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1567 if (ctx && imcontext) {
1568 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant) {
1569 if (_conformant_reset_done && _received_will_hide_event) {
1570 LOGD("Send will hide ack, _conformant_reset_done = 1, received_will_hide_event = 1");
1571 _send_will_hide_ack(imcontext);
1572 _conformant_reset_done = EINA_FALSE;
1573 _received_will_hide_event = EINA_FALSE;
1575 LOGD ("_conformant_reset_done=%d, received_will_hide_event=%d",
1576 _conformant_reset_done, _received_will_hide_event);
1579 LOGD("Send will hide ack right away, since there is no conformant available : %p %d",
1580 ecore_imf_context_client_canvas_get(ctx), has_conformant);
1581 _send_will_hide_ack (imcontext);
1585 if (need_temporary_context) {
1587 ecore_imf_context_del(ctx);
1592 static void _render_post_cb(void *data, Evas *e, void *event_info)
1594 void *callback = evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1595 _conformant_reset_done = EINA_TRUE;
1596 _conformant_reset_started = EINA_FALSE;
1597 LOGD("[_render_post_cb], _conformant_reset_done = 1 , %p", callback);
1598 send_will_hide_ack(NULL);
1601 static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
1603 Ecore_Wl2_Event_Conformant_Change *e = (Ecore_Wl2_Event_Conformant_Change *)ev;
1604 if (!e) return ECORE_CALLBACK_PASS_ON;
1606 LOGD ("CONFORMANT changed!! part type : %d, state : %d, win : %d", e->part_type, e->state, e->win);
1608 if (_active_context_window_id != e->win)
1609 return ECORE_CALLBACK_PASS_ON;
1611 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1612 if (!wl2_display) return ECORE_CALLBACK_PASS_ON;
1614 Ecore_Wl2_Window *window = ecore_wl2_display_window_find(wl2_display, e->win);
1615 if (!window) return ECORE_CALLBACK_PASS_ON;
1618 LOGD("_conformant_reset_done = 0, registering _render_post_cb : %p %p", _active_context_canvas, window);
1619 _conformant_reset_done = EINA_FALSE;
1620 if (_active_context_canvas && ecore_wl2_window_conformant_get(window) && !_custom_conformant_event) {
1621 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1622 evas_event_callback_add(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb, NULL);
1625 _conformant_reset_done = EINA_FALSE;
1626 if (_active_context_canvas) {
1627 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1630 Eina_Bool result = EINA_FALSE;
1631 int x = 0, y = 0, w = 0, h = 0;
1634 /* TV IME consists of two or three windows, so ecore_wl2_window_keyboard_geometry_get() may return wrong size. */
1635 x = _keyboard_geometry.x, y = _keyboard_geometry.y, w = _keyboard_geometry.w, h = _keyboard_geometry.h;
1636 if (_keyboard_geometry.w == 0 || _keyboard_geometry.h == 0) {
1637 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1640 /* Since the input_panel_geometry is not delivered right at the moment, we use conformant geometry instead */
1641 x = 0, y = 0, w = 0, h = 0;
1642 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1646 Evas_Coord scr_w = 0, scr_h = 0;
1648 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1650 ecore_wl2_display_screen_size_get(wl2_display ,&scr_w, &scr_h);
1651 int rot = ecore_wl2_window_rotation_get(window);
1652 /* Assume we are using keyboard that has the same width to the screen width*/
1655 _keyboard_geometry.h = w;
1656 _keyboard_geometry.w = h;
1657 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1658 _keyboard_geometry.x = 0;
1661 _keyboard_geometry.w = w;
1662 _keyboard_geometry.h = h;
1663 _keyboard_geometry.x = 0;
1664 _keyboard_geometry.y = scr_h - _keyboard_geometry.h;
1667 _keyboard_geometry.h = w;
1668 _keyboard_geometry.w = h;
1669 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1670 _keyboard_geometry.x = 0;
1673 _keyboard_geometry.x = x;
1674 _keyboard_geometry.y = y;
1675 _keyboard_geometry.w = w;
1676 _keyboard_geometry.h = h;
1678 LOGD("[KEYPAD]: scr %dx%d, rot %d, orig (%d,%d, %dx%d)", scr_w, scr_h, rot, x, y, w, h);
1679 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
1682 ecore_imf_context_input_panel_event_callback_call(_show_req_ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
1686 return ECORE_CALLBACK_PASS_ON;
1690 get_purpose(Ecore_IMF_Context *ctx)
1692 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1693 uint32_t new_purpose = 0;
1695 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1699 switch (imcontext->content_purpose) {
1700 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
1701 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED)
1702 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED;
1703 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL)
1704 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL;
1705 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL)
1706 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL;
1708 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
1710 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
1711 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY)
1712 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS;
1714 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
1716 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
1717 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME)
1718 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME;
1719 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME)
1720 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NAME;
1722 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
1725 new_purpose = imcontext->content_purpose;
1732 static void _canvas_focus_in_cb(void *data, Evas *e, void *event_info)
1734 LOGD("ctx : %p %d", _focus_req_ctx, _focus_req_only);
1736 if (_focus_req_ctx) {
1737 set_focus(_focus_req_ctx);
1738 if (ecore_imf_context_input_panel_enabled_get (_focus_req_ctx) || !_focus_req_only)
1739 if (!ecore_imf_context_input_panel_show_on_demand_get (_focus_req_ctx) || !_focus_req_only)
1740 show_input_panel (_focus_req_ctx);
1742 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(_focus_req_ctx);
1743 if (imcontext && imcontext->canvas)
1744 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1745 _focus_req_ctx = NULL;
1746 _focus_req_only = EINA_TRUE;
1751 show_input_panel(Ecore_IMF_Context *ctx)
1753 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1755 char *surrounding = NULL;
1758 if ((!imcontext) || (!imcontext->text_input))
1761 if (!imcontext->input) {
1763 if (!imcontext->input) {
1764 _focus_req_ctx = ctx;
1765 _focus_req_only = EINA_FALSE;
1766 if (imcontext->canvas) {
1767 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1768 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
1773 _clear_hide_timer ();
1775 _win_focus_out_handler_del ();
1777 if (!imcontext->input)
1780 ignore_hide = EINA_TRUE;
1782 _win_focus_out_handler = ecore_event_handler_add (ECORE_WL2_EVENT_FOCUS_OUT, _client_window_focus_out_cb, ctx);
1783 _conformant_change_handler_del ();
1784 _conformant_change_handler = ecore_event_handler_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, _conformant_change_cb, NULL);
1786 // TIZEN_ONLY(20160217): ignore the duplicate show request
1787 if ((_show_req_ctx == ctx) && _compare_context(_show_req_ctx, ctx) && (!will_hide)) {
1788 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW ||
1789 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
1790 LOGD("already show. ctx : %p", ctx);
1796 will_hide = EINA_FALSE;
1797 _show_req_ctx = ctx;
1798 _input_panel_ctx = ctx;
1799 _active_context_canvas = ecore_imf_context_client_canvas_get(ctx);
1803 // TIZEN_ONLY(20150715): Support input_panel_state_get
1804 int layout = ecore_imf_context_input_panel_layout_get (ctx);
1805 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1808 if (layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
1809 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
1811 wl_text_input_set_content_type(imcontext->text_input,
1812 imcontext->content_hint,
1815 if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos)) {
1816 SECURE_LOGD ("surrounding text : %s", surrounding);
1820 imcontext->cursor_position = cursor_pos;
1821 wl_text_input_set_cursor_position(imcontext->text_input, cursor_pos);
1823 // TIZEN_ONLY(20150716): Support return key type
1824 wl_text_input_set_return_key_type(imcontext->text_input,
1825 imcontext->return_key_type);
1827 wl_text_input_set_return_key_disabled(imcontext->text_input,
1828 imcontext->return_key_disabled);
1830 if (imcontext->imdata_size > 0)
1831 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
1833 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
1835 set_autocapital (ctx);
1837 if (imcontext->mime_type)
1838 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
1840 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
1841 wl_text_input_set_input_panel_position(imcontext->text_input,
1842 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
1844 LOGD ("ctx : %p, layout : %d, layout variation : %d, language : %d, cursor position : %d",
1845 ctx, layout, layout_variation,
1846 ecore_imf_context_input_panel_language_get (ctx),
1848 LOGD ("input hint : %#x, bidi direction : %d, return key type : %d, return key disabled : %d, autocapital type : %d",
1849 ecore_imf_context_input_hint_get (ctx),
1850 imcontext->bidi_direction,
1851 ecore_imf_context_input_panel_return_key_type_get (ctx),
1852 ecore_imf_context_input_panel_return_key_disabled_get (ctx),
1853 ecore_imf_context_autocapital_type_get (ctx));
1854 LOGD ("client_window : %#lx, password mode : %d, prediction_allow : %d, mime_type : %s, input panel position x : %d, y : %d",
1855 (unsigned long int)ecore_imf_context_client_window_get (ctx),
1856 (imcontext->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) ? 1 : 0,
1857 ecore_imf_context_prediction_allow_get (ctx),
1858 imcontext->mime_type,
1859 imcontext->input_panel_position.x,
1860 imcontext->input_panel_position.y);
1862 if (_active_context_canvas && !evas_focus_state_get (_active_context_canvas)) {
1863 LOGW ("Canvas does not have focus!");
1867 if (hw_keyboard_mode) {
1868 LOGD("hw_keyboard_mode is TRUE, returning");
1872 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
1874 wl_text_input_show_input_panel(imcontext->text_input);
1876 if (imcontext->window) {
1877 _active_context_window_id = ecore_wl2_window_id_get(imcontext->window);
1878 imcontext->has_conformant = ecore_wl2_window_conformant_get(imcontext->window);
1880 imcontext->has_conformant = EINA_FALSE;
1886 static void delete_surrounding_text(WaylandIMContext *imcontext, int index, int length)
1888 Ecore_IMF_Event_Delete_Surrounding ev;
1889 LOGD("delete surrounding text (index: %d, length: %u)",
1893 ev.n_chars = length;
1895 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
1899 text_input_preedit_string(void *data,
1900 struct wl_text_input *text_input EINA_UNUSED,
1905 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1906 Eina_Bool old_preedit = EINA_FALSE;
1907 Eina_Bool preedit_changed = EINA_FALSE;
1909 SECURE_LOGD("ctx : %p, preedit event (text: '%s', current pre-edit: '%s')",
1912 imcontext->preedit_text ? imcontext->preedit_text : "");
1914 if (!check_serial(imcontext, serial))
1918 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1920 if (imcontext->preedit_text)
1921 preedit_changed = (strcmp(imcontext->preedit_text, text) != 0);
1923 preedit_changed = (strlen(text) != 0);
1925 if (_preedit_cursor_changed) {
1926 preedit_changed = EINA_TRUE;
1927 _preedit_cursor_changed = EINA_FALSE;
1930 if (imcontext->pending_preedit.attrs)
1931 preedit_changed = EINA_TRUE;
1933 clear_preedit(imcontext);
1935 imcontext->preedit_text = strdup(text);
1936 imcontext->preedit_commit = (strlen(text) > 0 ? strdup(commit) : NULL);
1937 imcontext->preedit_cursor =
1938 utf8_offset_to_characters(text, imcontext->pending_preedit.cursor);
1939 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
1941 imcontext->pending_preedit.attrs = NULL;
1943 if (preedit_changed) {
1945 ecore_imf_context_event_callback_call(imcontext->ctx,
1946 ECORE_IMF_CALLBACK_PREEDIT_START,
1950 ecore_imf_context_event_callback_call(imcontext->ctx,
1951 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1954 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
1955 ecore_imf_context_event_callback_call(imcontext->ctx,
1956 ECORE_IMF_CALLBACK_PREEDIT_END,
1963 text_input_delete_surrounding_text(void *data,
1964 struct wl_text_input *text_input EINA_UNUSED,
1968 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1969 delete_surrounding_text(imcontext, index, length);
1973 text_input_cursor_position(void *data EINA_UNUSED,
1974 struct wl_text_input *text_input EINA_UNUSED,
1978 LOGD("cursor_position for next commit (index: %d, anchor: %d)",
1983 text_input_preedit_styling(void *data,
1984 struct wl_text_input *text_input EINA_UNUSED,
1989 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1990 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
1995 case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
1996 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_NONE;
1998 case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
1999 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
2001 case WL_TEXT_INPUT_PREEDIT_STYLE_REVERSE:
2002 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
2004 case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
2005 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
2007 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR1:
2008 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
2010 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR2:
2011 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
2013 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR3:
2014 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
2016 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR4:
2017 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
2020 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
2024 attr->start_index = index;
2025 attr->end_index = index + length;
2027 imcontext->pending_preedit.attrs =
2028 eina_list_append(imcontext->pending_preedit.attrs, attr);
2032 text_input_preedit_cursor(void *data,
2033 struct wl_text_input *text_input EINA_UNUSED,
2036 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2038 LOGD("preedit cursor : %d", index);
2040 if (imcontext->pending_preedit.cursor != index) {
2041 imcontext->pending_preedit.cursor = index;
2042 _preedit_cursor_changed = EINA_TRUE;
2046 static xkb_mod_index_t
2047 modifiers_get_index(struct wl_array *modifiers_map, const char *name)
2049 xkb_mod_index_t index = 0;
2050 char *p = modifiers_map->data;
2052 while ((const char *)p < ((const char *)modifiers_map->data + modifiers_map->size))
2054 if (strcmp(p, name) == 0)
2061 return XKB_MOD_INVALID;
2064 static xkb_mod_mask_t
2065 modifiers_get_mask(struct wl_array *modifiers_map,
2068 xkb_mod_index_t index = modifiers_get_index(modifiers_map, name);
2070 if (index == XKB_MOD_INVALID)
2071 return XKB_MOD_INVALID;
2077 text_input_modifiers_map(void *data,
2078 struct wl_text_input *text_input EINA_UNUSED,
2079 struct wl_array *map)
2081 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2082 imcontext->shift_mask = modifiers_get_mask(map, XKB_MOD_NAME_SHIFT);
2083 imcontext->control_mask = modifiers_get_mask(map, XKB_MOD_NAME_CTRL);
2084 imcontext->alt_mask = modifiers_get_mask(map, XKB_MOD_NAME_ALT);
2085 imcontext->caps_mask = modifiers_get_mask(map, XKB_MOD_NAME_CAPS);
2086 imcontext->num_mask = modifiers_get_mask(map, XKB_MOD_NAME_NUM);
2090 _ecore_keyevent_free (void *data EINA_UNUSED, void *ev)
2092 Ecore_Event_Key *e = ev;
2093 if (e->dev) ecore_device_unref(e->dev);
2099 text_input_keysym(void *data,
2100 struct wl_text_input *text_input EINA_UNUSED,
2101 uint32_t serial EINA_UNUSED,
2107 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2108 char string[32], key[32], keyname[32];
2111 memset(key, 0, sizeof(key));
2112 xkb_keysym_get_name(sym, key, sizeof(key));
2114 memset(keyname, 0, sizeof(keyname));
2115 xkb_keysym_get_name(sym, keyname, sizeof(keyname));
2116 if (keyname[0] == '\0')
2117 snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
2119 memset(string, 0, sizeof(string));
2120 xkb_keysym_to_utf8(sym, string, 32);
2122 SECURE_LOGD("key event (key: %s)", keyname);
2124 e = calloc(1, sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) +
2125 strlen(string) + 3);
2128 e->keyname = (char *)(e + 1);
2129 e->key = e->keyname + strlen(keyname) + 1;
2130 e->string = e->key + strlen(key) + 1;
2131 e->compose = e->string;
2133 strncpy((char *)e->keyname, keyname, strlen(keyname));
2134 strncpy((char *)e->key, key, strlen(key));
2135 strncpy((char *)e->string, string, strlen(string));
2137 e->window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2138 e->event_window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2139 e->dev = ecore_device_ref(_ime_device);
2140 e->timestamp = 0; /* For distinguishing S/W keyboard event */
2143 if (modifiers & imcontext->shift_mask)
2144 e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
2146 if (modifiers & imcontext->control_mask)
2147 e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
2149 if (modifiers & imcontext->alt_mask)
2150 e->modifiers |= ECORE_EVENT_MODIFIER_ALT;
2152 if (modifiers & MOD_Mod5_MASK)
2153 e->modifiers |= MOD_Mod5_MASK;
2155 if (modifiers & imcontext->caps_mask)
2156 e->modifiers |= ECORE_EVENT_LOCK_CAPS;
2158 if (modifiers & imcontext->num_mask)
2159 e->modifiers |= ECORE_EVENT_LOCK_NUM;
2161 //Save "wl_text_input::keysym" keysym to list if list is not empty,
2162 //if not, send keysym to ecore loop as key event.
2163 //This code let key event which will be filtered by IME one by one.
2164 if (eina_list_count(imcontext->keysym_list)) {
2165 e->data = (void *)(unsigned long int)(state ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP);
2166 imcontext->keysym_list = eina_list_prepend(imcontext->keysym_list, e);
2170 ecore_event_add(ECORE_EVENT_KEY_DOWN, e, _ecore_keyevent_free, NULL);
2172 ecore_event_add(ECORE_EVENT_KEY_UP, e, _ecore_keyevent_free, NULL);
2177 text_input_enter(void *data,
2178 struct wl_text_input *text_input EINA_UNUSED,
2179 struct wl_surface *surface EINA_UNUSED)
2181 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2183 update_state(imcontext);
2185 imcontext->reset_serial = imcontext->serial;
2189 text_input_leave(void *data,
2190 struct wl_text_input *text_input EINA_UNUSED)
2192 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2195 commit_preedit(imcontext);
2196 clear_preedit(imcontext);
2200 text_input_input_panel_state(void *data EINA_UNUSED,
2201 struct wl_text_input *text_input EINA_UNUSED,
2202 uint32_t state EINA_UNUSED)
2204 // TIZEN_ONLY(20150708): Support input panel state callback
2205 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2206 LOGD("input panel state: %d", state);
2208 case WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE:
2209 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2210 if (imcontext->ctx == _show_req_ctx)
2211 _show_req_ctx = NULL;
2213 will_hide = EINA_FALSE;
2215 _received_will_hide_event = EINA_TRUE;
2216 LOGD("_received_will_hide_event = 1");
2217 send_will_hide_ack(imcontext->ctx);
2219 case WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW:
2220 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
2221 _received_will_hide_event = EINA_FALSE;
2223 _show_req_ctx = imcontext->ctx;
2224 LOGD("_received_will_hide_event = 0");
2227 _input_panel_state = (Ecore_IMF_Input_Panel_State)state;
2231 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx,
2232 ECORE_IMF_INPUT_PANEL_STATE_EVENT,
2233 _input_panel_state);
2235 if (state == WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE) {
2236 reset_keyboard_geometry();
2237 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2238 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2243 // TIZEN_ONLY(20151221): Support input panel geometry
2245 text_input_input_panel_geometry(void *data EINA_UNUSED,
2246 struct wl_text_input *text_input EINA_UNUSED,
2252 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2254 if (_keyboard_geometry.x != (int)x || _keyboard_geometry.y != (int)y ||
2255 _keyboard_geometry.w != (int)w || _keyboard_geometry.h != (int)h)
2257 _keyboard_geometry.x = x;
2258 _keyboard_geometry.y = y;
2259 _keyboard_geometry.w = w;
2260 _keyboard_geometry.h = h;
2261 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2262 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2268 text_input_language(void *data,
2269 struct wl_text_input *text_input EINA_UNUSED,
2270 uint32_t serial EINA_UNUSED,
2271 const char *language)
2273 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2274 Eina_Bool changed = EINA_FALSE;
2276 if (!imcontext || !language) return;
2278 if (imcontext->language) {
2279 if (strcmp(imcontext->language, language) != 0) {
2280 changed = EINA_TRUE;
2281 free(imcontext->language);
2285 changed = EINA_TRUE;
2289 imcontext->language = strdup(language);
2292 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, 0);
2297 text_input_text_direction(void *data EINA_UNUSED,
2298 struct wl_text_input *text_input EINA_UNUSED,
2299 uint32_t serial EINA_UNUSED,
2300 uint32_t direction EINA_UNUSED)
2304 // TIZEN_ONLY(20150918): Support to set the selection region
2306 text_input_selection_region(void *data,
2307 struct wl_text_input *text_input EINA_UNUSED,
2308 uint32_t serial EINA_UNUSED,
2312 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2313 if (!imcontext || !imcontext->ctx) return;
2315 Ecore_IMF_Event_Selection ev;
2316 ev.ctx = imcontext->ctx;
2319 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_SELECTION_SET, &ev);
2323 text_input_private_command(void *data,
2324 struct wl_text_input *text_input EINA_UNUSED,
2325 uint32_t serial EINA_UNUSED,
2326 const char *command)
2328 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2329 if (!imcontext || !imcontext->ctx) return;
2331 const char *szConformantReset = "CONFORMANT_RESET";
2332 const char *szConformantRestore = "CONFORMANT_RESTORE";
2333 LOGD("Checking command : %s", command);
2335 if (strncmp(command, szConformantReset, strlen(szConformantReset)) == 0) {
2336 Ecore_Wl2_Window *window = imcontext->window;
2337 if (!window) return;
2339 if (!reset_conformant_area(imcontext->ctx) && !_conformant_reset_started) {
2340 LOGD("Could not reset conformant area, send will_hide_ack right away %d", _conformant_reset_started);
2341 _send_will_hide_ack(imcontext);
2342 } else if (_conformant_reset_done) {
2343 LOGD("Conformant reset has been already finished, send will_hide_ack right away");
2344 _send_will_hide_ack(imcontext);
2346 } else if (strncmp(command, szConformantRestore, strlen(szConformantRestore)) == 0) {
2347 Ecore_Wl2_Window *window = imcontext->window;
2348 if (!window) return;
2350 restore_conformant_area(imcontext->ctx);
2352 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)command);
2357 text_input_commit_content(void *data,
2358 struct wl_text_input *text_input EINA_UNUSED,
2359 uint32_t serial EINA_UNUSED,
2360 const char *content,
2361 const char *description,
2362 const char *mime_types)
2364 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2365 if (!imcontext || !imcontext->ctx) return;
2367 Ecore_IMF_Event_Commit_Content ev;
2368 ev.content_uri = content;
2369 ev.mime_types = mime_types;
2370 ev.description = description;
2372 SECURE_LOGD("commit content : %s, description : %s, mime types : %s", content, description, mime_types);
2374 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT_CONTENT, (void *)&ev);
2378 text_input_input_panel_data(void *data,
2379 struct wl_text_input *text_input EINA_UNUSED,
2380 uint32_t serial EINA_UNUSED,
2381 const char *input_panel_data,
2384 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2385 if (!imcontext || !imcontext->ctx) return;
2387 if (imcontext->input_panel_data)
2388 free (imcontext->input_panel_data);
2390 imcontext->input_panel_data = calloc (1, length);
2391 if (imcontext->input_panel_data)
2392 memcpy (imcontext->input_panel_data, input_panel_data, length);
2394 imcontext->input_panel_data_length = length;
2398 text_input_get_selection_text (void *data,
2399 struct wl_text_input *text_input EINA_UNUSED,
2402 char *selection = NULL;
2404 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2405 if (!imcontext || !imcontext->ctx) {
2406 LOGD ("No context!");
2411 ecore_imf_context_selection_get (imcontext->ctx, &selection);
2412 if (imcontext->text_input) {
2413 SECURE_LOGD ("selection :%s", selection ? selection : "");
2415 char *_selection = selection;
2416 size_t len = strlen (selection);
2418 ssize_t ret = write (fd, _selection, len);
2422 LOGW ("write pipe failed, errno: %d", errno);
2436 text_input_get_surrounding_text (void *data,
2437 struct wl_text_input *text_input EINA_UNUSED,
2438 uint32_t maxlen_before,
2439 uint32_t maxlen_after,
2443 char *surrounding = NULL;
2444 LOGD("fd: %d maxlen_before: %d maxlen_after: %d", fd, maxlen_before, maxlen_after);
2445 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2446 if (!imcontext || !imcontext->ctx) {
2447 LOGD ("No context!");
2452 /* cursor_pos is a byte index */
2453 if (ecore_imf_context_surrounding_get (imcontext->ctx, &surrounding, &cursor_pos)) {
2454 SECURE_LOGD ("surrounding : '%s', cursor: %d", surrounding ? surrounding : "", cursor_pos);
2455 if (imcontext->text_input) {
2456 Eina_Unicode *wide_surrounding = eina_unicode_utf8_to_unicode (surrounding, NULL);
2457 size_t wlen = eina_unicode_strlen (wide_surrounding);
2459 if (cursor_pos > (int)wlen || cursor_pos < 0)
2462 if (maxlen_before > cursor_pos)
2465 maxlen_before = cursor_pos - maxlen_before;
2467 if (maxlen_after > wlen - cursor_pos)
2468 maxlen_after = (uint32_t)wlen;
2470 maxlen_after = cursor_pos + maxlen_after;
2472 char *req_surrounding = eina_unicode_unicode_to_utf8_range (wide_surrounding + maxlen_before, maxlen_after - maxlen_before, NULL);
2474 ssize_t ret = write(fd, &cursor_pos, sizeof(cursor_pos));
2476 LOGW ("write pipe failed, errno: %d", errno);
2477 } else if (req_surrounding) {
2478 char *_surrounding = req_surrounding;
2479 size_t len = strlen(req_surrounding);
2481 ssize_t ret = write(fd, _surrounding, len);
2485 LOGW ("write pipe failed, errno: %d", errno);
2488 _surrounding += ret;
2493 if (req_surrounding)
2494 free (req_surrounding);
2496 if (wide_surrounding)
2497 free (wide_surrounding);
2507 text_input_filter_key_event_done(void *data,
2508 struct wl_text_input *text_input EINA_UNUSED,
2512 LOGD("serial: %d, state: %d", serial, state);
2513 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2514 if (!imcontext) return;
2516 imcontext->last_key_event_filter.serial = serial;
2517 imcontext->last_key_event_filter.state = state;
2521 text_input_hide_permission(void *data,
2522 struct wl_text_input *text_input EINA_UNUSED,
2523 uint32_t permission)
2525 LOGD("permission : %d", permission);
2526 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2527 if (!imcontext || !imcontext->ctx || ignore_hide)
2531 ecore_imf_context_input_panel_hide(imcontext->ctx);
2535 text_input_recapture_string(void *data,
2536 struct wl_text_input *text_input EINA_UNUSED,
2540 const char *preedit,
2541 const char *preedit_commit,
2544 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2545 Eina_Bool old_preedit = EINA_FALSE;
2546 Eina_Bool preedit_changed = EINA_FALSE;
2548 SECURE_LOGD("ctx : %p, index : %d, length : %d, preedit event (preedit: '%s', current pre-edit: '%s')",
2553 imcontext->preedit_text ? imcontext->preedit_text : "");
2555 if (!check_serial(imcontext, serial))
2559 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
2561 if (imcontext->preedit_text)
2562 preedit_changed = (strcmp(imcontext->preedit_text, preedit) != 0);
2564 preedit_changed = (strlen(preedit) != 0);
2566 // send transaction start
2567 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_START");
2568 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_START, NULL);
2570 commit_preedit(imcontext);
2571 clear_preedit(imcontext);
2573 // delete surrounding text
2574 delete_surrounding_text(imcontext, index, length);
2576 // update preedit string
2577 imcontext->preedit_text = strdup(preedit);
2578 imcontext->preedit_commit = (strlen(preedit) > 0 ? strdup(preedit_commit) : NULL);
2579 imcontext->preedit_cursor =
2580 utf8_offset_to_characters(preedit, imcontext->pending_preedit.cursor);
2581 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
2583 imcontext->pending_preedit.attrs = NULL;
2585 if (preedit_changed) {
2587 ecore_imf_context_event_callback_call(imcontext->ctx,
2588 ECORE_IMF_CALLBACK_PREEDIT_START,
2592 ecore_imf_context_event_callback_call(imcontext->ctx,
2593 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
2596 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
2597 ecore_imf_context_event_callback_call(imcontext->ctx,
2598 ECORE_IMF_CALLBACK_PREEDIT_END,
2604 if (commit && strlen(commit) != 0) {
2605 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)commit);
2608 // send transaction end
2609 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_END");
2610 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_END, NULL);
2614 text_input_input_panel_event(void *data,
2615 struct wl_text_input *text_input EINA_UNUSED,
2616 uint32_t serial EINA_UNUSED,
2617 uint32_t event_type,
2620 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2621 if (!imcontext || !imcontext->ctx) return;
2623 LOGD("event type : %d, value : %d", event_type, value);
2625 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, event_type, value);
2629 static const struct wl_text_input_listener text_input_listener =
2633 text_input_modifiers_map,
2634 text_input_input_panel_state,
2635 text_input_preedit_string,
2636 text_input_preedit_styling,
2637 text_input_preedit_cursor,
2638 text_input_commit_string,
2639 text_input_cursor_position,
2640 text_input_delete_surrounding_text,
2642 text_input_language,
2643 text_input_text_direction,
2644 // TIZEN_ONLY(20150918): Support to set the selection region
2645 text_input_selection_region,
2646 text_input_private_command,
2647 text_input_input_panel_geometry,
2648 text_input_input_panel_data,
2649 text_input_get_selection_text,
2650 text_input_get_surrounding_text,
2651 text_input_filter_key_event_done,
2652 text_input_hide_permission,
2653 text_input_recapture_string,
2654 text_input_input_panel_event,
2655 text_input_commit_content
2661 keyboard_mode_changed_cb (keynode_t *key, void* data)
2663 hw_keyboard_mode = vconf_keynode_get_bool (key);
2664 Ecore_IMF_Context *active_ctx = get_using_ctx ();
2666 LOGD ("ctx : %p, input detect : %d", active_ctx, hw_keyboard_mode);
2668 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;
2669 ecore_imf_context_input_panel_event_callback_call (active_ctx, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, input_mode);
2671 if (input_mode == ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE && _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW)
2672 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2674 if ((input_mode == ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE) && _focused_ctx && (active_ctx == _focused_ctx)) {
2675 if (ecore_imf_context_input_panel_enabled_get (active_ctx)) {
2676 ecore_imf_context_input_panel_show (active_ctx);
2683 #ifdef SOCKET_ACTIVATION
2684 static int activate_socket () {
2686 struct sockaddr_un svr;
2692 LOGD("socket_activate start");
2693 s = socket(AF_UNIX, SOCK_STREAM, 0);
2695 LOGW("socket error");
2699 flag = fcntl(s, F_GETFL, NULL);
2701 fcntl(s, F_SETFL, flag);
2703 svr.sun_family = AF_UNIX;
2704 strcpy(svr.sun_path, SOCK_PATH);
2707 r = connect(s, (struct sockaddr *)&svr, len);
2709 LOGD("connect error");
2717 gettimeofday(&s1, NULL);
2718 LOGD("%d %06d\n", (int)s1.tv_sec, (int)s1.tv_usec);
2720 r = send(s, (const void *)&s1, sizeof(s1), 0);
2733 void wayland_im_initialize ()
2735 register_key_handler ();
2737 /* get input language vconf value */
2738 char *input_lang_str = vconf_get_str (VCONFKEY_ISF_INPUT_LANGUAGE);
2739 if (input_lang_str) {
2740 set_input_language (input_lang_str);
2741 free (input_lang_str);
2745 /* get autoperiod allow vconf value */
2747 if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
2748 if (val == EINA_TRUE)
2749 autoperiod_allow = EINA_TRUE;
2752 /* get autocapital allow vconf value */
2753 if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
2754 if (val == EINA_TRUE)
2755 autocap_allow = EINA_TRUE;
2758 /* get hardware keyboard input detected vconf value */
2759 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
2760 if (val == EINA_TRUE)
2761 hw_keyboard_mode = EINA_TRUE;
2764 vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL);
2765 vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL);
2766 vconf_notify_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb, NULL);
2767 vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
2770 _ime_device = ecore_device_add();
2772 ecore_device_name_set (_ime_device, IME_DEVICE_NAME);
2773 ecore_device_description_set (_ime_device, IME_DEVICE_NAME);
2774 ecore_device_identifier_set (_ime_device, IME_DEVICE_NAME);
2775 ecore_device_class_set (_ime_device, ECORE_DEVICE_CLASS_KEYBOARD);
2776 ecore_device_subclass_set (_ime_device, ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD);
2780 void wayland_im_uninitialize ()
2782 _ecore_imf_wayland_imcontext_pair_destroy ();
2784 unregister_key_handler ();
2786 _win_focus_out_handler_del ();
2787 _conformant_change_handler_del ();
2790 vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
2791 vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
2792 vconf_ignore_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb);
2793 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
2797 ecore_device_del (_ime_device);
2801 ecore_event_type_flush(ECORE_EVENT_DEVICE_ADD, ECORE_EVENT_DEVICE_DEL);
2805 wayland_im_context_add(Ecore_IMF_Context *ctx)
2807 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2810 LOGD("ctx : %p", ctx);
2812 if (!imcontext) return;
2814 imcontext->ctx = ctx;
2815 imcontext->input_panel_layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2816 imcontext->keysym_list = NULL;
2818 imcontext->shift_mask = MOD_SHIFT_MASK;
2819 imcontext->control_mask = MOD_CONTROL_MASK;
2820 imcontext->alt_mask = MOD_ALT_MASK;
2821 imcontext->caps_mask = MOD_CAPS_MASK;
2822 imcontext->num_mask = MOD_NUM_MASK;
2824 imcontext->input_panel_position.x = -1;
2825 imcontext->input_panel_position.y = -1;
2827 LOGD("text_input_manager : %p", imcontext->text_input_manager);
2828 imcontext->text_input =
2829 wl_text_input_manager_create_text_input(imcontext->text_input_manager);
2831 if (imcontext->text_input)
2832 wl_text_input_add_listener(imcontext->text_input,
2833 &text_input_listener, imcontext);
2836 LOGD("app id : %s\n", appid);
2838 ecore_imf_context_prediction_hint_hash_set(ctx, "appid", appid ? appid : "");
2845 wayland_im_context_del (Ecore_IMF_Context *ctx)
2847 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2849 Eina_Bool valid = EINA_FALSE;
2850 Ecore_Imf_Wayland_Imcontext_Pair *pair = _ecore_imf_wayland_imcontext_pair_find(ctx);
2851 if (pair && pair->imcontext == imcontext) {
2852 _ecore_imf_wayland_imcontext_pair_del(ctx);
2856 LOGE("The Ecore_Imf %p and WaylandIMContext %p pair not found!! pair : %p, pair->imcontext %p",
2857 ctx, imcontext, pair, pair ? pair->imcontext : NULL);
2858 _ecore_imf_wayland_imcontext_pair_log();
2861 Ecore_Event_Key *ev;
2862 LOGD ("ctx : %p, ctx valid : %d, focused_ctx : %p, show_req_ctx : %p", ctx, valid, _focused_ctx, _show_req_ctx);
2864 if (!imcontext) return;
2866 // TIZEN_ONLY(20150708): Support back key
2867 if (_input_panel_ctx == ctx) {
2868 _clear_hide_timer();
2869 _input_panel_hide(ctx, EINA_TRUE);
2870 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2871 _input_panel_ctx = NULL;
2874 if (_focused_ctx == ctx)
2875 _focused_ctx = NULL;
2877 if (_show_req_ctx == ctx)
2878 _show_req_ctx = NULL;
2880 if (_focus_req_ctx == ctx) {
2881 if (imcontext->canvas)
2882 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
2884 _focus_req_ctx = NULL;
2885 _focus_req_only = EINA_TRUE;
2889 if (imcontext->language) {
2890 free (imcontext->language);
2891 imcontext->language = NULL;
2894 // TIZEN_ONLY(20150922): Support to set input panel data
2895 if (imcontext->imdata) {
2896 free (imcontext->imdata);
2897 imcontext->imdata = NULL;
2898 imcontext->imdata_size = 0;
2901 if (imcontext->input_panel_data) {
2902 free (imcontext->input_panel_data);
2903 imcontext->input_panel_data = NULL;
2904 imcontext->input_panel_data_length = 0;
2908 if (imcontext->prediction_hint) {
2909 free (imcontext->prediction_hint);
2910 imcontext->prediction_hint = NULL;
2913 if (imcontext->mime_type) {
2914 free (imcontext->mime_type);
2915 imcontext->mime_type = NULL;
2918 if (imcontext->text_input)
2919 wl_text_input_destroy (imcontext->text_input);
2921 clear_preedit (imcontext);
2923 EINA_LIST_FREE(imcontext->keysym_list, ev) {
2932 wayland_im_context_reset(Ecore_IMF_Context *ctx)
2934 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2936 LOGD("ctx : %p", ctx);
2938 if (!imcontext) return;
2940 commit_preedit (imcontext);
2942 if (!imcontext->input) return;
2944 if (imcontext->text_input) {
2945 wl_text_input_reset(imcontext->text_input);
2947 update_state(imcontext);
2949 imcontext->reset_serial = imcontext->serial;
2953 _prediction_hint_data_foreach_cb(const Eina_Hash *hash, const void *key,
2954 void *data, void *fdata)
2956 const char *key_str = key;
2957 const char *value = data;
2958 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)fdata;
2959 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2961 SECURE_LOGD("key : %s, value : %s\n", key_str, value);
2963 if (imcontext && imcontext->text_input)
2964 wl_text_input_prediction_hint_data(imcontext->text_input, key_str, value);
2970 wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
2972 LOGD ("ctx : %p. enable : %d, on demand : %d", ctx,
2973 ecore_imf_context_input_panel_enabled_get(ctx),
2974 ecore_imf_context_input_panel_show_on_demand_get (ctx));
2976 #ifdef SOCKET_ACTIVATION
2980 if (!set_focus(ctx)) {
2981 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2982 if (imcontext && !imcontext->input) {
2983 if (_focus_req_ctx != ctx)
2984 _focus_req_only = EINA_TRUE;
2985 _focus_req_ctx = ctx;
2986 if (imcontext->canvas) {
2987 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
2988 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
2991 LOGW("ctx : %p. Fail to set focus!", ctx);
2995 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2996 if (imcontext && imcontext->input && imcontext->text_input) {
2997 wl_text_input_set_return_key_disabled(imcontext->text_input,
2998 imcontext->return_key_disabled);
3000 if (imcontext->prediction_hint)
3001 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
3003 if (imcontext->mime_type)
3004 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
3006 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
3007 wl_text_input_set_input_panel_position(imcontext->text_input,
3008 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
3010 const Eina_Hash *hash = ecore_imf_context_prediction_hint_hash_get(ctx);
3012 eina_hash_foreach(hash, _prediction_hint_data_foreach_cb, ctx);
3014 wl_text_input_set_content_type(imcontext->text_input, imcontext->content_hint, get_purpose(ctx));
3018 hw_keyboard_mode = EINA_FALSE;
3020 if (ecore_imf_context_input_panel_enabled_get(ctx))
3021 if (!ecore_imf_context_input_panel_show_on_demand_get (ctx))
3022 show_input_panel(ctx);
3024 LOGD ("ctx : %p input panel on demand mode : TRUE", ctx);
3026 LOGD ("ctx : %p input panel enable : FALSE", ctx);
3030 wayland_im_context_focus_out(Ecore_IMF_Context *ctx)
3032 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3034 LOGD("ctx : %p", ctx);
3036 if (_focus_req_ctx == ctx) {
3037 _focus_req_ctx = NULL;
3038 _focus_req_only = EINA_TRUE;
3041 if (!imcontext || !imcontext->input) return;
3044 if (hw_keyboard_mode == EINA_TRUE) {
3045 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3046 hw_keyboard_mode = EINA_FALSE;
3050 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3051 ecore_imf_context_input_panel_hide(ctx);
3058 wayland_im_context_preedit_string_get(Ecore_IMF_Context *ctx,
3062 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3063 if (!imcontext) return;
3065 SECURE_LOGD("pre-edit string requested (preedit: '%s', preedit cursor : %d)",
3066 imcontext->preedit_text ? imcontext->preedit_text : "", imcontext->preedit_cursor);
3069 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3072 *cursor_pos = imcontext->preedit_cursor;
3076 wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
3081 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3082 if (!imcontext) return;
3084 SECURE_LOGD("pre-edit string with attributes requested (preedit: '%s', preedit cursor : %d)",
3085 imcontext->preedit_text ? imcontext->preedit_text : "", imcontext->preedit_cursor);
3088 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3092 Ecore_IMF_Preedit_Attr *a, *attr;
3094 if (imcontext->preedit_attrs) {
3095 EINA_LIST_FOREACH(imcontext->preedit_attrs, l, a) {
3096 attr = malloc(sizeof(*attr));
3098 attr = memcpy(attr, a, sizeof(*attr));
3099 *attrs = eina_list_append(*attrs, attr);
3104 if (imcontext->preedit_text) {
3105 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
3107 // use REVERSE style as default
3108 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
3109 attr->start_index = 0;
3110 attr->end_index = strlen(imcontext->preedit_text);
3111 *attrs = eina_list_append(*attrs, attr);
3118 *cursor_pos = imcontext->preedit_cursor;
3122 wayland_im_context_cursor_position_set (Ecore_IMF_Context *ctx,
3125 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3126 if (!imcontext) return;
3128 if (imcontext->cursor_position != cursor_pos) {
3129 imcontext->cursor_position = cursor_pos;
3131 if (imcontext->input && imcontext->text_input) {
3132 LOGD ("ctx : %p, cursor pos : %d", ctx, cursor_pos);
3134 set_autocapital (ctx);
3136 if (!imcontext->preedit_text || strlen(imcontext->preedit_text) == 0)
3137 wl_text_input_set_cursor_position (imcontext->text_input, cursor_pos);
3143 wayland_im_context_use_preedit_set(Ecore_IMF_Context *ctx EINA_UNUSED,
3144 Eina_Bool use_preedit EINA_UNUSED)
3149 wayland_im_context_client_window_set(Ecore_IMF_Context *ctx,
3152 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3154 LOGD("client window set (window: %p)", window);
3156 if (imcontext && window) {
3157 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3160 imcontext->window = ecore_wl2_display_window_find(wl2_display, (Ecore_Window)window);
3162 if (_ime_device && imcontext->window)
3163 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3168 wayland_im_context_client_canvas_set(Ecore_IMF_Context *ctx,
3171 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3173 LOGD("client canvas set (canvas: %p)", canvas);
3175 if (imcontext && canvas) {
3176 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3177 imcontext->canvas = canvas;
3179 if (wl2_display && !imcontext->window)
3180 imcontext->window = ecore_wl2_display_window_find(wl2_display, ecore_evas_window_get(ecore_evas_ecore_evas_get(canvas)));
3182 if (_ime_device && imcontext->window)
3183 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3188 wayland_im_context_show(Ecore_IMF_Context *ctx)
3190 LOGD("ctx : %p", ctx);
3192 show_input_panel(ctx);
3196 wayland_im_context_hide(Ecore_IMF_Context *ctx)
3198 LOGD("ctx : %p", ctx);
3200 if (!get_using_ctx()) {
3201 LOGW("Can't hide input_panel because there is no using context!!");
3205 _input_panel_hide(ctx, EINA_FALSE);
3208 #if !(ENABLE_GRAB_KEYBOARD)
3210 _ecore_imf_lock_to_ecore_key_modifier(unsigned int locks)
3212 unsigned int mask = 0;
3214 if (locks & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
3215 mask |= ECORE_EVENT_LOCK_SCROLL;
3217 if (locks & ECORE_IMF_KEYBOARD_LOCK_CAPS)
3218 mask |= ECORE_EVENT_LOCK_CAPS;
3220 if (locks & ECORE_IMF_KEYBOARD_LOCK_NUM)
3221 mask |= ECORE_EVENT_LOCK_NUM;
3227 _ecore_imf_modifier_to_ecore_key_modifier(Ecore_IMF_Keyboard_Modifiers modifiers)
3229 unsigned int mask = 0;
3231 /**< "Control" is pressed */
3232 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
3233 mask |= ECORE_EVENT_MODIFIER_CTRL;
3235 /**< "Alt" is pressed */
3236 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
3237 mask |= ECORE_EVENT_MODIFIER_ALT;
3239 /**< "Shift" is pressed */
3240 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
3241 mask |= ECORE_EVENT_MODIFIER_SHIFT;
3243 /**< "Win" (between "Ctrl" and "Alt") is pressed */
3244 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
3245 mask |= ECORE_EVENT_MODIFIER_WIN;
3247 /**< "AltGr" is pressed */
3248 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
3249 mask |= ECORE_EVENT_MODIFIER_ALTGR;
3256 wayland_im_context_filter_event(Ecore_IMF_Context *ctx,
3257 Ecore_IMF_Event_Type type,
3258 Ecore_IMF_Event *imf_event)
3261 #if !(ENABLE_GRAB_KEYBOARD)
3262 Eina_Bool ret = EINA_FALSE;
3263 Ecore_Event_Key ecore_key_ev;
3264 char *key_dev_name = NULL;
3265 uint32_t key_dev_class = 0;
3266 uint32_t key_dev_subclass = 0;
3268 if (type == ECORE_IMF_EVENT_MOUSE_UP) {
3269 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3270 LOGD ("[Mouse-up event] ctx : %p", ctx);
3271 if (ctx == _focused_ctx) {
3272 ecore_imf_context_input_panel_show(ctx);
3275 LOGE ("Can't show IME because there is no focus. ctx : %p", ctx);
3278 #if !(ENABLE_GRAB_KEYBOARD)
3279 else if (type == ECORE_IMF_EVENT_KEY_UP) {
3280 Ecore_IMF_Event_Key_Up *key_ev = (Ecore_IMF_Event_Key_Up *)imf_event;
3281 ecore_key_ev.keyname = key_ev->keyname;
3282 ecore_key_ev.key = key_ev->key;
3283 ecore_key_ev.string = key_ev->string;
3284 ecore_key_ev.compose = key_ev->compose;
3285 ecore_key_ev.timestamp = key_ev->timestamp;
3286 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3287 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3288 key_dev_name = (char *)key_ev->dev_name;
3289 key_dev_class = key_ev->dev_class;
3290 key_dev_subclass = key_ev->dev_subclass;
3291 ecore_key_ev.keycode = key_ev->keycode;
3293 else if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3294 Ecore_IMF_Event_Key_Down *key_ev = (Ecore_IMF_Event_Key_Down *)imf_event;
3295 ecore_key_ev.keyname = key_ev->keyname;
3296 ecore_key_ev.key = key_ev->key;
3297 ecore_key_ev.string = key_ev->string;
3298 ecore_key_ev.compose = key_ev->compose;
3299 ecore_key_ev.timestamp = key_ev->timestamp;
3300 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3301 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3302 key_dev_name = (char *)key_ev->dev_name;
3303 key_dev_class = key_ev->dev_class;
3304 key_dev_subclass = key_ev->dev_subclass;
3305 ecore_key_ev.keycode = key_ev->keycode;
3308 if (type == ECORE_IMF_EVENT_KEY_UP || type == ECORE_IMF_EVENT_KEY_DOWN) {
3309 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3310 if (!imcontext || !imcontext->input || !imcontext->text_input)
3313 if (!_focused_ctx) {
3318 if (_focused_ctx != ctx) {
3319 LOGW ("focused context is different from the context used in ecore_imf_context_filter_event.");
3320 LOGW ("focus context : %p, context : %p", _focused_ctx, ctx);
3325 if (!ecore_key_ev.timestamp && (ecore_key_ev.modifiers & MOD_Mod5_MASK)
3326 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD) {
3327 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3328 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3329 strcmp (ecore_key_ev.key, "KP_Space") == 0 ) {
3330 autoperiod_insert (ctx);
3334 LOGD("Return! This is SW keyboard fake event!");
3338 int serial = imcontext->serial++;
3339 double start_time = ecore_time_get();
3342 uint32_t modifiers = 0;
3343 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_SHIFT)
3344 modifiers |= imcontext->shift_mask;
3345 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_CTRL)
3346 modifiers |= imcontext->control_mask;
3347 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_ALT)
3348 modifiers |= imcontext->alt_mask;
3349 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_CAPS)
3350 modifiers |= imcontext->caps_mask;
3351 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_NUM)
3352 modifiers |= imcontext->num_mask;
3354 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, keycode=%u", ecore_key_ev.modifiers, modifiers, imcontext->shift_mask, imcontext->control_mask, imcontext->alt_mask, imcontext->caps_mask, imcontext->num_mask, ecore_key_ev.keycode);
3355 //Send key event to IME.
3356 wl_text_input_filter_key_event(imcontext->text_input, serial, ecore_key_ev.timestamp, ecore_key_ev.key,
3357 type == ECORE_IMF_EVENT_KEY_UP? WL_KEYBOARD_KEY_STATE_RELEASED : WL_KEYBOARD_KEY_STATE_PRESSED,
3358 modifiers, (key_dev_name ? key_dev_name : ""), key_dev_class, key_dev_subclass, ecore_key_ev.keycode);
3359 //Waiting for filter_key_event_done from IME.
3360 //This function should return IME filtering result with boolean type.
3361 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3362 struct wl_display *display = NULL;
3364 display = ecore_wl2_display_get(wl2_display);
3367 struct wl_event_queue *queue = wl_display_create_queue(display);
3370 while (ecore_time_get() - start_time < WAIT_FOR_FILTER_DONE_SECOND && _focused_ctx == ctx && wl_display_roundtrip_queue(display, queue) != -1) {
3371 wl_display_dispatch_pending(display);
3372 if (imcontext->last_key_event_filter.serial == serial) {
3373 ret = imcontext->last_key_event_filter.state;
3375 } else if (imcontext->last_key_event_filter.serial > serial)
3379 wl_event_queue_destroy(queue);
3382 LOGD ("elapsed : %.3f ms, serial (last, require) : (%d, %d)", (ecore_time_get() - start_time)*1000, imcontext->last_key_event_filter.serial, serial);
3386 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3387 if (ret == EINA_FALSE) {
3389 if (strcmp (ecore_key_ev.keyname, "Return") == 0 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_REMOCON) {
3391 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
3393 LOGD ("Changed keyboard mode from H/W to S/W ");
3394 hw_keyboard_mode = EINA_FALSE;
3395 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3396 if (ecore_imf_context_input_panel_enabled_get (ctx)) {
3397 ecore_imf_context_input_panel_show (ctx);
3404 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3405 strcmp (ecore_key_ev.key, "KP_Space") == 0) {
3406 autoperiod_insert (ctx);
3411 //Deal with the next key event in list.
3412 Ecore_Event_Key *ev = NULL;
3413 if (eina_list_count (imcontext->keysym_list)) {
3414 Eina_List *n = eina_list_last(imcontext->keysym_list);
3415 ev = (Ecore_Event_Key *)eina_list_data_get(n);
3416 int event_type = (unsigned long int)ev->data;
3419 ecore_event_add(event_type, ev, _ecore_keyevent_free, NULL);
3420 imcontext->keysym_list = eina_list_remove_list(imcontext->keysym_list, n);
3431 wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int width, int height)
3433 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3434 if (!imcontext) return;
3436 if ((imcontext->cursor_location.x != x) ||
3437 (imcontext->cursor_location.y != y) ||
3438 (imcontext->cursor_location.width != width) ||
3439 (imcontext->cursor_location.height != height)) {
3440 imcontext->cursor_location.x = x;
3441 imcontext->cursor_location.y = y;
3442 imcontext->cursor_location.width = width;
3443 imcontext->cursor_location.height = height;
3445 if (_focused_ctx == ctx)
3446 send_cursor_location (imcontext);
3450 void wayland_im_context_autocapital_type_set(Ecore_IMF_Context *ctx,
3451 Ecore_IMF_Autocapital_Type autocapital_type)
3453 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3454 if (!imcontext) return;
3456 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
3457 // TIZEN_ONLY(20160201): Add autocapitalization word
3458 WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION |
3460 WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
3461 WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE);
3463 if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE)
3464 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION;
3465 // TIZEN_ONLY(20160201): Add autocapitalization word
3466 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD)
3467 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
3469 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER)
3470 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE;
3472 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE;
3474 if (imcontext->input && imcontext->text_input) {
3475 LOGD ("ctx : %p. set autocapital type : %d", ctx, autocapital_type);
3476 wl_text_input_set_content_type(imcontext->text_input,
3477 imcontext->content_hint,
3483 wayland_im_context_input_panel_layout_set(Ecore_IMF_Context *ctx,
3484 Ecore_IMF_Input_Panel_Layout layout)
3486 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3487 if (!imcontext) return;
3489 imcontext->input_panel_layout = layout;
3492 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER:
3493 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
3495 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL:
3496 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL;
3498 case ECORE_IMF_INPUT_PANEL_LAYOUT_URL:
3499 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_URL;
3501 case ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER:
3502 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE;
3504 case ECORE_IMF_INPUT_PANEL_LAYOUT_IP:
3505 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3506 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_IP;
3509 case ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH:
3510 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATE;
3512 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY:
3513 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
3515 case ECORE_IMF_INPUT_PANEL_LAYOUT_HEX:
3516 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_HEX;
3518 case ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL:
3519 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL;
3521 case ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD:
3522 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
3523 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3525 case ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME:
3526 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME;
3528 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3529 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON:
3530 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON;
3533 case ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE:
3534 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE;
3537 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
3541 if (imcontext->input && imcontext->text_input) {
3542 LOGD ("ctx : %p, layout type : %d", ctx, layout);
3543 wl_text_input_set_content_type(imcontext->text_input,
3544 imcontext->content_hint,
3549 Ecore_IMF_Input_Panel_Layout
3550 wayland_im_context_input_panel_layout_get(Ecore_IMF_Context *ctx)
3552 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3553 if (!imcontext) return ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
3555 return imcontext->input_panel_layout;
3559 wayland_im_context_input_mode_set(Ecore_IMF_Context *ctx,
3560 Ecore_IMF_Input_Mode input_mode)
3562 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3563 if (!imcontext) return;
3565 if (input_mode & ECORE_IMF_INPUT_MODE_INVISIBLE)
3566 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3568 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3570 if (imcontext->input && imcontext->text_input) {
3571 LOGD ("ctx : %p, input mode : %d", ctx, input_mode);
3572 wl_text_input_set_content_type(imcontext->text_input,
3573 imcontext->content_hint,
3579 wayland_im_context_input_hint_set(Ecore_IMF_Context *ctx,
3580 Ecore_IMF_Input_Hints input_hints)
3582 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3583 if (!imcontext) return;
3585 if (input_hints & ECORE_IMF_INPUT_HINT_AUTO_COMPLETE)
3586 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3588 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3590 if (input_hints & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA)
3591 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3593 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3595 if (input_hints & ECORE_IMF_INPUT_HINT_MULTILINE)
3596 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3598 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3601 LOGD("autofill hint : %x\n", input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK);
3603 switch(input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK)
3605 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE:
3606 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE;
3608 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY:
3609 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY;
3611 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH:
3612 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH;
3614 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR:
3615 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR;
3617 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_NUMBER:
3618 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_NUMBER;
3620 case ECORE_IMF_INPUT_HINT_AUTOFILL_EMAIL_ADDRESS:
3621 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_EMAIL_ADDRESS;
3623 case ECORE_IMF_INPUT_HINT_AUTOFILL_PHONE:
3624 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_PHONE;
3626 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_ADDRESS:
3627 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_ADDRESS;
3629 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_CODE:
3630 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_CODE;
3632 case ECORE_IMF_INPUT_HINT_AUTOFILL_ID:
3633 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_ID;
3635 case ECORE_IMF_INPUT_HINT_AUTOFILL_NAME:
3636 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_NAME;
3640 if (imcontext->input && imcontext->text_input) {
3641 LOGD("ctx : %p, input hint : %#x", ctx, input_hints);
3642 wl_text_input_set_content_type(imcontext->text_input,
3643 imcontext->content_hint,
3649 wayland_im_context_input_panel_language_set(Ecore_IMF_Context *ctx,
3650 Ecore_IMF_Input_Panel_Lang lang)
3652 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3653 if (!imcontext) return;
3655 if (lang == ECORE_IMF_INPUT_PANEL_LANG_ALPHABET)
3656 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3658 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3660 if (imcontext->input && imcontext->text_input)
3661 wl_text_input_set_content_type(imcontext->text_input,
3662 imcontext->content_hint,
3666 // TIZEN_ONLY(20150708): Support input_panel_state_get
3667 Ecore_IMF_Input_Panel_State
3668 wayland_im_context_input_panel_state_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3670 return _input_panel_state;
3674 wayland_im_context_input_panel_return_key_type_set(Ecore_IMF_Context *ctx,
3675 Ecore_IMF_Input_Panel_Return_Key_Type return_key_type)
3677 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3678 if (!imcontext) return;
3680 imcontext->return_key_type = return_key_type;
3682 if (imcontext->input && imcontext->text_input)
3683 wl_text_input_set_return_key_type(imcontext->text_input,
3684 imcontext->return_key_type);
3688 wayland_im_context_input_panel_return_key_disabled_set(Ecore_IMF_Context *ctx,
3691 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3692 if (!imcontext) return;
3694 imcontext->return_key_disabled = disabled;
3696 if (imcontext->input && imcontext->text_input)
3697 wl_text_input_set_return_key_disabled(imcontext->text_input,
3698 imcontext->return_key_disabled);
3703 wayland_im_context_input_panel_language_locale_get(Ecore_IMF_Context *ctx,
3706 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3707 if (!imcontext) return;
3710 *locale = strdup(imcontext->language ? imcontext->language : "");
3714 wayland_im_context_prediction_allow_set(Ecore_IMF_Context *ctx,
3715 Eina_Bool prediction)
3717 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3718 if (!imcontext) return;
3721 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3723 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3725 if (imcontext->input && imcontext->text_input)
3726 wl_text_input_set_content_type(imcontext->text_input,
3727 imcontext->content_hint,
3731 // TIZEN_ONLY(20151221): Support input panel geometry
3733 wayland_im_context_input_panel_geometry_get(Ecore_IMF_Context *ctx EINA_UNUSED,
3734 int *x, int *y, int *w, int *h)
3737 *x = _keyboard_geometry.x;
3739 *y = _keyboard_geometry.y;
3741 *w = _keyboard_geometry.w;
3743 *h = _keyboard_geometry.h;
3747 wayland_im_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *data, int length)
3749 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3750 if (!imcontext) return;
3752 if (data && length > 0) {
3753 const char *custom_conformant_enabled = "conformant:custom,enabled";
3754 const char *custom_conformant_disabled = "conformant:custom,disabled";
3755 const char *custom_conformant_finished = "conformant:custom,finished";
3757 if (strncmp(data, custom_conformant_enabled, strlen(custom_conformant_enabled)) == 0) {
3758 _custom_conformant_event = EINA_TRUE;
3761 if (strncmp(data, custom_conformant_disabled, strlen(custom_conformant_disabled)) == 0) {
3762 _custom_conformant_event = EINA_FALSE;
3765 if (strncmp(data, custom_conformant_finished, strlen(custom_conformant_finished)) == 0) {
3766 if (_custom_conformant_event) {
3767 _conformant_reset_done = EINA_TRUE;
3768 LOGD("[conformant:custom,finished], _conformant_reset_done = 1");
3769 send_will_hide_ack(NULL);
3775 if (imcontext->imdata)
3776 free(imcontext->imdata);
3778 imcontext->imdata = calloc(1, length);
3779 if (imcontext->imdata && data)
3780 memcpy(imcontext->imdata, data, length);
3782 imcontext->imdata_size = length;
3784 if (imcontext->input && imcontext->text_input && (imcontext->imdata_size > 0))
3785 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
3789 wayland_im_context_input_panel_imdata_get(Ecore_IMF_Context *ctx, void *data, int *length)
3792 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3794 if (imcontext && imcontext->input_panel_data && (imcontext->input_panel_data_length > 0)) {
3796 memcpy(data, imcontext->input_panel_data, imcontext->input_panel_data_length);
3799 *length = imcontext->input_panel_data_length;
3807 // TIZEN_ONLY(20160218): Support BiDi direction
3809 wayland_im_context_bidi_direction_set(Ecore_IMF_Context *ctx, Ecore_IMF_BiDi_Direction bidi_direction)
3811 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3812 if (!imcontext) return;
3814 imcontext->bidi_direction = bidi_direction;
3816 if (imcontext->input && imcontext->text_input) {
3817 LOGD ("ctx : %p, bidi direction : %#x", ctx, bidi_direction);
3818 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
3823 Ecore_IMF_Input_Panel_Keyboard_Mode
3824 wayland_im_context_input_panel_keyboard_mode_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3826 return hw_keyboard_mode ? ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE : ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE;
3830 wayland_im_context_prediction_hint_set (Ecore_IMF_Context *ctx, const char *prediction_hint)
3832 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3833 if (!imcontext) return;
3835 imcontext->prediction_hint = strdup(prediction_hint ? prediction_hint : "");
3837 if (imcontext->input && imcontext->text_input) {
3838 SECURE_LOGD ("ctx : %p, prediction_hint : %s", ctx, imcontext->prediction_hint);
3839 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
3844 wayland_im_context_mime_type_accept_set (Ecore_IMF_Context *ctx, const char *mime_type)
3846 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3847 if (!imcontext) return;
3849 imcontext->mime_type = strdup(mime_type);
3851 if (imcontext->input && imcontext->text_input && (strlen(mime_type) > 0)) {
3852 LOGD ("ctx : %p, mime_type : %s", ctx, imcontext->mime_type);
3853 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
3858 wayland_im_context_input_panel_position_set (Ecore_IMF_Context *ctx, int x, int y)
3860 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3861 if (!imcontext) return;
3863 if ((imcontext->input_panel_position.x != x) || (imcontext->input_panel_position.y != y)) {
3864 imcontext->input_panel_position.x = x;
3865 imcontext->input_panel_position.y = y;
3868 if (imcontext->input && imcontext->text_input) {
3869 LOGD ("ctx : %p, x = %d, y = %d", ctx, x, y);
3870 wl_text_input_set_input_panel_position(imcontext->text_input,
3871 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
3875 WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager)
3877 WaylandIMContext *context = calloc(1, sizeof(WaylandIMContext));
3879 LOGD("new context created");
3880 context->text_input_manager = text_input_manager;
3886 void wayland_im_context_pair_set (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
3888 _ecore_imf_wayland_imcontext_pair_add (ctx, imcontext);