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 1.3
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 static Eina_Bool will_hide = EINA_FALSE;
109 static Eina_Bool ignore_hide = EINA_FALSE;
111 static Ecore_Event_Filter *_ecore_event_filter_handler = NULL;
112 static Ecore_IMF_Context *_focused_ctx = NULL;
113 static Ecore_IMF_Context *_show_req_ctx = NULL;
114 static Ecore_IMF_Context *_hide_req_ctx = NULL;
115 static Ecore_IMF_Context *_focus_req_ctx = NULL;
116 static Ecore_IMF_Context *_input_panel_ctx = NULL;
117 static Eina_Bool _focus_req_only = EINA_TRUE;
119 static Eina_Rectangle _keyboard_geometry = {0, 0, 0, 0};
121 static Ecore_IMF_Input_Panel_State _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
122 static Ecore_Event_Handler *_win_focus_out_handler = NULL;
123 static Ecore_Event_Handler *_conformant_change_handler = NULL;
125 static Eina_Bool _custom_conformant_event = EINA_FALSE;
126 static Eina_Bool _received_will_hide_event = EINA_FALSE;
127 static Eina_Bool _conformant_reset_done = EINA_FALSE;
128 static Eina_Bool _conformant_reset_started = EINA_FALSE;
129 static Evas *_active_context_canvas = NULL;
130 static unsigned int _active_context_window_id = 0;
132 static Ecore_Device *_ime_device = NULL;
134 static double space_key_time = 0.0;
135 static Eina_Bool autoperiod_allow = EINA_FALSE;
136 static Eina_Bool autocap_allow = EINA_FALSE;
137 static Eina_Bool hw_keyboard_mode = EINA_FALSE;
138 static Eina_Bool _preedit_cursor_changed = EINA_FALSE;
140 static Input_Language input_lang = INPUT_LANG_OTHER;
141 static Evas_Coord g_scr_w = 0, g_scr_h = 0;
143 static void set_autocapital (Ecore_IMF_Context *ctx);
145 static Eina_Bool g_key_rate_checked = EINA_FALSE, g_focused = EINA_FALSE;
146 static double g_original_key_rate = 0.0, g_original_key_delay = 0.0, g_desired_key_rate = 0.0;
149 typedef struct __LanguageInfo {
152 Eina_Unicode punc_code;
155 static LanguageInfo __language_infos [] = {
156 { "ur_PK", INPUT_LANG_URDU, 0x06D4 },
157 { "hi_IN", INPUT_LANG_HINDI, 0x0964 },
158 { "bn_IN", INPUT_LANG_BENGALI_IN, 0x0964 },
159 { "bn_BD", INPUT_LANG_BENGALI_BD, 0x0964 },
160 { "as_IN", INPUT_LANG_ASSAMESE, 0x0964 },
161 { "pa_IN", INPUT_LANG_PUNJABI, 0x0964 },
162 { "ne_NP", INPUT_LANG_NEPALI, 0x0964 },
163 { "or_IN", INPUT_LANG_ORIYA, 0x0964 },
164 { "mai_IN", INPUT_LANG_MAITHILI, 0x0964 },
165 { "hy_AM", INPUT_LANG_ARMENIAN, 0x0589 },
166 { "zh_CN", INPUT_LANG_CN, 0x3002 },
167 { "zh_HK", INPUT_LANG_CN_HK, 0x3002 },
168 { "zh_TW", INPUT_LANG_CN_TW, 0x3002 },
169 { "ja_JP", INPUT_LANG_JAPANESE, 0x3002 },
170 { "km_KH", INPUT_LANG_KHMER, 0x17D4 },
171 { "ko_KR", INPUT_LANG_KOREAN, 0x002E },
172 { "asb_IN", INPUT_LANG_ASSAMESE_BN, 0x0964 },
173 { "bna_IN", INPUT_LANG_BENGALI_AS, 0x0964 },
174 { "brx_IN", INPUT_LANG_BODO, 0x0964 },
175 { "doi_IN", INPUT_LANG_DOGRI, 0x0964 },
176 { "mni_IN", INPUT_LANG_MANIPURI, 0xabeb },
177 { "mnia_IN",INPUT_LANG_MANIPURI_AS, 0x0964 },
178 { "mnib_IN",INPUT_LANG_MANIPURI_BN, 0x0964 },
179 { "kok_IN", INPUT_LANG_KONKANI, 0x0964 },
180 { "sd_IN", INPUT_LANG_SINDHI, 0x0964 },
183 static const char *hide_keys [] = {
185 "XF86Back", // BACK_KEY
186 "XF86Stop" // OLD_BACK_KEY
189 struct _WaylandIMContext
191 Ecore_IMF_Context *ctx;
193 struct wl_text_input_manager *text_input_manager;
194 struct wl_text_input *text_input;
196 Ecore_Wl2_Window *window;
197 Ecore_Wl2_Input *input;
201 char *preedit_commit;
203 Eina_List *preedit_attrs;
204 int32_t preedit_cursor;
212 int32_t cursor_position;
222 xkb_mod_mask_t control_mask;
223 xkb_mod_mask_t alt_mask;
224 xkb_mod_mask_t shift_mask;
225 xkb_mod_mask_t caps_mask;
226 xkb_mod_mask_t num_mask;
229 uint32_t content_purpose;
230 uint32_t content_hint;
231 Ecore_IMF_Input_Panel_Layout input_panel_layout;
233 // TIZEN_ONLY(20150716): Support return key type
234 uint32_t return_key_type;
236 Eina_Bool return_key_disabled;
239 uint32_t imdata_size;
241 uint32_t bidi_direction;
243 void *input_panel_data;
244 uint32_t input_panel_data_length;
250 } last_key_event_filter;
251 Eina_List *keysym_list;
253 uint32_t reset_serial;
255 Eina_Bool has_conformant;
256 char *prediction_hint;
263 } input_panel_position;
268 Ecore_IMF_Context *ctx;
269 WaylandIMContext *imcontext;
270 } Ecore_Imf_Wayland_Imcontext_Pair;
271 Eina_List *_ecore_imf_wayland_imcontext_pair_list = NULL;
273 static void _ecore_imf_wayland_imcontext_pair_add (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
275 Ecore_Imf_Wayland_Imcontext_Pair *pair = malloc (sizeof (Ecore_Imf_Wayland_Imcontext_Pair));
278 pair->imcontext = imcontext;
280 _ecore_imf_wayland_imcontext_pair_list = eina_list_append (_ecore_imf_wayland_imcontext_pair_list, pair);
284 static Ecore_Imf_Wayland_Imcontext_Pair* _ecore_imf_wayland_imcontext_pair_find (Ecore_IMF_Context *ctx)
287 Ecore_Imf_Wayland_Imcontext_Pair *pair;
288 EINA_LIST_FOREACH (_ecore_imf_wayland_imcontext_pair_list, l, pair)
289 if (pair->ctx == ctx) {
292 LOGE("The Ecore_Imf %p if not found in Ecore_IMF-WaylandIMContext pair list!!", ctx);
296 static void _ecore_imf_wayland_imcontext_pair_del (Ecore_IMF_Context *ctx)
300 Ecore_Imf_Wayland_Imcontext_Pair *pair;
302 EINA_LIST_FOREACH_SAFE (_ecore_imf_wayland_imcontext_pair_list, l, l_next, pair)
303 if (ctx == pair->ctx) {
305 _ecore_imf_wayland_imcontext_pair_list = eina_list_remove_list (_ecore_imf_wayland_imcontext_pair_list, l);
309 static void _ecore_imf_wayland_imcontext_pair_destroy ()
311 if (_ecore_imf_wayland_imcontext_pair_list) {
312 Ecore_Imf_Wayland_Imcontext_Pair *pair;
313 EINA_LIST_FREE (_ecore_imf_wayland_imcontext_pair_list, pair)
315 _ecore_imf_wayland_imcontext_pair_list = NULL;
319 static int _ecore_imf_wayland_imcontext_pair_log ()
321 char buffer[255] = { '\0' };
324 Ecore_Imf_Wayland_Imcontext_Pair *pair;
325 EINA_LIST_FOREACH(_ecore_imf_wayland_imcontext_pair_list, l, pair) {
327 snprintf(buffer + strlen(buffer), 255 - strlen(buffer), "%s[%p/%p]", (count ? "," : ""), pair->ctx, pair->imcontext);
332 LOGD("No Ecore_Imf / Wayland_Imcontext pair found");
334 LOGD("%d Pair(s) : %s", count, buffer);
340 // TIZEN_ONLY(20150708): Support back key
341 static void _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant);
342 static Eina_Bool show_input_panel(Ecore_IMF_Context *ctx);
345 reset_keyboard_geometry ()
347 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
348 if (wl2_display && (g_scr_w == 0 || g_scr_h == 0)) {
350 ecore_wl2_display_screen_size_get(wl2_display, &g_scr_w, &g_scr_h);
352 _keyboard_geometry.x = 0;
353 _keyboard_geometry.y = g_scr_h;
354 _keyboard_geometry.w = 0;
355 _keyboard_geometry.h = 0;
359 _device_info_free (void *data EINA_UNUSED, void *ev)
361 Ecore_Event_Device_Info *e;
364 eina_stringshare_del (e->name);
365 eina_stringshare_del (e->identifier);
366 eina_stringshare_del (e->seatname);
372 _device_info_send (unsigned int window, Eina_Bool flag)
374 Ecore_Event_Device_Info *e;
376 if (!(e = calloc (1, sizeof (Ecore_Event_Device_Info)))) return;
378 e->name = eina_stringshare_ref (IME_DEVICE_NAME);
379 e->identifier = eina_stringshare_ref (IME_DEVICE_NAME);
380 e->seatname = eina_stringshare_ref (IME_DEVICE_NAME);
381 e->clas = ECORE_DEVICE_CLASS_KEYBOARD;
382 e->subclas = ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD;
386 ecore_event_add (ECORE_EVENT_DEVICE_ADD, e, _device_info_free, NULL);
388 ecore_event_add (ECORE_EVENT_DEVICE_DEL, e, _device_info_free, NULL);
392 set_input_language (const char *input_lang_str)
395 input_lang = INPUT_LANG_OTHER;
397 for (i = 0; i < (sizeof (__language_infos) / sizeof (__language_infos[0])); i++) {
398 if (strcmp (input_lang_str, __language_infos[i].code) == 0) {
399 input_lang = __language_infos[i].lang;
405 static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
407 autoperiod_allow = vconf_keynode_get_bool (key);
410 static void autocapital_allow_changed_cb (keynode_t *key, void* data)
412 autocap_allow = vconf_keynode_get_bool (key);
415 static void input_language_changed_cb (keynode_t *key, void* data)
417 char *input_lang = vconf_keynode_get_str (key);
419 set_input_language (input_lang);
420 LOGD("input lang : %s", input_lang);
425 check_symbol (Eina_Unicode ucode, Eina_Unicode symbols[], int symbol_num)
428 for (i = 0; i < symbol_num; i++) {
430 if (ucode == symbols[i])
438 check_space_symbol (Eina_Unicode uchar)
440 Eina_Unicode space_symbols[] = {' ', 0x00A0 /* no-break space */, 0x3000 /* ideographic space */};
441 const int symbol_num = sizeof (space_symbols) / sizeof (space_symbols[0]);
443 return check_symbol (uchar, space_symbols, symbol_num);
447 autoperiod_insert (Ecore_IMF_Context *ctx)
449 char *plain_str = NULL;
451 Eina_Unicode *ustr = NULL;
452 Ecore_IMF_Event_Delete_Surrounding ev;
453 char *fullstop_mark = NULL;
456 WaylandIMContext *imcontext = NULL;
458 if (autoperiod_allow == EINA_FALSE)
463 Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
464 if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
467 if ((ecore_time_get () - space_key_time) > DOUBLE_SPACE_INTERVAL)
470 imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
471 if (!imcontext) return;
473 ecore_imf_context_surrounding_get (ctx, &plain_str, NULL);
474 if (!plain_str) goto done;
476 cursor_pos = imcontext->cursor_position;
478 // Convert string from UTF-8 to unicode
479 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
480 if (!ustr) goto done;
482 ulen = eina_unicode_strlen (ustr);
484 if (cursor_pos < 2 || cursor_pos > (int)ulen) {
485 LOGD ("invalid range. cursor pos : %d, length : %zu", cursor_pos, ulen);
489 if (check_space_symbol (ustr[cursor_pos-1])) {
490 // any character (except space & punctuation) + press space key twice in short time
491 if (!(iswpunct (ustr[cursor_pos-2]) || check_space_symbol (ustr[cursor_pos-2])) &&
492 iswprint(ustr[cursor_pos-2])) {
495 // any character (except space & punctuation) + space + press space key twice in short time
496 else if (cursor_pos >= 3 &&
497 check_space_symbol (ustr[cursor_pos-2]) &&
498 !(iswpunct (ustr[cursor_pos-3]) || check_space_symbol (ustr[cursor_pos-3])) &&
499 iswprint(ustr[cursor_pos-3])) {
505 ev.n_chars = del_chars;
506 ev.offset = del_chars * -1;
508 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
510 if (input_lang == INPUT_LANG_OTHER) {
511 fullstop_mark = strdup (".");
514 Eina_Unicode wbuf[2] = {0};
515 wbuf[0] = __language_infos[input_lang].punc_code;
517 fullstop_mark = eina_unicode_unicode_to_utf8 (wbuf, NULL);
520 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)fullstop_mark);
523 free (fullstop_mark);
524 fullstop_mark = NULL;
530 if (plain_str) free (plain_str);
531 if (ustr) free (ustr);
532 space_key_time = ecore_time_get ();
536 check_except_autocapital (Eina_Unicode *ustr, int cursor_pos)
538 const char *except_str[] = {"e.g.", "E.g."};
539 unsigned int i = 0, j = 0, len = 0;
540 for (i = 0; i < (sizeof (except_str) / sizeof (except_str[0])); i++) {
541 len = strlen (except_str[i]);
542 if (cursor_pos < (int)len)
545 for (j = len; j > 0; j--) {
546 if (ustr[cursor_pos-j] != except_str[i][len-j])
550 if (j == 0) return EINA_TRUE;
557 analyze_surrounding_text (Ecore_IMF_Context *ctx)
559 char *plain_str = NULL;
560 Eina_Unicode puncs[] = {'\n','.', '!', '?', 0x00BF /* ¿ */, 0x00A1 /* ¡ */,
561 0x3002 /* 。 */, 0x06D4 /* Urdu */, 0x0964 /* Hindi */,
562 0x0589 /* Armenian */, 0x17D4 /* Khmer */, 0x104A /* Myanmar */};
563 Eina_Unicode *ustr = NULL;
564 Eina_Bool ret = EINA_FALSE;
565 Eina_Bool detect_space = EINA_FALSE;
568 const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
569 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
570 if (!imcontext) return EINA_FALSE;
572 switch (ecore_imf_context_autocapital_type_get (ctx)) {
573 case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
575 case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
581 if (imcontext->preedit_text && strcmp (imcontext->preedit_text, "") != 0)
584 if (imcontext->cursor_position == 0)
587 ecore_imf_context_surrounding_get (ctx, &plain_str, &cursor_pos);
589 if (!plain_str) goto done;
591 if (cursor_pos == 0) {
596 // Convert string from UTF-8 to unicode
597 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
598 if (!ustr) goto done;
600 if (eina_unicode_strlen (ustr) < (size_t)cursor_pos) goto done;
602 if (cursor_pos >= 1) {
603 if (ecore_imf_context_autocapital_type_get (ctx) == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
604 // Check space or no-break space
605 if (check_space_symbol (ustr[cursor_pos-1])) {
611 // Check paragraph separator <PS> or carriage return <br>
612 if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
617 for (i = cursor_pos; i > 0; i--) {
618 // Check space or no-break space
619 if (check_space_symbol (ustr[i-1])) {
620 detect_space = EINA_TRUE;
624 // Check punctuation and following the continuous space(s)
625 if (detect_space && check_symbol (ustr[i-1], puncs, punc_num)) {
626 if (check_except_autocapital (ustr, i))
638 if ((i == 0) && (detect_space == EINA_TRUE)) {
639 // continuous space(s) without any character
646 if (ustr) free (ustr);
647 if (plain_str) free (plain_str);
653 set_autocapital (Ecore_IMF_Context *ctx)
655 Eina_Bool uppercase = EINA_FALSE;
657 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
658 if (!imcontext || !imcontext->text_input || !imcontext->input) return;
660 if (hw_keyboard_mode) return;
662 if (ecore_imf_context_input_panel_layout_get (ctx) != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
665 // Check autocapital type
666 if (ecore_imf_context_input_panel_caps_lock_mode_get (ctx)) {
667 uppercase = EINA_TRUE;
669 if (autocap_allow == EINA_FALSE)
672 uppercase = analyze_surrounding_text (ctx);
675 LOGD ("ctx : %p, auto capital : %d", ctx, uppercase);
676 wl_text_input_set_capital_mode (imcontext->text_input, uppercase);
679 static Ecore_IMF_Context *
682 return (_show_req_ctx ? _show_req_ctx : _focused_ctx);
686 check_hide_key(const char *keyname)
688 if (!keyname) return EINA_FALSE;
691 for (i = 0; i < (sizeof(hide_keys) / sizeof(hide_keys[0])); i++) {
692 if (strcmp(keyname, hide_keys[i]) == 0) {
701 _ecore_key_modifiers_to_ecore_imf_locks(unsigned int modifiers)
703 unsigned int locks = 0;
705 if (modifiers & ECORE_EVENT_LOCK_SCROLL)
706 locks |= ECORE_IMF_KEYBOARD_LOCK_SCROLL;
708 if (modifiers & ECORE_EVENT_LOCK_CAPS)
709 locks |= ECORE_IMF_KEYBOARD_LOCK_CAPS;
711 if (modifiers & ECORE_EVENT_LOCK_NUM)
712 locks |= ECORE_IMF_KEYBOARD_LOCK_NUM;
718 _ecore_key_modifiers_to_ecore_imf_modifiers(unsigned int modifiers)
720 unsigned int mask = 0;
722 /**< "Control" is pressed */
723 if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
724 mask |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
726 /**< "Alt" is pressed */
727 if (modifiers & ECORE_EVENT_MODIFIER_ALT)
728 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
730 /**< "Shift" is pressed */
731 if (modifiers & ECORE_EVENT_MODIFIER_SHIFT)
732 mask |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT;
734 /**< "Win" (between "Ctrl" and "Alt") is pressed */
735 if (modifiers & ECORE_EVENT_MODIFIER_WIN)
736 mask |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
738 /**< "AltGr" is pressed */
739 if (modifiers & ECORE_EVENT_MODIFIER_ALTGR)
740 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
746 _ecore_event_to_ecore_imf_key_down_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Down *imf_event)
748 if (!ecore_event || !imf_event)
751 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
752 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
753 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
754 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
755 imf_event->timestamp = ecore_event->timestamp;
757 if (ecore_event->dev) {
758 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
759 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
760 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
763 imf_event->dev_name = _ecore_imf_event_empty;
764 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
765 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
768 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
769 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
773 _ecore_event_to_ecore_imf_key_up_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Up *imf_event)
775 if (!ecore_event || !imf_event)
778 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
779 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
780 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
781 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
782 imf_event->timestamp = ecore_event->timestamp;
784 if (ecore_event->dev) {
785 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
786 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
787 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
790 imf_event->dev_name = _ecore_imf_event_empty;
791 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
792 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
795 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
796 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
799 static Eina_Bool check_nograb_backkey()
801 char *nograb_backkey = getenv ("ISF_KEY_NOGRAB_BACKKEY");
802 if (nograb_backkey) {
803 if (atoi (nograb_backkey) != 0)
804 return EINA_TRUE; /* the event is kept */
811 key_down_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
813 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
814 if (!ev || !ev->keyname) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
816 Ecore_IMF_Context *active_ctx = get_using_ctx ();
818 if (!active_ctx) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
820 if (check_nograb_backkey()) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
822 if ((_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW ||
823 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW) &&
824 check_hide_key(ev->keyname)) {
826 if (ev->event_flags & ECORE_EVENT_FLAG_CANCEL) {
827 SECURE_LOGD ("%s key is cancelled.", ev->keyname);
828 return ECORE_CALLBACK_PASS_ON;
831 SECURE_LOGD ("%s key is pressed.", ev->keyname);
833 Ecore_IMF_Event_Key_Down imf_event;
834 Eina_Bool filter_ret = EINA_FALSE;
836 _ecore_event_to_ecore_imf_key_down_event(ev, &imf_event);
839 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_DOWN, (Ecore_IMF_Event *)&imf_event);
843 SECURE_LOGD ("%s key is pressed. ret : %d", ev->keyname, filter_ret);
844 return ECORE_CALLBACK_DONE; /* the event is removed from the queue */
846 return ECORE_CALLBACK_PASS_ON; /* the event is kept */
850 key_up_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
852 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
853 if (!ev || !ev->keyname) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
855 Ecore_IMF_Context *active_ctx = get_using_ctx ();
857 if (!active_ctx) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
859 if (check_nograb_backkey()) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
861 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE ||
862 !check_hide_key(ev->keyname))
863 return ECORE_CALLBACK_PASS_ON; /* the event is kept */
865 if (ev->event_flags & ECORE_EVENT_FLAG_CANCEL) {
866 SECURE_LOGD ("%s key is cancelled.", ev->keyname);
867 return ECORE_CALLBACK_PASS_ON;
870 SECURE_LOGD ("%s key is released.", ev->keyname);
872 Ecore_IMF_Event_Key_Up imf_event;
873 Eina_Bool filter_ret = EINA_FALSE;
875 _ecore_event_to_ecore_imf_key_up_event(ev, &imf_event);
878 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_UP, (Ecore_IMF_Event *)&imf_event);
882 SECURE_LOGD ("%s key is released. ret : %d", ev->keyname, filter_ret);
884 return ECORE_CALLBACK_DONE; /* the event is removed from the queue */
887 ecore_imf_context_reset(active_ctx);
888 _input_panel_hide(active_ctx, EINA_TRUE);
889 return ECORE_CALLBACK_DONE; /* the event is removed from the queue */
894 rotary_event_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
896 Ecore_Event_Detent_Rotate *ev = event;
897 if (!ev) return ECORE_CALLBACK_PASS_ON;
899 Ecore_IMF_Context *active_ctx = NULL;
901 active_ctx = _show_req_ctx;
902 else if (_focused_ctx)
903 active_ctx = _focused_ctx;
905 if (!active_ctx) return ECORE_CALLBACK_PASS_ON;
907 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
908 return ECORE_CALLBACK_PASS_ON;
910 ecore_imf_context_reset(active_ctx);
911 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(active_ctx);
912 if (imcontext && imcontext->input && imcontext->text_input) {
913 isf_device_type_e device_type = find_device_type_from_ecore_event(ECORE_EVENT_DETENT_ROTATE);
917 if (device_buffer_encode((const char*)(event), sizeof(Ecore_Event_Detent_Rotate), &buffer, &buflen) &&
918 buffer && buflen > 0) {
919 wl_text_input_process_input_device_event(imcontext->text_input,
920 (unsigned int)device_type, buffer, buflen);
922 if (buffer) free(buffer);
925 return ECORE_CALLBACK_DONE;
929 _ecore_event_filter_cb(void *data, void *loop_data EINA_UNUSED, int type, void *event)
931 if (type == ECORE_EVENT_KEY_DOWN) {
932 return key_down_filter_cb(data, type, event);
934 else if (type == ECORE_EVENT_KEY_UP) {
935 return key_up_filter_cb(data, type, event);
937 /* The IME needs to process Rotary event prior to client application */
938 else if (type == ECORE_EVENT_DETENT_ROTATE) {
939 return rotary_event_cb(data, type, event);
942 return ECORE_CALLBACK_PASS_ON;
946 register_key_handler()
948 if (!_ecore_event_filter_handler)
949 _ecore_event_filter_handler = ecore_event_filter_add(NULL, _ecore_event_filter_cb, NULL, NULL);
953 unregister_key_handler()
955 if (_ecore_event_filter_handler) {
956 ecore_event_filter_del(_ecore_event_filter_handler);
957 _ecore_event_filter_handler = NULL;
968 LOGD("Delete hide timer");
969 ecore_timer_del(_hide_timer);
977 static void _win_focus_out_handler_del ()
979 if (_win_focus_out_handler) {
980 ecore_event_handler_del (_win_focus_out_handler);
981 _win_focus_out_handler = NULL;
985 static void _conformant_change_handler_del()
987 if (_conformant_change_handler) {
988 ecore_event_handler_del(_conformant_change_handler);
989 _conformant_change_handler = NULL;
994 _send_input_panel_hide_request(Ecore_IMF_Context *ctx)
998 // TIZEN_ONLY(20150708): Support back key
999 _hide_req_ctx = NULL;
1002 _win_focus_out_handler_del ();
1004 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1005 if (imcontext && imcontext->text_input) {
1006 LOGD("Send IME hide request");
1007 wl_text_input_hide_input_panel(imcontext->text_input);
1009 LOGD("creating temporary context for sending hide request");
1010 const char *ctx_id = ecore_imf_context_default_id_get();
1011 Ecore_IMF_Context *temp_context = ecore_imf_context_add(ctx_id);
1013 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(temp_context);
1014 if (imcontext && imcontext->text_input) {
1015 LOGD("Send IME hide request");
1016 wl_text_input_hide_input_panel(imcontext->text_input);
1019 ecore_imf_context_del(temp_context);
1024 static void _conformant_area_free (void *data EINA_UNUSED, void *ev)
1026 Ecore_Wl2_Event_Conformant_Change *e = ev;
1031 static void add_conformant_change_event(Ecore_Wl2_Window *window)
1033 Ecore_Wl2_Event_Conformant_Change *ev;
1034 ev = calloc(1, sizeof(Ecore_Wl2_Event_Conformant_Change));
1036 ev->win = ecore_wl2_window_id_get(window);
1039 ecore_event_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, ev, _conformant_area_free, NULL);
1043 static Eina_Rectangle _conformant_area_backup = { 0, 0, 0, 0 };
1044 static Eina_Bool reset_conformant_area(Ecore_IMF_Context *ctx)
1046 Eina_Bool reset = EINA_FALSE;
1047 Eina_Bool has_conformant = EINA_FALSE;
1048 Ecore_Wl2_Window *window = NULL;
1050 if (!ctx) return EINA_FALSE;
1052 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1054 window = imcontext->window;
1055 has_conformant = imcontext->has_conformant;
1059 int x = 0, y = 0, w = 0, h = 0;
1060 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1063 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w != 0 || h != 0)) {
1065 _conformant_area_backup.x = x;
1066 _conformant_area_backup.y = y;
1067 _conformant_area_backup.w = w;
1068 _conformant_area_backup.h = h;
1072 LOGD("reset %d", reset);
1074 ecore_wl2_window_keyboard_geometry_set(window, 0, 0, 0, 0);
1076 add_conformant_change_event(window);
1078 _conformant_reset_started = EINA_TRUE;
1084 static void restore_conformant_area(Ecore_IMF_Context *ctx)
1086 Eina_Bool restore = EINA_FALSE;
1087 Eina_Bool has_conformant = EINA_FALSE;
1088 Ecore_Wl2_Window *window = NULL;
1092 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1094 window = imcontext->window;
1095 has_conformant = imcontext->has_conformant;
1099 int x = 0, y = 0, w = 0, h = 0;
1100 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1103 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w == 0 || h == 0)) {
1104 restore = EINA_TRUE;
1108 LOGD("restore %d", restore);
1110 ecore_wl2_window_keyboard_geometry_set(window,
1111 _conformant_area_backup.x, _conformant_area_backup.y,
1112 _conformant_area_backup.w, _conformant_area_backup.h);
1114 add_conformant_change_event(window);
1116 _conformant_reset_started = EINA_FALSE;
1121 _send_will_hide_ack(WaylandIMContext *imcontext)
1123 if (!imcontext) return;
1124 if (!(imcontext->text_input)) return;
1126 const char *szWillHideAck = "WILL_HIDE_ACK";
1127 wl_text_input_set_input_panel_data(imcontext->text_input, szWillHideAck, strlen(szWillHideAck));
1128 _received_will_hide_event = EINA_FALSE;
1132 _hide_timer_handler(void *data)
1134 LOGD("Start hide timer");
1135 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1136 _send_input_panel_hide_request(ctx);
1138 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1139 LOGD("No need to reset conformant, sending ACK right away");
1140 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1144 reset_keyboard_geometry();
1147 return ECORE_CALLBACK_CANCEL;
1151 _input_panel_hide_timer_start(void *data)
1154 LOGD("Add timer to hide input panel");
1155 _hide_timer = ecore_timer_add(HIDE_TIMER_INTERVAL, _hide_timer_handler, data);
1160 _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant)
1162 LOGD ("ctx : %p", ctx);
1166 will_hide = EINA_TRUE;
1167 _conformant_reset_started = EINA_FALSE;
1169 if (instant || (_hide_timer && ecore_timer_pending_get(_hide_timer) <= 0.0)) {
1170 _clear_hide_timer();
1171 _send_input_panel_hide_request(ctx);
1173 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1174 LOGD("No need to reset conformant, sending ACK right away");
1175 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1179 reset_keyboard_geometry();
1181 _input_panel_hide_timer_start(ctx);
1182 // TIZEN_ONLY(20150708): Support back key
1183 _hide_req_ctx = ctx;
1189 utf8_offset_to_characters(const char *str, int offset)
1194 for (; index < offset; i++) {
1195 if (eina_unicode_utf8_next_get(str, &index) == 0)
1203 send_cursor_location(WaylandIMContext *imcontext)
1205 #if ENABLE_SEND_CURSOR_LOCATION
1206 Ecore_Evas *ee = NULL;
1207 int canvas_x = 0, canvas_y = 0;
1209 if (imcontext->canvas) {
1210 ee = ecore_evas_ecore_evas_get(imcontext->canvas);
1212 ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
1215 if (imcontext->input && imcontext->text_input) {
1216 wl_text_input_set_cursor_rectangle(imcontext->text_input,
1217 imcontext->cursor_location.x + canvas_x,
1218 imcontext->cursor_location.y + canvas_y,
1219 imcontext->cursor_location.width,
1220 imcontext->cursor_location.height);
1226 update_state(WaylandIMContext *imcontext)
1228 if (!imcontext->ctx)
1231 send_cursor_location (imcontext);
1233 if (imcontext->input && imcontext->text_input) {
1234 wl_text_input_commit_state(imcontext->text_input, ++imcontext->serial);
1239 check_serial(WaylandIMContext *imcontext, uint32_t serial)
1244 Ecore_IMF_Preedit_Attr *attr;
1246 if ((imcontext->serial - serial) >
1247 (imcontext->serial - imcontext->reset_serial)) {
1248 LOGD("outdated serial: %u, current: %u, reset: %u",
1249 serial, imcontext->serial, imcontext->reset_serial);
1251 imcontext->pending_preedit.cursor = 0;
1253 if (imcontext->pending_preedit.attrs) {
1254 EINA_LIST_FREE(imcontext->pending_preedit.attrs, attr) {
1258 imcontext->pending_preedit.attrs = NULL;
1269 clear_preedit_text(WaylandIMContext *imcontext)
1271 Ecore_IMF_Preedit_Attr *attr = NULL;
1273 imcontext->preedit_cursor = 0;
1275 if (imcontext->preedit_text) {
1276 free(imcontext->preedit_text);
1277 imcontext->preedit_text = NULL;
1280 if (imcontext->preedit_attrs) {
1281 EINA_LIST_FREE(imcontext->preedit_attrs, attr) {
1287 imcontext->preedit_attrs = NULL;
1291 clear_preedit(WaylandIMContext *imcontext)
1293 clear_preedit_text(imcontext);
1295 if (imcontext->preedit_commit) {
1296 free(imcontext->preedit_commit);
1297 imcontext->preedit_commit = NULL;
1302 text_input_commit_string(void *data,
1303 struct wl_text_input *text_input EINA_UNUSED,
1307 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1308 Eina_Bool old_preedit = EINA_FALSE;
1310 SECURE_LOGD("ctx : %p, commit event (text: '%s', current pre-edit: '%s')",
1313 imcontext->preedit_text ? imcontext->preedit_text : "");
1315 if (!imcontext->ctx)
1319 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1321 if (!check_serial(imcontext, serial))
1325 ecore_imf_context_event_callback_call(imcontext->ctx,
1326 ECORE_IMF_CALLBACK_PREEDIT_END,
1330 clear_preedit(imcontext);
1335 Eina_Unicode *ustr = eina_unicode_utf8_to_unicode (text, NULL);
1338 if (eina_unicode_strcmp (ustr, L" ") == 0 ||
1339 eina_unicode_strcmp (ustr, L" ") == 0)
1340 autoperiod_insert (imcontext->ctx);
1345 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)text);
1349 commit_preedit(WaylandIMContext *imcontext)
1351 if (!imcontext->preedit_commit)
1354 if (!imcontext->ctx)
1357 imcontext->pending_preedit.cursor = 0;
1358 clear_preedit_text(imcontext);
1360 size_t commit_len = strlen(imcontext->preedit_commit);
1362 if (commit_len == 0) {
1363 ecore_imf_context_event_callback_call(imcontext->ctx,
1364 ECORE_IMF_CALLBACK_PREEDIT_START,
1367 ecore_imf_context_event_callback_call(imcontext->ctx,
1368 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1371 ecore_imf_context_event_callback_call(imcontext->ctx,
1372 ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
1375 if (commit_len > 0) {
1376 char *commit_str = NULL;
1377 commit_str = strdup(imcontext->preedit_commit);
1378 clear_preedit(imcontext);
1379 ecore_imf_context_event_callback_call(imcontext->ctx,
1380 ECORE_IMF_CALLBACK_COMMIT,
1381 (void *)commit_str);
1387 set_focus(Ecore_IMF_Context *ctx)
1389 LOGD("ctx : %p", ctx);
1390 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1391 if (!imcontext) return EINA_FALSE;
1393 if (!imcontext->window) {
1394 LOGW("window is not given");
1398 if (imcontext->canvas) {
1399 if (!evas_focus_state_get(imcontext->canvas)) {
1400 LOGW("ctx : %p, canvas does not have focus", ctx);
1404 else if (!ecore_wl2_window_activated_get(imcontext->window)) {
1405 LOGW("ctx : %p, window does not have focus", ctx);
1409 Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
1411 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1415 struct wl_seat *seat = ecore_wl2_input_seat_get(input);
1417 LOGW("ctx : %p, Can't get Wl_seat", ctx);
1421 imcontext->input = input;
1424 wl_text_input_activate(imcontext->text_input, seat,
1425 ecore_wl2_window_surface_get(imcontext->window));
1427 if (g_key_rate_checked == EINA_FALSE && g_desired_key_rate == 0.0) {
1428 char *key_rate = getenv ("ISF_KEY_REPEAT_RATE");
1430 g_desired_key_rate = atof (key_rate);
1431 if (g_desired_key_rate > 0.0) {
1432 if (!ecore_wl2_input_keyboard_repeat_get (input, &g_original_key_rate, &g_original_key_delay)) {
1433 LOGE ("ecore_wl2_input_keyboard_repeat_get failed");
1436 LOGD ("ecore_wl2_input_keyboard_repeat_get original rate=%f, delay=%f. Desired rate=%f",
1437 g_original_key_rate, g_original_key_delay, g_desired_key_rate);
1441 g_key_rate_checked = EINA_TRUE;
1444 if (g_desired_key_rate > 0.0 && g_original_key_delay > 0.0 && !g_focused) {
1445 g_focused = EINA_TRUE;
1446 if (!ecore_wl2_input_keyboard_repeat_set (input, g_desired_key_rate, g_original_key_delay)) {
1447 LOGE ("ecore_wl2_input_keyboard_repeat_set failed");
1450 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_desired_key_rate, g_original_key_delay);
1458 set_focus_out(Ecore_IMF_Context *ctx)
1460 char *surrounding = NULL;
1463 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1464 if (!imcontext || !imcontext->input) return;
1466 if (ecore_imf_context_surrounding_get(ctx, &surrounding, &cursor_pos)) {
1468 wl_text_input_finalize_content(imcontext->text_input, surrounding, cursor_pos);
1474 if (imcontext->text_input)
1475 wl_text_input_deactivate(imcontext->text_input,
1476 ecore_wl2_input_seat_get(imcontext->input));
1478 if (ctx == _focused_ctx)
1479 _focused_ctx = NULL;
1481 imcontext->input = NULL;
1482 _preedit_cursor_changed = EINA_FALSE;
1484 if (g_desired_key_rate > 0.0 && g_focused) {
1485 g_focused = EINA_FALSE;
1487 Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
1489 if (!ecore_wl2_input_keyboard_repeat_set (input, g_original_key_rate, g_original_key_delay)) {
1490 LOGE ("ecore_wl2_input_keyboard_repeat_set failed.");
1493 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_original_key_rate, g_original_key_delay);
1497 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1502 // TIZEN_ONLY(20160217): ignore the duplicate show request
1503 static Eina_Bool _compare_context(Ecore_IMF_Context *ctx1, Ecore_IMF_Context *ctx2)
1505 if (!ctx1 || !ctx2) return EINA_FALSE;
1507 if ((ecore_imf_context_autocapital_type_get(ctx1) == ecore_imf_context_autocapital_type_get(ctx2)) &&
1508 (ecore_imf_context_input_panel_layout_get(ctx1) == ecore_imf_context_input_panel_layout_get(ctx2)) &&
1509 (ecore_imf_context_input_panel_layout_variation_get(ctx1) == ecore_imf_context_input_panel_layout_variation_get(ctx2)) &&
1510 (ecore_imf_context_input_panel_language_get(ctx1) == ecore_imf_context_input_panel_language_get(ctx2)) &&
1511 (ecore_imf_context_input_panel_return_key_type_get(ctx1) == ecore_imf_context_input_panel_return_key_type_get(ctx2)) &&
1512 (ecore_imf_context_input_panel_return_key_disabled_get(ctx1) == ecore_imf_context_input_panel_return_key_disabled_get(ctx2)) &&
1513 (ecore_imf_context_input_panel_caps_lock_mode_get(ctx1) == ecore_imf_context_input_panel_caps_lock_mode_get(ctx2)))
1520 static void send_get_hide_permission(WaylandIMContext *imcontext)
1522 if (imcontext->text_input) {
1523 ignore_hide = EINA_FALSE;
1524 wl_text_input_get_hide_permission(imcontext->text_input);
1528 static Eina_Bool _client_window_focus_out_cb(void *data, int ev_type, void *ev)
1530 Ecore_Wl2_Event_Focus_Out *e = (Ecore_Wl2_Event_Focus_Out *)ev;
1531 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1532 if (!ctx || !e) return ECORE_CALLBACK_PASS_ON;
1534 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
1535 if (!imcontext || !imcontext->window) return ECORE_CALLBACK_PASS_ON;
1537 unsigned int client_win_id = ecore_wl2_window_id_get (imcontext->window);
1539 LOGD ("ctx : %p, client_window id : %#x, focus-out win : %#x", ctx, client_win_id, e->window);
1541 if (client_win_id > 0) {
1542 if (e->window == client_win_id) {
1543 LOGD ("window focus out");
1545 if (_focused_ctx == ctx) {
1546 wayland_im_context_focus_out (ctx);
1549 if (_show_req_ctx == ctx) {
1550 send_get_hide_permission(imcontext);
1555 send_get_hide_permission(imcontext);
1558 return ECORE_CALLBACK_PASS_ON;
1561 static void send_will_hide_ack(Ecore_IMF_Context *ctx)
1563 Eina_Bool need_temporary_context = EINA_FALSE;
1564 Eina_Bool has_conformant = EINA_FALSE;
1565 WaylandIMContext *imcontext = NULL;
1568 LOGD("ctx is NULL");
1569 need_temporary_context = EINA_TRUE;
1571 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1573 LOGD("imcontext is NULL :%p", ctx);
1574 need_temporary_context = EINA_TRUE;
1576 has_conformant = imcontext->has_conformant;
1580 /* When the RENDER_POST event is emitted, it is possible that our IMF_Context is already deleted,
1581 meaning that there is no connection available for communicating with the window manager.
1582 So we are creating a temporary context for sending WILL_HIDE_ACK message */
1583 if (need_temporary_context) {
1584 LOGD("creating temporary context for sending WILL_HIDE_ACK");
1585 const char *ctx_id = ecore_imf_context_default_id_get();
1586 ctx = ecore_imf_context_add(ctx_id);
1588 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1592 if (ctx && imcontext) {
1593 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant) {
1594 if (_conformant_reset_done && _received_will_hide_event) {
1595 LOGD("Send will hide ack, _conformant_reset_done = 1, received_will_hide_event = 1");
1596 _send_will_hide_ack(imcontext);
1597 _conformant_reset_done = EINA_FALSE;
1598 _received_will_hide_event = EINA_FALSE;
1600 LOGD ("_conformant_reset_done=%d, received_will_hide_event=%d",
1601 _conformant_reset_done, _received_will_hide_event);
1604 LOGD("Send will hide ack right away, since there is no conformant available : %p %d",
1605 ecore_imf_context_client_canvas_get(ctx), has_conformant);
1606 _send_will_hide_ack (imcontext);
1610 if (need_temporary_context) {
1612 ecore_imf_context_del(ctx);
1617 static void _render_post_cb(void *data, Evas *e, void *event_info)
1619 void *callback = evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1620 _conformant_reset_done = EINA_TRUE;
1621 _conformant_reset_started = EINA_FALSE;
1622 LOGD("[_render_post_cb], _conformant_reset_done = 1 , %p", callback);
1623 send_will_hide_ack(NULL);
1626 static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
1628 Ecore_Wl2_Event_Conformant_Change *e = (Ecore_Wl2_Event_Conformant_Change *)ev;
1629 if (!e) return ECORE_CALLBACK_PASS_ON;
1631 LOGD ("CONFORMANT changed!! part type : %d, state : %d, win : %d", e->part_type, e->state, e->win);
1633 if (_active_context_window_id != e->win)
1634 return ECORE_CALLBACK_PASS_ON;
1636 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1637 if (!wl2_display) return ECORE_CALLBACK_PASS_ON;
1639 Ecore_Wl2_Window *window = ecore_wl2_display_window_find(wl2_display, e->win);
1640 if (!window) return ECORE_CALLBACK_PASS_ON;
1643 LOGD("_conformant_reset_done = 0, registering _render_post_cb : %p %p", _active_context_canvas, window);
1644 _conformant_reset_done = EINA_FALSE;
1645 if (_active_context_canvas && ecore_wl2_window_conformant_get(window) && !_custom_conformant_event) {
1646 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1647 evas_event_callback_add(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb, NULL);
1650 _conformant_reset_done = EINA_FALSE;
1651 if (_active_context_canvas) {
1652 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1655 Eina_Bool result = EINA_FALSE;
1656 int x = 0, y = 0, w = 0, h = 0;
1659 /* TV IME consists of two or three windows, so ecore_wl2_window_keyboard_geometry_get() may return wrong size. */
1660 x = _keyboard_geometry.x, y = _keyboard_geometry.y, w = _keyboard_geometry.w, h = _keyboard_geometry.h;
1661 if (_keyboard_geometry.w == 0 || _keyboard_geometry.h == 0) {
1662 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1665 /* Since the input_panel_geometry is not delivered right at the moment, we use conformant geometry instead */
1666 x = 0, y = 0, w = 0, h = 0;
1667 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1671 Evas_Coord scr_w = 0, scr_h = 0;
1673 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1675 ecore_wl2_display_screen_size_get(wl2_display ,&scr_w, &scr_h);
1676 int rot = ecore_wl2_window_rotation_get(window);
1677 /* Assume we are using keyboard that has the same width to the screen width*/
1680 _keyboard_geometry.h = w;
1681 _keyboard_geometry.w = h;
1682 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1683 _keyboard_geometry.x = 0;
1686 _keyboard_geometry.w = w;
1687 _keyboard_geometry.h = h;
1688 _keyboard_geometry.x = 0;
1689 _keyboard_geometry.y = scr_h - _keyboard_geometry.h;
1692 _keyboard_geometry.h = w;
1693 _keyboard_geometry.w = h;
1694 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1695 _keyboard_geometry.x = 0;
1698 _keyboard_geometry.x = x;
1699 _keyboard_geometry.y = y;
1700 _keyboard_geometry.w = w;
1701 _keyboard_geometry.h = h;
1703 LOGD("[KEYPAD]: scr %dx%d, rot %d, orig (%d,%d, %dx%d)", scr_w, scr_h, rot, x, y, w, h);
1704 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
1707 ecore_imf_context_input_panel_event_callback_call(_show_req_ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
1711 return ECORE_CALLBACK_PASS_ON;
1715 get_purpose(Ecore_IMF_Context *ctx)
1717 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1718 uint32_t new_purpose = 0;
1720 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1724 switch (imcontext->content_purpose) {
1725 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
1726 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED)
1727 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED;
1728 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL)
1729 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL;
1730 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL)
1731 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL;
1733 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
1735 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
1736 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY)
1737 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS;
1739 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
1741 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
1742 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME)
1743 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME;
1744 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME)
1745 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NAME;
1747 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
1750 new_purpose = imcontext->content_purpose;
1757 static void _canvas_focus_in_cb(void *data, Evas *e, void *event_info)
1759 LOGD("ctx : %p %d", _focus_req_ctx, _focus_req_only);
1761 if (_focus_req_ctx) {
1762 set_focus(_focus_req_ctx);
1763 if (ecore_imf_context_input_panel_enabled_get (_focus_req_ctx) || !_focus_req_only)
1764 if (!ecore_imf_context_input_panel_show_on_demand_get (_focus_req_ctx) || !_focus_req_only)
1765 show_input_panel (_focus_req_ctx);
1767 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(_focus_req_ctx);
1768 if (imcontext && imcontext->canvas)
1769 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1770 _focus_req_ctx = NULL;
1771 _focus_req_only = EINA_TRUE;
1776 show_input_panel(Ecore_IMF_Context *ctx)
1778 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1780 char *surrounding = NULL;
1783 if ((!imcontext) || (!imcontext->text_input))
1786 if (!imcontext->input) {
1788 if (!imcontext->input) {
1789 _focus_req_ctx = ctx;
1790 _focus_req_only = EINA_FALSE;
1791 if (imcontext->canvas) {
1792 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1793 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
1798 _clear_hide_timer ();
1800 _win_focus_out_handler_del ();
1802 if (!imcontext->input)
1805 ignore_hide = EINA_TRUE;
1807 _win_focus_out_handler = ecore_event_handler_add (ECORE_WL2_EVENT_FOCUS_OUT, _client_window_focus_out_cb, ctx);
1808 _conformant_change_handler_del ();
1809 _conformant_change_handler = ecore_event_handler_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, _conformant_change_cb, NULL);
1811 // TIZEN_ONLY(20160217): ignore the duplicate show request
1812 if ((_show_req_ctx == ctx) && _compare_context(_show_req_ctx, ctx) && (!will_hide)) {
1813 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW ||
1814 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
1815 LOGD("already show. ctx : %p", ctx);
1821 will_hide = EINA_FALSE;
1822 _show_req_ctx = ctx;
1823 _input_panel_ctx = ctx;
1824 _active_context_canvas = ecore_imf_context_client_canvas_get(ctx);
1828 // TIZEN_ONLY(20150715): Support input_panel_state_get
1829 int layout = ecore_imf_context_input_panel_layout_get (ctx);
1830 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1833 if (layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
1834 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
1836 wl_text_input_set_content_type(imcontext->text_input,
1837 imcontext->content_hint,
1840 if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos)) {
1841 SECURE_LOGD ("surrounding text : %s", surrounding);
1845 imcontext->cursor_position = cursor_pos;
1846 wl_text_input_set_cursor_position(imcontext->text_input, cursor_pos);
1848 // TIZEN_ONLY(20150716): Support return key type
1849 wl_text_input_set_return_key_type(imcontext->text_input,
1850 imcontext->return_key_type);
1852 wl_text_input_set_return_key_disabled(imcontext->text_input,
1853 imcontext->return_key_disabled);
1855 if (imcontext->imdata_size > 0)
1856 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
1858 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
1860 set_autocapital (ctx);
1862 if (imcontext->mime_type)
1863 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
1865 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
1866 wl_text_input_set_input_panel_position(imcontext->text_input,
1867 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
1869 LOGD ("ctx : %p, layout : %d, layout variation : %d, language : %d, cursor position : %d",
1870 ctx, layout, layout_variation,
1871 ecore_imf_context_input_panel_language_get (ctx),
1873 LOGD ("input hint : %#x, bidi direction : %d, return key type : %d, return key disabled : %d, autocapital type : %d",
1874 ecore_imf_context_input_hint_get (ctx),
1875 imcontext->bidi_direction,
1876 ecore_imf_context_input_panel_return_key_type_get (ctx),
1877 ecore_imf_context_input_panel_return_key_disabled_get (ctx),
1878 ecore_imf_context_autocapital_type_get (ctx));
1879 LOGD ("client_window : %#lx, Ecore_Wl2_Window : %p, password mode : %d, prediction_allow : %d, mime_type : %s, input panel position x : %d, y : %d",
1880 (unsigned long int)ecore_imf_context_client_window_get (ctx),
1882 (imcontext->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) ? 1 : 0,
1883 ecore_imf_context_prediction_allow_get (ctx),
1884 imcontext->mime_type,
1885 imcontext->input_panel_position.x,
1886 imcontext->input_panel_position.y);
1888 if (_active_context_canvas && !evas_focus_state_get (_active_context_canvas)) {
1889 LOGW ("Canvas does not have focus!");
1893 if (hw_keyboard_mode) {
1894 LOGD("hw_keyboard_mode is TRUE, returning");
1898 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
1900 wl_text_input_show_input_panel(imcontext->text_input);
1902 if (imcontext->window) {
1903 _active_context_window_id = ecore_wl2_window_id_get(imcontext->window);
1904 imcontext->has_conformant = ecore_wl2_window_conformant_get(imcontext->window);
1906 imcontext->has_conformant = EINA_FALSE;
1912 static void delete_surrounding_text(WaylandIMContext *imcontext, int index, int length)
1914 Ecore_IMF_Event_Delete_Surrounding ev;
1915 LOGD("delete surrounding text (index: %d, length: %u)",
1919 ev.n_chars = length;
1921 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
1925 text_input_preedit_string(void *data,
1926 struct wl_text_input *text_input EINA_UNUSED,
1931 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1932 Eina_Bool old_preedit = EINA_FALSE;
1933 Eina_Bool preedit_changed = EINA_FALSE;
1935 SECURE_LOGD("ctx : %p, preedit event (text: '%s', current pre-edit: '%s')",
1938 imcontext->preedit_text ? imcontext->preedit_text : "");
1940 if (!check_serial(imcontext, serial))
1944 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1946 if (imcontext->preedit_text)
1947 preedit_changed = (strcmp(imcontext->preedit_text, text) != 0);
1949 preedit_changed = (strlen(text) != 0);
1951 if (_preedit_cursor_changed) {
1952 preedit_changed = EINA_TRUE;
1953 _preedit_cursor_changed = EINA_FALSE;
1956 if (imcontext->pending_preedit.attrs)
1957 preedit_changed = EINA_TRUE;
1959 clear_preedit(imcontext);
1961 imcontext->preedit_text = strdup(text);
1962 imcontext->preedit_commit = (strlen(text) > 0 ? strdup(commit) : NULL);
1963 imcontext->preedit_cursor =
1964 utf8_offset_to_characters(text, imcontext->pending_preedit.cursor);
1965 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
1967 imcontext->pending_preedit.attrs = NULL;
1969 if (preedit_changed) {
1971 ecore_imf_context_event_callback_call(imcontext->ctx,
1972 ECORE_IMF_CALLBACK_PREEDIT_START,
1976 ecore_imf_context_event_callback_call(imcontext->ctx,
1977 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1980 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
1981 ecore_imf_context_event_callback_call(imcontext->ctx,
1982 ECORE_IMF_CALLBACK_PREEDIT_END,
1989 text_input_delete_surrounding_text(void *data,
1990 struct wl_text_input *text_input EINA_UNUSED,
1994 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1995 delete_surrounding_text(imcontext, index, length);
1999 text_input_cursor_position(void *data EINA_UNUSED,
2000 struct wl_text_input *text_input EINA_UNUSED,
2004 LOGD("cursor_position for next commit (index: %d, anchor: %d)",
2009 text_input_preedit_styling(void *data,
2010 struct wl_text_input *text_input EINA_UNUSED,
2015 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2016 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
2021 case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
2022 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_NONE;
2024 case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
2025 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
2027 case WL_TEXT_INPUT_PREEDIT_STYLE_REVERSE:
2028 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
2030 case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
2031 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
2033 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR1:
2034 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
2036 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR2:
2037 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
2039 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR3:
2040 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
2042 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR4:
2043 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
2046 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
2050 attr->start_index = index;
2051 attr->end_index = index + length;
2053 imcontext->pending_preedit.attrs =
2054 eina_list_append(imcontext->pending_preedit.attrs, attr);
2058 text_input_preedit_cursor(void *data,
2059 struct wl_text_input *text_input EINA_UNUSED,
2062 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2064 LOGD("preedit cursor : %d", index);
2066 if (imcontext->pending_preedit.cursor != index) {
2067 imcontext->pending_preedit.cursor = index;
2068 _preedit_cursor_changed = EINA_TRUE;
2072 static xkb_mod_index_t
2073 modifiers_get_index(struct wl_array *modifiers_map, const char *name)
2075 xkb_mod_index_t index = 0;
2076 char *p = modifiers_map->data;
2078 while ((const char *)p < ((const char *)modifiers_map->data + modifiers_map->size))
2080 if (strcmp(p, name) == 0)
2087 return XKB_MOD_INVALID;
2090 static xkb_mod_mask_t
2091 modifiers_get_mask(struct wl_array *modifiers_map,
2094 xkb_mod_index_t index = modifiers_get_index(modifiers_map, name);
2096 if (index == XKB_MOD_INVALID)
2097 return XKB_MOD_INVALID;
2103 text_input_modifiers_map(void *data,
2104 struct wl_text_input *text_input EINA_UNUSED,
2105 struct wl_array *map)
2107 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2108 imcontext->shift_mask = modifiers_get_mask(map, XKB_MOD_NAME_SHIFT);
2109 imcontext->control_mask = modifiers_get_mask(map, XKB_MOD_NAME_CTRL);
2110 imcontext->alt_mask = modifiers_get_mask(map, XKB_MOD_NAME_ALT);
2111 imcontext->caps_mask = modifiers_get_mask(map, XKB_MOD_NAME_CAPS);
2112 imcontext->num_mask = modifiers_get_mask(map, XKB_MOD_NAME_NUM);
2116 _ecore_keyevent_free (void *data EINA_UNUSED, void *ev)
2118 Ecore_Event_Key *e = ev;
2119 if (e->dev) ecore_device_unref(e->dev);
2125 text_input_keysym(void *data,
2126 struct wl_text_input *text_input EINA_UNUSED,
2127 uint32_t serial EINA_UNUSED,
2133 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2134 char string[32] = {'\0'};
2135 char key[32] = {'\0'};
2136 char keyname[32] = {'\0'};
2139 memset(key, 0, sizeof(key));
2140 xkb_keysym_get_name(sym, key, sizeof(key));
2142 memset(keyname, 0, sizeof(keyname));
2143 xkb_keysym_get_name(sym, keyname, sizeof(keyname));
2144 if (keyname[0] == '\0')
2145 snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
2147 memset(string, 0, sizeof(string));
2148 xkb_keysym_to_utf8(sym, string, 32);
2150 SECURE_LOGD("key event (key: %s)", keyname);
2152 unsigned int key_len = strlen(key);
2153 unsigned int key_name_len = strlen(keyname);
2154 unsigned int key_string_len = strlen(string);
2156 if (key_len > sizeof(key)-1)
2157 key_len = sizeof(key)-1;
2159 if (key_name_len > sizeof(keyname)-1)
2160 key_name_len = sizeof(keyname)-1;
2162 if (key_string_len > sizeof(string)-1)
2163 key_string_len = sizeof(string)-1;
2165 e = calloc(1, sizeof(Ecore_Event_Key) + key_len + key_name_len +
2166 key_string_len + 3);
2169 e->keyname = (char *)(e + 1);
2170 e->key = e->keyname + key_name_len + 1;
2171 e->string = e->key + key_len + 1;
2172 e->compose = e->string;
2174 memcpy((void *)e->keyname, keyname, key_name_len);
2175 *((char *)e->keyname + key_name_len) = '\0';
2176 memcpy((void *)e->key, key, key_len);
2177 *((char *)e->key + key_len) = '\0';
2178 memcpy((void *)e->string, string, key_string_len);
2179 *((char *)e->string + key_string_len) = '\0';
2181 e->window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2182 e->event_window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2183 e->dev = ecore_device_ref(_ime_device);
2184 e->timestamp = 0; /* For distinguishing S/W keyboard event */
2187 if (modifiers & imcontext->shift_mask)
2188 e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
2190 if (modifiers & imcontext->control_mask)
2191 e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
2193 if (modifiers & imcontext->alt_mask)
2194 e->modifiers |= ECORE_EVENT_MODIFIER_ALT;
2196 if (modifiers & MOD_Mod5_MASK)
2197 e->modifiers |= MOD_Mod5_MASK;
2199 if (modifiers & imcontext->caps_mask)
2200 e->modifiers |= ECORE_EVENT_LOCK_CAPS;
2202 if (modifiers & imcontext->num_mask)
2203 e->modifiers |= ECORE_EVENT_LOCK_NUM;
2205 //Save "wl_text_input::keysym" keysym to list if list is not empty,
2206 //if not, send keysym to ecore loop as key event.
2207 //This code let key event which will be filtered by IME one by one.
2208 if (eina_list_count(imcontext->keysym_list)) {
2209 e->data = (void *)(unsigned long int)(state ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP);
2210 imcontext->keysym_list = eina_list_prepend(imcontext->keysym_list, e);
2214 ecore_event_add(ECORE_EVENT_KEY_DOWN, e, _ecore_keyevent_free, NULL);
2216 ecore_event_add(ECORE_EVENT_KEY_UP, e, _ecore_keyevent_free, NULL);
2221 text_input_enter(void *data,
2222 struct wl_text_input *text_input EINA_UNUSED,
2223 struct wl_surface *surface EINA_UNUSED)
2225 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2227 update_state(imcontext);
2229 imcontext->reset_serial = imcontext->serial;
2233 text_input_leave(void *data,
2234 struct wl_text_input *text_input EINA_UNUSED)
2236 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2239 commit_preedit(imcontext);
2240 clear_preedit(imcontext);
2244 text_input_input_panel_state(void *data EINA_UNUSED,
2245 struct wl_text_input *text_input EINA_UNUSED,
2246 uint32_t state EINA_UNUSED)
2248 // TIZEN_ONLY(20150708): Support input panel state callback
2249 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2250 LOGD("input panel state: %d", state);
2252 case WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE:
2253 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2254 if (imcontext->ctx == _show_req_ctx)
2255 _show_req_ctx = NULL;
2257 will_hide = EINA_FALSE;
2259 _received_will_hide_event = EINA_TRUE;
2260 LOGD("_received_will_hide_event = 1");
2261 send_will_hide_ack(imcontext->ctx);
2263 case WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW:
2264 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
2265 _received_will_hide_event = EINA_FALSE;
2267 _show_req_ctx = imcontext->ctx;
2268 LOGD("_received_will_hide_event = 0");
2271 _input_panel_state = (Ecore_IMF_Input_Panel_State)state;
2275 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx,
2276 ECORE_IMF_INPUT_PANEL_STATE_EVENT,
2277 _input_panel_state);
2279 if (state == WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE) {
2280 reset_keyboard_geometry();
2281 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2282 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2287 // TIZEN_ONLY(20151221): Support input panel geometry
2289 text_input_input_panel_geometry(void *data EINA_UNUSED,
2290 struct wl_text_input *text_input EINA_UNUSED,
2296 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2298 if (_keyboard_geometry.x != (int)x || _keyboard_geometry.y != (int)y ||
2299 _keyboard_geometry.w != (int)w || _keyboard_geometry.h != (int)h)
2301 _keyboard_geometry.x = x;
2302 _keyboard_geometry.y = y;
2303 _keyboard_geometry.w = w;
2304 _keyboard_geometry.h = h;
2305 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2306 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2312 text_input_language(void *data,
2313 struct wl_text_input *text_input EINA_UNUSED,
2314 uint32_t serial EINA_UNUSED,
2315 const char *language)
2317 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2318 Eina_Bool changed = EINA_FALSE;
2320 if (!imcontext || !language) return;
2322 if (imcontext->language) {
2323 if (strcmp(imcontext->language, language) != 0) {
2324 changed = EINA_TRUE;
2325 free(imcontext->language);
2329 changed = EINA_TRUE;
2333 imcontext->language = strdup(language);
2336 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, 0);
2341 text_input_text_direction(void *data EINA_UNUSED,
2342 struct wl_text_input *text_input EINA_UNUSED,
2343 uint32_t serial EINA_UNUSED,
2344 uint32_t direction EINA_UNUSED)
2348 // TIZEN_ONLY(20150918): Support to set the selection region
2350 text_input_selection_region(void *data,
2351 struct wl_text_input *text_input EINA_UNUSED,
2352 uint32_t serial EINA_UNUSED,
2356 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2357 if (!imcontext || !imcontext->ctx) return;
2359 Ecore_IMF_Event_Selection ev;
2360 ev.ctx = imcontext->ctx;
2363 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_SELECTION_SET, &ev);
2367 text_input_private_command(void *data,
2368 struct wl_text_input *text_input EINA_UNUSED,
2369 uint32_t serial EINA_UNUSED,
2370 const char *command)
2372 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2373 if (!imcontext || !imcontext->ctx) return;
2375 const char *szConformantReset = "CONFORMANT_RESET";
2376 const char *szConformantRestore = "CONFORMANT_RESTORE";
2377 LOGD("Checking command : %s", command);
2379 if (strncmp(command, szConformantReset, strlen(szConformantReset)) == 0) {
2380 Ecore_Wl2_Window *window = imcontext->window;
2381 if (!window) return;
2383 if (!reset_conformant_area(imcontext->ctx) && !_conformant_reset_started) {
2384 LOGD("Could not reset conformant area, send will_hide_ack right away %d", _conformant_reset_started);
2385 _send_will_hide_ack(imcontext);
2386 } else if (_conformant_reset_done) {
2387 LOGD("Conformant reset has been already finished, send will_hide_ack right away");
2388 _send_will_hide_ack(imcontext);
2390 } else if (strncmp(command, szConformantRestore, strlen(szConformantRestore)) == 0) {
2391 Ecore_Wl2_Window *window = imcontext->window;
2392 if (!window) return;
2394 restore_conformant_area(imcontext->ctx);
2396 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)command);
2401 text_input_commit_content(void *data,
2402 struct wl_text_input *text_input EINA_UNUSED,
2403 uint32_t serial EINA_UNUSED,
2404 const char *content,
2405 const char *description,
2406 const char *mime_types)
2408 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2409 if (!imcontext || !imcontext->ctx) return;
2411 Ecore_IMF_Event_Commit_Content ev;
2412 ev.content_uri = content;
2413 ev.mime_types = mime_types;
2414 ev.description = description;
2416 SECURE_LOGD("commit content : %s, description : %s, mime types : %s", content, description, mime_types);
2418 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT_CONTENT, (void *)&ev);
2422 text_input_input_panel_data(void *data,
2423 struct wl_text_input *text_input EINA_UNUSED,
2424 uint32_t serial EINA_UNUSED,
2425 const char *input_panel_data,
2428 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2429 if (!imcontext || !imcontext->ctx) return;
2431 if (imcontext->input_panel_data)
2432 free (imcontext->input_panel_data);
2434 imcontext->input_panel_data = calloc (1, length);
2435 if (imcontext->input_panel_data)
2436 memcpy (imcontext->input_panel_data, input_panel_data, length);
2438 imcontext->input_panel_data_length = length;
2442 text_input_get_selection_text (void *data,
2443 struct wl_text_input *text_input EINA_UNUSED,
2446 char *selection = NULL;
2448 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2449 if (!imcontext || !imcontext->ctx) {
2450 LOGD ("No context!");
2455 ecore_imf_context_selection_get (imcontext->ctx, &selection);
2456 if (imcontext->text_input) {
2457 SECURE_LOGD ("selection :%s", selection ? selection : "");
2459 char *_selection = selection;
2460 size_t len = strlen (selection);
2462 ssize_t ret = write (fd, _selection, len);
2466 LOGW ("write pipe failed, errno: %d", errno);
2480 text_input_get_surrounding_text (void *data,
2481 struct wl_text_input *text_input EINA_UNUSED,
2482 uint32_t maxlen_before,
2483 uint32_t maxlen_after,
2487 char *surrounding = NULL;
2488 LOGD("fd: %d maxlen_before: %d maxlen_after: %d", fd, maxlen_before, maxlen_after);
2489 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2490 if (!imcontext || !imcontext->ctx) {
2491 LOGD ("No context!");
2496 /* cursor_pos is a byte index */
2497 if (ecore_imf_context_surrounding_get (imcontext->ctx, &surrounding, &cursor_pos)) {
2498 SECURE_LOGD ("surrounding : '%s', cursor: %d", surrounding ? surrounding : "", cursor_pos);
2499 if (imcontext->text_input) {
2500 Eina_Unicode *wide_surrounding = eina_unicode_utf8_to_unicode (surrounding, NULL);
2501 size_t wlen = eina_unicode_strlen (wide_surrounding);
2503 if (cursor_pos > (int)wlen || cursor_pos < 0)
2506 if (maxlen_before > cursor_pos)
2509 maxlen_before = cursor_pos - maxlen_before;
2511 if (maxlen_after > wlen - cursor_pos)
2512 maxlen_after = (uint32_t)wlen;
2514 maxlen_after = cursor_pos + maxlen_after;
2516 char *req_surrounding = eina_unicode_unicode_to_utf8_range (wide_surrounding + maxlen_before, maxlen_after - maxlen_before, NULL);
2518 ssize_t ret = write(fd, &cursor_pos, sizeof(cursor_pos));
2520 LOGW ("write pipe failed, errno: %d", errno);
2521 } else if (req_surrounding) {
2522 char *_surrounding = req_surrounding;
2523 size_t len = strlen(req_surrounding);
2525 ssize_t ret = write(fd, _surrounding, len);
2529 LOGW ("write pipe failed, errno: %d", errno);
2532 _surrounding += ret;
2537 if (req_surrounding)
2538 free (req_surrounding);
2540 if (wide_surrounding)
2541 free (wide_surrounding);
2551 text_input_filter_key_event_done(void *data,
2552 struct wl_text_input *text_input EINA_UNUSED,
2556 LOGD("serial: %d, state: %d", serial, state);
2557 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2558 if (!imcontext) return;
2560 imcontext->last_key_event_filter.serial = serial;
2561 imcontext->last_key_event_filter.state = state;
2565 text_input_hide_permission(void *data,
2566 struct wl_text_input *text_input EINA_UNUSED,
2567 uint32_t permission)
2569 LOGD("permission : %d", permission);
2570 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2571 if (!imcontext || !imcontext->ctx || ignore_hide)
2575 ecore_imf_context_input_panel_hide(imcontext->ctx);
2579 text_input_recapture_string(void *data,
2580 struct wl_text_input *text_input EINA_UNUSED,
2584 const char *preedit,
2585 const char *preedit_commit,
2588 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2589 Eina_Bool old_preedit = EINA_FALSE;
2590 Eina_Bool preedit_changed = EINA_FALSE;
2592 SECURE_LOGD("ctx : %p, index : %d, length : %d, preedit event (preedit: '%s', current pre-edit: '%s')",
2597 imcontext->preedit_text ? imcontext->preedit_text : "");
2599 if (!check_serial(imcontext, serial))
2603 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
2605 if (imcontext->preedit_text)
2606 preedit_changed = (strcmp(imcontext->preedit_text, preedit) != 0);
2608 preedit_changed = (strlen(preedit) != 0);
2610 // send transaction start
2611 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_START");
2612 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_START, NULL);
2614 commit_preedit(imcontext);
2615 clear_preedit(imcontext);
2617 // delete surrounding text
2618 delete_surrounding_text(imcontext, index, length);
2620 // update preedit string
2621 imcontext->preedit_text = strdup(preedit);
2622 imcontext->preedit_commit = (strlen(preedit) > 0 ? strdup(preedit_commit) : NULL);
2623 imcontext->preedit_cursor =
2624 utf8_offset_to_characters(preedit, imcontext->pending_preedit.cursor);
2625 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
2627 imcontext->pending_preedit.attrs = NULL;
2629 if (preedit_changed) {
2631 ecore_imf_context_event_callback_call(imcontext->ctx,
2632 ECORE_IMF_CALLBACK_PREEDIT_START,
2636 ecore_imf_context_event_callback_call(imcontext->ctx,
2637 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
2640 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
2641 ecore_imf_context_event_callback_call(imcontext->ctx,
2642 ECORE_IMF_CALLBACK_PREEDIT_END,
2648 if (commit && strlen(commit) != 0) {
2649 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)commit);
2652 // send transaction end
2653 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_END");
2654 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_END, NULL);
2658 text_input_input_panel_event(void *data,
2659 struct wl_text_input *text_input EINA_UNUSED,
2660 uint32_t serial EINA_UNUSED,
2661 uint32_t event_type,
2664 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2665 if (!imcontext || !imcontext->ctx) return;
2667 LOGD("event type : %d, value : %d", event_type, value);
2669 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, event_type, value);
2673 static const struct wl_text_input_listener text_input_listener =
2677 text_input_modifiers_map,
2678 text_input_input_panel_state,
2679 text_input_preedit_string,
2680 text_input_preedit_styling,
2681 text_input_preedit_cursor,
2682 text_input_commit_string,
2683 text_input_cursor_position,
2684 text_input_delete_surrounding_text,
2686 text_input_language,
2687 text_input_text_direction,
2688 // TIZEN_ONLY(20150918): Support to set the selection region
2689 text_input_selection_region,
2690 text_input_private_command,
2691 text_input_input_panel_geometry,
2692 text_input_input_panel_data,
2693 text_input_get_selection_text,
2694 text_input_get_surrounding_text,
2695 text_input_filter_key_event_done,
2696 text_input_hide_permission,
2697 text_input_recapture_string,
2698 text_input_input_panel_event,
2699 text_input_commit_content
2705 keyboard_mode_changed_cb (keynode_t *key, void* data)
2707 hw_keyboard_mode = vconf_keynode_get_bool (key);
2708 Ecore_IMF_Context *active_ctx = get_using_ctx ();
2710 LOGD ("ctx : %p, input detect : %d", active_ctx, hw_keyboard_mode);
2712 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;
2713 ecore_imf_context_input_panel_event_callback_call (active_ctx, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, input_mode);
2715 if (input_mode == ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE && _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW)
2716 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2718 if ((input_mode == ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE) && _focused_ctx && (active_ctx == _focused_ctx)) {
2719 if (ecore_imf_context_input_panel_enabled_get (active_ctx)) {
2720 ecore_imf_context_input_panel_show (active_ctx);
2727 #ifdef SOCKET_ACTIVATION
2728 static int activate_socket () {
2730 struct sockaddr_un svr;
2736 LOGD("socket_activate start");
2737 s = socket(AF_UNIX, SOCK_STREAM, 0);
2739 LOGW("socket error");
2743 flag = fcntl(s, F_GETFL, NULL);
2745 fcntl(s, F_SETFL, flag);
2747 svr.sun_family = AF_UNIX;
2748 strcpy(svr.sun_path, SOCK_PATH);
2751 r = connect(s, (struct sockaddr *)&svr, len);
2753 LOGD("connect error");
2761 gettimeofday(&s1, NULL);
2762 LOGD("%d %06d\n", (int)s1.tv_sec, (int)s1.tv_usec);
2764 r = send(s, (const void *)&s1, sizeof(s1), 0);
2777 void wayland_im_initialize ()
2779 register_key_handler ();
2781 /* get input language vconf value */
2782 char *input_lang_str = vconf_get_str (VCONFKEY_ISF_INPUT_LANGUAGE);
2783 if (input_lang_str) {
2784 set_input_language (input_lang_str);
2785 free (input_lang_str);
2789 /* get autoperiod allow vconf value */
2791 if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
2792 if (val == EINA_TRUE)
2793 autoperiod_allow = EINA_TRUE;
2796 /* get autocapital allow vconf value */
2797 if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
2798 if (val == EINA_TRUE)
2799 autocap_allow = EINA_TRUE;
2802 /* get hardware keyboard input detected vconf value */
2803 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
2804 if (val == EINA_TRUE)
2805 hw_keyboard_mode = EINA_TRUE;
2808 vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL);
2809 vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL);
2810 vconf_notify_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb, NULL);
2811 vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
2814 _ime_device = ecore_device_add();
2816 ecore_device_name_set (_ime_device, IME_DEVICE_NAME);
2817 ecore_device_description_set (_ime_device, IME_DEVICE_NAME);
2818 ecore_device_identifier_set (_ime_device, IME_DEVICE_NAME);
2819 ecore_device_class_set (_ime_device, ECORE_DEVICE_CLASS_KEYBOARD);
2820 ecore_device_subclass_set (_ime_device, ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD);
2824 void wayland_im_uninitialize ()
2826 _ecore_imf_wayland_imcontext_pair_destroy ();
2828 unregister_key_handler ();
2830 _win_focus_out_handler_del ();
2831 _conformant_change_handler_del ();
2834 vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
2835 vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
2836 vconf_ignore_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb);
2837 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
2841 ecore_device_del (_ime_device);
2845 ecore_event_type_flush(ECORE_EVENT_DEVICE_ADD, ECORE_EVENT_DEVICE_DEL);
2849 wayland_im_context_add(Ecore_IMF_Context *ctx)
2851 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2854 LOGD("ctx : %p", ctx);
2856 if (!imcontext) return;
2858 imcontext->ctx = ctx;
2859 imcontext->input_panel_layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2860 imcontext->keysym_list = NULL;
2862 imcontext->shift_mask = MOD_SHIFT_MASK;
2863 imcontext->control_mask = MOD_CONTROL_MASK;
2864 imcontext->alt_mask = MOD_ALT_MASK;
2865 imcontext->caps_mask = MOD_CAPS_MASK;
2866 imcontext->num_mask = MOD_NUM_MASK;
2868 imcontext->input_panel_position.x = -1;
2869 imcontext->input_panel_position.y = -1;
2871 LOGD("text_input_manager : %p", imcontext->text_input_manager);
2872 imcontext->text_input =
2873 wl_text_input_manager_create_text_input(imcontext->text_input_manager);
2875 if (imcontext->text_input)
2876 wl_text_input_add_listener(imcontext->text_input,
2877 &text_input_listener, imcontext);
2880 LOGD("app id : %s\n", appid);
2882 ecore_imf_context_prediction_hint_hash_set(ctx, "appid", appid ? appid : "");
2889 wayland_im_context_del (Ecore_IMF_Context *ctx)
2891 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2893 Eina_Bool valid = EINA_FALSE;
2894 Ecore_Imf_Wayland_Imcontext_Pair *pair = _ecore_imf_wayland_imcontext_pair_find(ctx);
2895 if (pair && pair->imcontext == imcontext) {
2896 _ecore_imf_wayland_imcontext_pair_del(ctx);
2900 LOGE("The Ecore_Imf %p and WaylandIMContext %p pair not found!! pair : %p, pair->imcontext %p",
2901 ctx, imcontext, pair, pair ? pair->imcontext : NULL);
2902 _ecore_imf_wayland_imcontext_pair_log();
2905 Ecore_Event_Key *ev;
2906 LOGD ("ctx : %p, ctx valid : %d, focused_ctx : %p, show_req_ctx : %p", ctx, valid, _focused_ctx, _show_req_ctx);
2908 if (!imcontext) return;
2910 // TIZEN_ONLY(20150708): Support back key
2911 if (_input_panel_ctx == ctx) {
2912 _clear_hide_timer();
2913 _input_panel_hide(ctx, EINA_TRUE);
2914 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2915 _input_panel_ctx = NULL;
2918 if (_focused_ctx == ctx)
2919 _focused_ctx = NULL;
2921 if (_show_req_ctx == ctx)
2922 _show_req_ctx = NULL;
2924 if (_focus_req_ctx == ctx) {
2925 if (imcontext->canvas)
2926 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
2928 _focus_req_ctx = NULL;
2929 _focus_req_only = EINA_TRUE;
2933 if (imcontext->language) {
2934 free (imcontext->language);
2935 imcontext->language = NULL;
2938 // TIZEN_ONLY(20150922): Support to set input panel data
2939 if (imcontext->imdata) {
2940 free (imcontext->imdata);
2941 imcontext->imdata = NULL;
2942 imcontext->imdata_size = 0;
2945 if (imcontext->input_panel_data) {
2946 free (imcontext->input_panel_data);
2947 imcontext->input_panel_data = NULL;
2948 imcontext->input_panel_data_length = 0;
2952 if (imcontext->prediction_hint) {
2953 free (imcontext->prediction_hint);
2954 imcontext->prediction_hint = NULL;
2957 if (imcontext->mime_type) {
2958 free (imcontext->mime_type);
2959 imcontext->mime_type = NULL;
2962 if (imcontext->text_input)
2963 wl_text_input_destroy (imcontext->text_input);
2965 clear_preedit (imcontext);
2967 EINA_LIST_FREE(imcontext->keysym_list, ev) {
2976 wayland_im_context_reset(Ecore_IMF_Context *ctx)
2978 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2980 LOGD("ctx : %p", ctx);
2982 if (!imcontext) return;
2984 commit_preedit (imcontext);
2986 if (!imcontext->input) return;
2988 if (imcontext->text_input) {
2989 wl_text_input_reset(imcontext->text_input);
2991 update_state(imcontext);
2993 imcontext->reset_serial = imcontext->serial;
2997 _prediction_hint_data_foreach_cb(const Eina_Hash *hash, const void *key,
2998 void *data, void *fdata)
3000 const char *key_str = key;
3001 const char *value = data;
3002 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)fdata;
3003 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3005 SECURE_LOGD("key : %s, value : %s\n", key_str, value);
3007 if (imcontext && imcontext->text_input)
3008 wl_text_input_prediction_hint_data(imcontext->text_input, key_str, value);
3014 wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
3016 LOGD ("ctx : %p. enable : %d, on demand : %d", ctx,
3017 ecore_imf_context_input_panel_enabled_get(ctx),
3018 ecore_imf_context_input_panel_show_on_demand_get (ctx));
3020 #ifdef SOCKET_ACTIVATION
3024 if (!set_focus(ctx)) {
3025 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3026 if (imcontext && !imcontext->input) {
3027 if (_focus_req_ctx != ctx)
3028 _focus_req_only = EINA_TRUE;
3029 _focus_req_ctx = ctx;
3030 if (imcontext->canvas) {
3031 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
3032 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
3035 LOGW("ctx : %p. Fail to set focus!", ctx);
3039 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3040 if (imcontext && imcontext->input && imcontext->text_input) {
3041 wl_text_input_set_return_key_disabled(imcontext->text_input,
3042 imcontext->return_key_disabled);
3044 if (imcontext->prediction_hint)
3045 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
3047 if (imcontext->mime_type)
3048 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
3050 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
3051 wl_text_input_set_input_panel_position(imcontext->text_input,
3052 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
3054 const Eina_Hash *hash = ecore_imf_context_prediction_hint_hash_get(ctx);
3056 eina_hash_foreach(hash, _prediction_hint_data_foreach_cb, ctx);
3058 wl_text_input_set_content_type(imcontext->text_input, imcontext->content_hint, get_purpose(ctx));
3062 hw_keyboard_mode = EINA_FALSE;
3064 if (ecore_imf_context_input_panel_enabled_get(ctx))
3065 if (!ecore_imf_context_input_panel_show_on_demand_get (ctx))
3066 show_input_panel(ctx);
3068 LOGD ("ctx : %p input panel on demand mode : TRUE", ctx);
3070 LOGD ("ctx : %p input panel enable : FALSE", ctx);
3074 wayland_im_context_focus_out(Ecore_IMF_Context *ctx)
3076 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3078 LOGD("ctx : %p", ctx);
3080 if (_focus_req_ctx == ctx) {
3081 _focus_req_ctx = NULL;
3082 _focus_req_only = EINA_TRUE;
3085 if (!imcontext || !imcontext->input) return;
3088 if (hw_keyboard_mode == EINA_TRUE) {
3089 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3090 hw_keyboard_mode = EINA_FALSE;
3094 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3095 ecore_imf_context_input_panel_hide(ctx);
3102 wayland_im_context_preedit_string_get(Ecore_IMF_Context *ctx,
3106 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3107 if (!imcontext) return;
3109 SECURE_LOGD("pre-edit string requested (preedit: '%s', preedit cursor : %d)",
3110 imcontext->preedit_text ? imcontext->preedit_text : "", imcontext->preedit_cursor);
3113 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3116 *cursor_pos = imcontext->preedit_cursor;
3120 wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
3125 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3126 if (!imcontext) return;
3128 SECURE_LOGD("pre-edit string with attributes requested (preedit: '%s', preedit cursor : %d)",
3129 imcontext->preedit_text ? imcontext->preedit_text : "", imcontext->preedit_cursor);
3132 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3136 Ecore_IMF_Preedit_Attr *a, *attr;
3138 if (imcontext->preedit_attrs) {
3139 EINA_LIST_FOREACH(imcontext->preedit_attrs, l, a) {
3140 attr = malloc(sizeof(*attr));
3142 attr = memcpy(attr, a, sizeof(*attr));
3143 *attrs = eina_list_append(*attrs, attr);
3148 if (imcontext->preedit_text) {
3149 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
3151 // use REVERSE style as default
3152 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
3153 attr->start_index = 0;
3154 attr->end_index = strlen(imcontext->preedit_text);
3155 *attrs = eina_list_append(*attrs, attr);
3162 *cursor_pos = imcontext->preedit_cursor;
3166 wayland_im_context_cursor_position_set (Ecore_IMF_Context *ctx,
3169 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3170 if (!imcontext) return;
3172 if (imcontext->cursor_position != cursor_pos) {
3173 imcontext->cursor_position = cursor_pos;
3175 if (imcontext->input && imcontext->text_input) {
3176 LOGD ("ctx : %p, cursor pos : %d", ctx, cursor_pos);
3178 set_autocapital (ctx);
3180 if (!imcontext->preedit_text || strlen(imcontext->preedit_text) == 0)
3181 wl_text_input_set_cursor_position (imcontext->text_input, cursor_pos);
3187 wayland_im_context_use_preedit_set(Ecore_IMF_Context *ctx EINA_UNUSED,
3188 Eina_Bool use_preedit EINA_UNUSED)
3193 wayland_im_context_client_window_set(Ecore_IMF_Context *ctx,
3196 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3198 LOGD("client window set (Ecore_Window: %p)", window);
3200 if (imcontext && window) {
3201 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3204 imcontext->window = ecore_wl2_display_window_find(wl2_display, (Ecore_Window)window);
3205 LOGD("client Ecore_Wl2_Window : %p", imcontext->window);
3208 if (_ime_device && imcontext->window)
3209 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3214 wayland_im_context_client_canvas_set(Ecore_IMF_Context *ctx,
3217 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3219 LOGD("client canvas set (canvas: %p)", canvas);
3221 if (imcontext && canvas) {
3222 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3223 imcontext->canvas = canvas;
3225 if (wl2_display && !imcontext->window) {
3226 imcontext->window = ecore_wl2_display_window_find(wl2_display, ecore_evas_window_get(ecore_evas_ecore_evas_get(canvas)));
3227 LOGD("client Ecore_Wl2_Window : %p", imcontext->window);
3230 if (_ime_device && imcontext->window)
3231 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3236 wayland_im_context_show(Ecore_IMF_Context *ctx)
3238 LOGD("ctx : %p", ctx);
3240 show_input_panel(ctx);
3244 wayland_im_context_hide(Ecore_IMF_Context *ctx)
3246 LOGD("ctx : %p", ctx);
3248 if (!get_using_ctx()) {
3249 LOGW("Can't hide input_panel because there is no using context!!");
3253 _input_panel_hide(ctx, EINA_FALSE);
3256 #if !(ENABLE_GRAB_KEYBOARD)
3258 _ecore_imf_lock_to_ecore_key_modifier(unsigned int locks)
3260 unsigned int mask = 0;
3262 if (locks & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
3263 mask |= ECORE_EVENT_LOCK_SCROLL;
3265 if (locks & ECORE_IMF_KEYBOARD_LOCK_CAPS)
3266 mask |= ECORE_EVENT_LOCK_CAPS;
3268 if (locks & ECORE_IMF_KEYBOARD_LOCK_NUM)
3269 mask |= ECORE_EVENT_LOCK_NUM;
3275 _ecore_imf_modifier_to_ecore_key_modifier(Ecore_IMF_Keyboard_Modifiers modifiers)
3277 unsigned int mask = 0;
3279 /**< "Control" is pressed */
3280 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
3281 mask |= ECORE_EVENT_MODIFIER_CTRL;
3283 /**< "Alt" is pressed */
3284 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
3285 mask |= ECORE_EVENT_MODIFIER_ALT;
3287 /**< "Shift" is pressed */
3288 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
3289 mask |= ECORE_EVENT_MODIFIER_SHIFT;
3291 /**< "Win" (between "Ctrl" and "Alt") is pressed */
3292 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
3293 mask |= ECORE_EVENT_MODIFIER_WIN;
3295 /**< "AltGr" is pressed */
3296 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
3297 mask |= ECORE_EVENT_MODIFIER_ALTGR;
3304 wayland_im_context_filter_event(Ecore_IMF_Context *ctx,
3305 Ecore_IMF_Event_Type type,
3306 Ecore_IMF_Event *imf_event)
3309 #if !(ENABLE_GRAB_KEYBOARD)
3310 Eina_Bool ret = EINA_FALSE;
3311 Ecore_Event_Key ecore_key_ev;
3312 char *key_dev_name = NULL;
3313 uint32_t key_dev_class = 0;
3314 uint32_t key_dev_subclass = 0;
3316 if (type == ECORE_IMF_EVENT_MOUSE_UP) {
3317 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3318 LOGD ("[Mouse-up event] ctx : %p", ctx);
3319 if (ctx == _focused_ctx) {
3320 ecore_imf_context_input_panel_show(ctx);
3323 LOGE ("Can't show IME because there is no focus. ctx : %p", ctx);
3326 #if !(ENABLE_GRAB_KEYBOARD)
3327 else if (type == ECORE_IMF_EVENT_KEY_UP) {
3328 Ecore_IMF_Event_Key_Up *key_ev = (Ecore_IMF_Event_Key_Up *)imf_event;
3329 ecore_key_ev.keyname = key_ev->keyname;
3330 ecore_key_ev.key = key_ev->key;
3331 ecore_key_ev.string = key_ev->string;
3332 ecore_key_ev.compose = key_ev->compose;
3333 ecore_key_ev.timestamp = key_ev->timestamp;
3334 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3335 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3336 key_dev_name = (char *)key_ev->dev_name;
3337 key_dev_class = key_ev->dev_class;
3338 key_dev_subclass = key_ev->dev_subclass;
3339 ecore_key_ev.keycode = key_ev->keycode;
3341 else if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3342 Ecore_IMF_Event_Key_Down *key_ev = (Ecore_IMF_Event_Key_Down *)imf_event;
3343 ecore_key_ev.keyname = key_ev->keyname;
3344 ecore_key_ev.key = key_ev->key;
3345 ecore_key_ev.string = key_ev->string;
3346 ecore_key_ev.compose = key_ev->compose;
3347 ecore_key_ev.timestamp = key_ev->timestamp;
3348 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3349 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3350 key_dev_name = (char *)key_ev->dev_name;
3351 key_dev_class = key_ev->dev_class;
3352 key_dev_subclass = key_ev->dev_subclass;
3353 ecore_key_ev.keycode = key_ev->keycode;
3356 if (type == ECORE_IMF_EVENT_KEY_UP || type == ECORE_IMF_EVENT_KEY_DOWN) {
3357 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3358 if (!imcontext || !imcontext->input || !imcontext->text_input)
3361 if (!_focused_ctx) {
3366 if (_focused_ctx != ctx) {
3367 LOGW ("focused context is different from the context used in ecore_imf_context_filter_event.");
3368 LOGW ("focus context : %p, context : %p", _focused_ctx, ctx);
3373 if (!ecore_key_ev.timestamp && (ecore_key_ev.modifiers & MOD_Mod5_MASK)
3374 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD) {
3375 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3376 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3377 strcmp (ecore_key_ev.key, "KP_Space") == 0 ) {
3378 autoperiod_insert (ctx);
3382 LOGD("Return! This is SW keyboard fake event!");
3386 int serial = imcontext->serial++;
3387 double start_time = ecore_time_get();
3390 uint32_t modifiers = 0;
3391 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_SHIFT)
3392 modifiers |= imcontext->shift_mask;
3393 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_CTRL)
3394 modifiers |= imcontext->control_mask;
3395 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_ALT)
3396 modifiers |= imcontext->alt_mask;
3397 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_CAPS)
3398 modifiers |= imcontext->caps_mask;
3399 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_NUM)
3400 modifiers |= imcontext->num_mask;
3402 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);
3403 //Send key event to IME.
3404 wl_text_input_filter_key_event(imcontext->text_input, serial, ecore_key_ev.timestamp, ecore_key_ev.key,
3405 type == ECORE_IMF_EVENT_KEY_UP? WL_KEYBOARD_KEY_STATE_RELEASED : WL_KEYBOARD_KEY_STATE_PRESSED,
3406 modifiers, (key_dev_name ? key_dev_name : ""), key_dev_class, key_dev_subclass, ecore_key_ev.keycode);
3407 //Waiting for filter_key_event_done from IME.
3408 //This function should return IME filtering result with boolean type.
3409 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3410 struct wl_display *display = NULL;
3412 display = ecore_wl2_display_get(wl2_display);
3415 struct wl_event_queue *queue = wl_display_create_queue(display);
3418 while (ecore_time_get() - start_time < WAIT_FOR_FILTER_DONE_SECOND && _focused_ctx == ctx && wl_display_roundtrip_queue(display, queue) != -1) {
3419 wl_display_dispatch_pending(display);
3420 if (imcontext->last_key_event_filter.serial == serial) {
3421 ret = imcontext->last_key_event_filter.state;
3423 } else if (imcontext->last_key_event_filter.serial > serial)
3427 if (ecore_time_get() - start_time > WAIT_FOR_FILTER_DONE_SECOND) {
3428 LOGE("Key processing result not received");
3432 if (imcontext->last_key_event_filter.serial < serial) {
3433 LOGW("Timeout occured");
3437 wl_event_queue_destroy(queue);
3440 LOGD ("elapsed : %.3f ms, serial (last, require) : (%d, %d)", (ecore_time_get() - start_time)*1000, imcontext->last_key_event_filter.serial, serial);
3444 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3445 if (ret == EINA_FALSE) {
3447 if (strcmp (ecore_key_ev.keyname, "Return") == 0 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_REMOCON) {
3449 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
3451 LOGD ("Changed keyboard mode from H/W to S/W ");
3452 hw_keyboard_mode = EINA_FALSE;
3453 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3454 if (ecore_imf_context_input_panel_enabled_get (ctx)) {
3455 ecore_imf_context_input_panel_show (ctx);
3462 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3463 strcmp (ecore_key_ev.key, "KP_Space") == 0) {
3464 autoperiod_insert (ctx);
3469 //Deal with the next key event in list.
3470 Ecore_Event_Key *ev = NULL;
3471 if (eina_list_count (imcontext->keysym_list)) {
3472 Eina_List *n = eina_list_last(imcontext->keysym_list);
3473 ev = (Ecore_Event_Key *)eina_list_data_get(n);
3474 int event_type = (unsigned long int)ev->data;
3477 ecore_event_add(event_type, ev, _ecore_keyevent_free, NULL);
3478 imcontext->keysym_list = eina_list_remove_list(imcontext->keysym_list, n);
3489 wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int width, int height)
3491 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3492 if (!imcontext) return;
3494 if ((imcontext->cursor_location.x != x) ||
3495 (imcontext->cursor_location.y != y) ||
3496 (imcontext->cursor_location.width != width) ||
3497 (imcontext->cursor_location.height != height)) {
3498 imcontext->cursor_location.x = x;
3499 imcontext->cursor_location.y = y;
3500 imcontext->cursor_location.width = width;
3501 imcontext->cursor_location.height = height;
3503 if (_focused_ctx == ctx)
3504 send_cursor_location (imcontext);
3508 void wayland_im_context_autocapital_type_set(Ecore_IMF_Context *ctx,
3509 Ecore_IMF_Autocapital_Type autocapital_type)
3511 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3512 if (!imcontext) return;
3514 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
3515 // TIZEN_ONLY(20160201): Add autocapitalization word
3516 WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION |
3518 WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
3519 WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE);
3521 if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE)
3522 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION;
3523 // TIZEN_ONLY(20160201): Add autocapitalization word
3524 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD)
3525 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
3527 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER)
3528 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE;
3530 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE;
3532 if (imcontext->input && imcontext->text_input) {
3533 LOGD ("ctx : %p. set autocapital type : %d", ctx, autocapital_type);
3534 wl_text_input_set_content_type(imcontext->text_input,
3535 imcontext->content_hint,
3541 wayland_im_context_input_panel_layout_set(Ecore_IMF_Context *ctx,
3542 Ecore_IMF_Input_Panel_Layout layout)
3544 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3545 if (!imcontext) return;
3547 imcontext->input_panel_layout = layout;
3550 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER:
3551 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
3553 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL:
3554 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL;
3556 case ECORE_IMF_INPUT_PANEL_LAYOUT_URL:
3557 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_URL;
3559 case ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER:
3560 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE;
3562 case ECORE_IMF_INPUT_PANEL_LAYOUT_IP:
3563 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3564 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_IP;
3567 case ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH:
3568 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATE;
3570 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY:
3571 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
3573 case ECORE_IMF_INPUT_PANEL_LAYOUT_HEX:
3574 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_HEX;
3576 case ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL:
3577 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL;
3579 case ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD:
3580 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
3581 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3583 case ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME:
3584 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME;
3586 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3587 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON:
3588 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON;
3591 case ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE:
3592 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE;
3595 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
3599 if (imcontext->input && imcontext->text_input) {
3600 LOGD ("ctx : %p, layout type : %d", ctx, layout);
3601 wl_text_input_set_content_type(imcontext->text_input,
3602 imcontext->content_hint,
3607 Ecore_IMF_Input_Panel_Layout
3608 wayland_im_context_input_panel_layout_get(Ecore_IMF_Context *ctx)
3610 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3611 if (!imcontext) return ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
3613 return imcontext->input_panel_layout;
3617 wayland_im_context_input_mode_set(Ecore_IMF_Context *ctx,
3618 Ecore_IMF_Input_Mode input_mode)
3620 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3621 if (!imcontext) return;
3623 if (input_mode & ECORE_IMF_INPUT_MODE_INVISIBLE)
3624 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3626 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3628 if (imcontext->input && imcontext->text_input) {
3629 LOGD ("ctx : %p, input mode : %d", ctx, input_mode);
3630 wl_text_input_set_content_type(imcontext->text_input,
3631 imcontext->content_hint,
3637 wayland_im_context_input_hint_set(Ecore_IMF_Context *ctx,
3638 Ecore_IMF_Input_Hints input_hints)
3640 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3641 if (!imcontext) return;
3643 if (input_hints & ECORE_IMF_INPUT_HINT_AUTO_COMPLETE)
3644 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3646 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3648 if (input_hints & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA)
3649 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3651 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3653 if (input_hints & ECORE_IMF_INPUT_HINT_MULTILINE)
3654 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3656 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3659 LOGD("autofill hint : %x\n", input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK);
3661 switch(input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK)
3663 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE:
3664 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE;
3666 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY:
3667 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY;
3669 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH:
3670 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH;
3672 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR:
3673 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR;
3675 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_NUMBER:
3676 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_NUMBER;
3678 case ECORE_IMF_INPUT_HINT_AUTOFILL_EMAIL_ADDRESS:
3679 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_EMAIL_ADDRESS;
3681 case ECORE_IMF_INPUT_HINT_AUTOFILL_PHONE:
3682 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_PHONE;
3684 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_ADDRESS:
3685 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_ADDRESS;
3687 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_CODE:
3688 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_CODE;
3690 case ECORE_IMF_INPUT_HINT_AUTOFILL_ID:
3691 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_ID;
3693 case ECORE_IMF_INPUT_HINT_AUTOFILL_NAME:
3694 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_NAME;
3698 if (imcontext->input && imcontext->text_input) {
3699 LOGD("ctx : %p, input hint : %#x", ctx, input_hints);
3700 wl_text_input_set_content_type(imcontext->text_input,
3701 imcontext->content_hint,
3707 wayland_im_context_input_panel_language_set(Ecore_IMF_Context *ctx,
3708 Ecore_IMF_Input_Panel_Lang lang)
3710 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3711 if (!imcontext) return;
3713 if (lang == ECORE_IMF_INPUT_PANEL_LANG_ALPHABET)
3714 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3716 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3718 if (imcontext->input && imcontext->text_input)
3719 wl_text_input_set_content_type(imcontext->text_input,
3720 imcontext->content_hint,
3724 // TIZEN_ONLY(20150708): Support input_panel_state_get
3725 Ecore_IMF_Input_Panel_State
3726 wayland_im_context_input_panel_state_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3728 return _input_panel_state;
3732 wayland_im_context_input_panel_return_key_type_set(Ecore_IMF_Context *ctx,
3733 Ecore_IMF_Input_Panel_Return_Key_Type return_key_type)
3735 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3736 if (!imcontext) return;
3738 imcontext->return_key_type = return_key_type;
3740 if (imcontext->input && imcontext->text_input)
3741 wl_text_input_set_return_key_type(imcontext->text_input,
3742 imcontext->return_key_type);
3746 wayland_im_context_input_panel_return_key_disabled_set(Ecore_IMF_Context *ctx,
3749 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3750 if (!imcontext) return;
3752 imcontext->return_key_disabled = disabled;
3754 if (imcontext->input && imcontext->text_input)
3755 wl_text_input_set_return_key_disabled(imcontext->text_input,
3756 imcontext->return_key_disabled);
3761 wayland_im_context_input_panel_language_locale_get(Ecore_IMF_Context *ctx,
3764 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3765 if (!imcontext) return;
3768 *locale = strdup(imcontext->language ? imcontext->language : "");
3772 wayland_im_context_prediction_allow_set(Ecore_IMF_Context *ctx,
3773 Eina_Bool prediction)
3775 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3776 if (!imcontext) return;
3779 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3781 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3783 if (imcontext->input && imcontext->text_input)
3784 wl_text_input_set_content_type(imcontext->text_input,
3785 imcontext->content_hint,
3789 // TIZEN_ONLY(20151221): Support input panel geometry
3791 wayland_im_context_input_panel_geometry_get(Ecore_IMF_Context *ctx EINA_UNUSED,
3792 int *x, int *y, int *w, int *h)
3795 *x = _keyboard_geometry.x;
3797 *y = _keyboard_geometry.y;
3799 *w = _keyboard_geometry.w;
3801 *h = _keyboard_geometry.h;
3805 wayland_im_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *data, int length)
3807 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3808 if (!imcontext) return;
3810 if (data && length > 0) {
3811 const char *custom_conformant_enabled = "conformant:custom,enabled";
3812 const char *custom_conformant_disabled = "conformant:custom,disabled";
3813 const char *custom_conformant_finished = "conformant:custom,finished";
3815 if (strncmp(data, custom_conformant_enabled, strlen(custom_conformant_enabled)) == 0) {
3816 _custom_conformant_event = EINA_TRUE;
3819 if (strncmp(data, custom_conformant_disabled, strlen(custom_conformant_disabled)) == 0) {
3820 _custom_conformant_event = EINA_FALSE;
3823 if (strncmp(data, custom_conformant_finished, strlen(custom_conformant_finished)) == 0) {
3824 if (_custom_conformant_event) {
3825 _conformant_reset_done = EINA_TRUE;
3826 LOGD("[conformant:custom,finished], _conformant_reset_done = 1");
3827 send_will_hide_ack(NULL);
3833 if (imcontext->imdata)
3834 free(imcontext->imdata);
3836 imcontext->imdata = calloc(1, length + 1);
3837 if (imcontext->imdata && data)
3838 memcpy(imcontext->imdata, data, length);
3840 imcontext->imdata_size = length;
3842 if (imcontext->input && imcontext->text_input && (imcontext->imdata_size > 0))
3843 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
3847 wayland_im_context_input_panel_imdata_get(Ecore_IMF_Context *ctx, void *data, int *length)
3850 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3852 if (imcontext && imcontext->input_panel_data && (imcontext->input_panel_data_length > 0)) {
3854 memcpy(data, imcontext->input_panel_data, imcontext->input_panel_data_length);
3857 *length = imcontext->input_panel_data_length;
3865 // TIZEN_ONLY(20160218): Support BiDi direction
3867 wayland_im_context_bidi_direction_set(Ecore_IMF_Context *ctx, Ecore_IMF_BiDi_Direction bidi_direction)
3869 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3870 if (!imcontext) return;
3872 imcontext->bidi_direction = bidi_direction;
3874 if (imcontext->input && imcontext->text_input) {
3875 LOGD ("ctx : %p, bidi direction : %#x", ctx, bidi_direction);
3876 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
3881 Ecore_IMF_Input_Panel_Keyboard_Mode
3882 wayland_im_context_input_panel_keyboard_mode_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3884 return hw_keyboard_mode ? ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE : ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE;
3888 wayland_im_context_prediction_hint_set (Ecore_IMF_Context *ctx, const char *prediction_hint)
3890 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3891 if (!imcontext) return;
3893 imcontext->prediction_hint = strdup(prediction_hint ? prediction_hint : "");
3895 if (imcontext->input && imcontext->text_input) {
3896 SECURE_LOGD ("ctx : %p, prediction_hint : %s", ctx, imcontext->prediction_hint);
3897 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
3902 wayland_im_context_mime_type_accept_set (Ecore_IMF_Context *ctx, const char *mime_type)
3904 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3905 if (!imcontext) return;
3907 imcontext->mime_type = strdup(mime_type);
3909 if (imcontext->input && imcontext->text_input && (strlen(mime_type) > 0)) {
3910 LOGD ("ctx : %p, mime_type : %s", ctx, imcontext->mime_type);
3911 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
3916 wayland_im_context_input_panel_position_set (Ecore_IMF_Context *ctx, int x, int y)
3918 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3919 if (!imcontext) return;
3921 if ((imcontext->input_panel_position.x != x) || (imcontext->input_panel_position.y != y)) {
3922 imcontext->input_panel_position.x = x;
3923 imcontext->input_panel_position.y = y;
3926 if (imcontext->input && imcontext->text_input) {
3927 LOGD ("ctx : %p, x = %d, y = %d", ctx, x, y);
3928 wl_text_input_set_input_panel_position(imcontext->text_input,
3929 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
3933 WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager)
3935 WaylandIMContext *context = calloc(1, sizeof(WaylandIMContext));
3937 LOGD("new context created");
3938 context->text_input_manager = text_input_manager;
3944 void wayland_im_context_pair_set (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
3946 _ecore_imf_wayland_imcontext_pair_add (ctx, imcontext);