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
59 #define MAX_WAIT_FOR_WL_SERVER 5.0
61 #define MOD_SHIFT_MASK 0x01
62 #define MOD_CAPS_MASK 0x02
63 #define MOD_CONTROL_MASK 0x04
64 #define MOD_ALT_MASK 0x08
65 #define MOD_SUPER_MASK 0x20
66 #define MOD_NUM_MASK 0x100
67 #define MOD_Mod5_MASK 0x80
69 #define VCONFKEY_AUTOPERIOD_ALLOW_BOOL "file/private/isf/autoperiod_allow"
70 #define VCONFKEY_AUTOCAPITAL_ALLOW_BOOL "file/private/isf/autocapital_allow"
71 #define SOCK_PATH "/run/.isf/scim-panel-socket"
76 INPUT_LANG_BENGALI_IN,
77 INPUT_LANG_BENGALI_BD,
92 INPUT_LANG_ASSAMESE_BN,
93 INPUT_LANG_BENGALI_AS,
97 INPUT_LANG_MANIPURI_AS,
98 INPUT_LANG_MANIPURI_BN,
103 const double DOUBLE_SPACE_INTERVAL = 1.0;
105 static Eina_Bool _clear_hide_timer();
106 static Ecore_Timer *_hide_timer = NULL;
108 static const char *_ecore_imf_event_empty = "";
110 static Eina_Bool will_hide = EINA_FALSE;
111 static Eina_Bool ignore_hide = EINA_FALSE;
113 static Ecore_Event_Filter *_ecore_event_filter_handler = NULL;
114 static Ecore_IMF_Context *_focused_ctx = NULL;
115 static Ecore_IMF_Context *_show_req_ctx = NULL;
116 static Ecore_IMF_Context *_hide_req_ctx = NULL;
117 static Ecore_IMF_Context *_focus_req_ctx = NULL;
118 static Ecore_IMF_Context *_input_panel_ctx = NULL;
119 static Eina_Bool _focus_req_only = EINA_TRUE;
121 static Eina_Rectangle _keyboard_geometry = {0, 0, 0, 0};
122 static Eina_Bool _keyboard_geometry_notified = EINA_FALSE;
124 static Ecore_IMF_Input_Panel_State _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
125 static Ecore_Event_Handler *_win_focus_out_handler = NULL;
126 static Ecore_Event_Handler *_win_focus_in_handler = NULL;
127 static Ecore_Event_Handler *_conformant_change_handler = NULL;
129 static Eina_Bool _custom_conformant_event = EINA_FALSE;
130 static Eina_Bool _received_will_hide_event = EINA_FALSE;
131 static Eina_Bool _conformant_reset_done = EINA_FALSE;
132 static Eina_Bool _conformant_reset_started = EINA_FALSE;
133 static Evas *_active_context_canvas = NULL;
134 static unsigned int _active_context_window_id = 0;
136 static Ecore_Device *_ime_device = NULL;
138 static double space_key_time = 0.0;
139 static Eina_Bool autoperiod_allow = EINA_FALSE;
140 static Eina_Bool autocap_allow = EINA_FALSE;
141 static Eina_Bool hw_keyboard_mode = EINA_FALSE;
142 static Eina_Bool _preedit_cursor_changed = EINA_FALSE;
144 static Input_Language input_lang = INPUT_LANG_OTHER;
146 static void set_autocapital (Ecore_IMF_Context *ctx);
148 static Eina_Bool g_key_rate_checked = EINA_FALSE, g_focused = EINA_FALSE;
149 static double g_original_key_rate = 0.0, g_original_key_delay = 0.0, g_desired_key_rate = 0.0;
150 static double g_filter_event_elapsed_time = 0.0;
151 static int g_last_key_event_serial = 0;
154 typedef struct __LanguageInfo {
157 Eina_Unicode punc_code;
160 static LanguageInfo __language_infos [] = {
161 { "ur_PK", INPUT_LANG_URDU, 0x06D4 },
162 { "hi_IN", INPUT_LANG_HINDI, 0x0964 },
163 { "bn_IN", INPUT_LANG_BENGALI_IN, 0x0964 },
164 { "bn_BD", INPUT_LANG_BENGALI_BD, 0x0964 },
165 { "as_IN", INPUT_LANG_ASSAMESE, 0x0964 },
166 { "pa_IN", INPUT_LANG_PUNJABI, 0x0964 },
167 { "ne_NP", INPUT_LANG_NEPALI, 0x0964 },
168 { "or_IN", INPUT_LANG_ORIYA, 0x0964 },
169 { "mai_IN", INPUT_LANG_MAITHILI, 0x0964 },
170 { "hy_AM", INPUT_LANG_ARMENIAN, 0x0589 },
171 { "zh_CN", INPUT_LANG_CN, 0x3002 },
172 { "zh_HK", INPUT_LANG_CN_HK, 0x3002 },
173 { "zh_TW", INPUT_LANG_CN_TW, 0x3002 },
174 { "ja_JP", INPUT_LANG_JAPANESE, 0x3002 },
175 { "km_KH", INPUT_LANG_KHMER, 0x17D4 },
176 { "ko_KR", INPUT_LANG_KOREAN, 0x002E },
177 { "asb_IN", INPUT_LANG_ASSAMESE_BN, 0x0964 },
178 { "bna_IN", INPUT_LANG_BENGALI_AS, 0x0964 },
179 { "brx_IN", INPUT_LANG_BODO, 0x0964 },
180 { "doi_IN", INPUT_LANG_DOGRI, 0x0964 },
181 { "mni_IN", INPUT_LANG_MANIPURI, 0xabeb },
182 { "mnia_IN",INPUT_LANG_MANIPURI_AS, 0x0964 },
183 { "mnib_IN",INPUT_LANG_MANIPURI_BN, 0x0964 },
184 { "kok_IN", INPUT_LANG_KONKANI, 0x0964 },
185 { "sd_IN", INPUT_LANG_SINDHI, 0x0964 },
188 static const char *hide_keys [] = {
190 "XF86Back", // BACK_KEY
191 "XF86Stop" // OLD_BACK_KEY
194 struct _WaylandIMContext
196 Ecore_IMF_Context *ctx;
198 struct wl_text_input_manager *text_input_manager;
199 struct wl_text_input *text_input;
201 Ecore_Wl2_Window *window;
202 Ecore_Wl2_Input *input;
206 char *preedit_commit;
208 Eina_List *preedit_attrs;
209 int32_t preedit_cursor;
217 int32_t cursor_position;
227 xkb_mod_mask_t control_mask;
228 xkb_mod_mask_t alt_mask;
229 xkb_mod_mask_t shift_mask;
230 xkb_mod_mask_t caps_mask;
231 xkb_mod_mask_t num_mask;
232 xkb_mod_mask_t super_mask;
235 uint32_t content_purpose;
236 uint32_t content_hint;
237 Ecore_IMF_Input_Panel_Layout input_panel_layout;
239 // TIZEN_ONLY(20150716): Support return key type
240 uint32_t return_key_type;
242 Eina_Bool return_key_disabled;
245 uint32_t imdata_size;
247 uint32_t bidi_direction;
249 void *input_panel_data;
250 uint32_t input_panel_data_length;
256 } last_key_event_filter;
257 Eina_List *keysym_list;
259 uint32_t reset_serial;
261 Eina_Bool has_conformant;
262 char *prediction_hint;
269 } input_panel_position;
274 Ecore_IMF_Context *ctx;
275 WaylandIMContext *imcontext;
276 } Ecore_Imf_Wayland_Imcontext_Pair;
277 Eina_List *_ecore_imf_wayland_imcontext_pair_list = NULL;
279 static void _ecore_imf_wayland_imcontext_pair_add (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
281 Ecore_Imf_Wayland_Imcontext_Pair *pair = malloc (sizeof (Ecore_Imf_Wayland_Imcontext_Pair));
284 pair->imcontext = imcontext;
286 _ecore_imf_wayland_imcontext_pair_list = eina_list_append (_ecore_imf_wayland_imcontext_pair_list, pair);
290 static Ecore_Imf_Wayland_Imcontext_Pair* _ecore_imf_wayland_imcontext_pair_find (Ecore_IMF_Context *ctx)
293 Ecore_Imf_Wayland_Imcontext_Pair *pair;
294 EINA_LIST_FOREACH (_ecore_imf_wayland_imcontext_pair_list, l, pair) {
295 if (pair && pair->ctx == ctx) {
299 LOGE("The Ecore_Imf %p if not found in Ecore_IMF-WaylandIMContext pair list!!", ctx);
303 static void _ecore_imf_wayland_imcontext_pair_del (Ecore_IMF_Context *ctx)
307 Ecore_Imf_Wayland_Imcontext_Pair *pair;
309 EINA_LIST_FOREACH_SAFE (_ecore_imf_wayland_imcontext_pair_list, l, l_next, pair)
310 if (ctx == pair->ctx) {
312 _ecore_imf_wayland_imcontext_pair_list = eina_list_remove_list (_ecore_imf_wayland_imcontext_pair_list, l);
316 static void _ecore_imf_wayland_imcontext_pair_destroy ()
318 if (_ecore_imf_wayland_imcontext_pair_list) {
319 Ecore_Imf_Wayland_Imcontext_Pair *pair;
320 EINA_LIST_FREE (_ecore_imf_wayland_imcontext_pair_list, pair)
322 _ecore_imf_wayland_imcontext_pair_list = NULL;
326 static int _ecore_imf_wayland_imcontext_pair_log ()
328 char buffer[255] = { '\0' };
331 Ecore_Imf_Wayland_Imcontext_Pair *pair;
332 EINA_LIST_FOREACH(_ecore_imf_wayland_imcontext_pair_list, l, pair) {
334 snprintf(buffer + strlen(buffer), 255 - strlen(buffer), "%s[%p/%p]", (count ? "," : ""), pair->ctx, pair->imcontext);
339 LOGD("No Ecore_Imf / Wayland_Imcontext pair found");
341 LOGD("%d Pair(s) : %s", count, buffer);
347 // TIZEN_ONLY(20150708): Support back key
348 static void _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant);
349 static Eina_Bool show_input_panel(Ecore_IMF_Context *ctx);
352 reset_keyboard_geometry ()
354 _keyboard_geometry.x = 0;
355 _keyboard_geometry.y = 0;
356 _keyboard_geometry.w = 0;
357 _keyboard_geometry.h = 0;
358 _keyboard_geometry_notified = EINA_FALSE;
362 _device_info_free (void *data EINA_UNUSED, void *ev)
364 Ecore_Event_Device_Info *e;
367 eina_stringshare_del (e->name);
368 eina_stringshare_del (e->identifier);
369 eina_stringshare_del (e->seatname);
375 _device_info_send (unsigned int window, Eina_Bool flag)
377 Ecore_Event_Device_Info *e;
379 if (!(e = calloc (1, sizeof (Ecore_Event_Device_Info)))) return;
381 e->name = eina_stringshare_ref (IME_DEVICE_NAME);
382 e->identifier = eina_stringshare_ref (IME_DEVICE_NAME);
383 e->seatname = eina_stringshare_ref (IME_DEVICE_NAME);
384 e->clas = ECORE_DEVICE_CLASS_KEYBOARD;
385 e->subclas = ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD;
389 ecore_event_add (ECORE_EVENT_DEVICE_ADD, e, _device_info_free, NULL);
391 ecore_event_add (ECORE_EVENT_DEVICE_DEL, e, _device_info_free, NULL);
395 set_input_language (const char *input_lang_str)
398 input_lang = INPUT_LANG_OTHER;
400 for (i = 0; i < (sizeof (__language_infos) / sizeof (__language_infos[0])); i++) {
401 if (strcmp (input_lang_str, __language_infos[i].code) == 0) {
402 input_lang = __language_infos[i].lang;
408 static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
410 autoperiod_allow = vconf_keynode_get_bool (key);
413 static void autocapital_allow_changed_cb (keynode_t *key, void* data)
415 autocap_allow = vconf_keynode_get_bool (key);
418 static void input_language_changed_cb (keynode_t *key, void* data)
420 char *input_lang = vconf_keynode_get_str (key);
422 set_input_language (input_lang);
423 LOGD("input lang : %s", input_lang);
428 check_symbol (Eina_Unicode ucode, Eina_Unicode symbols[], int symbol_num)
431 for (i = 0; i < symbol_num; i++) {
433 if (ucode == symbols[i])
441 check_space_symbol (Eina_Unicode uchar)
443 Eina_Unicode space_symbols[] = {' ', 0x00A0 /* no-break space */, 0x3000 /* ideographic space */};
444 const int symbol_num = sizeof (space_symbols) / sizeof (space_symbols[0]);
446 return check_symbol (uchar, space_symbols, symbol_num);
450 autoperiod_insert (Ecore_IMF_Context *ctx)
452 char *plain_str = NULL;
454 Eina_Unicode *ustr = NULL;
455 Ecore_IMF_Event_Delete_Surrounding ev;
456 char *fullstop_mark = NULL;
459 WaylandIMContext *imcontext = NULL;
461 if (autoperiod_allow == EINA_FALSE)
466 Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
467 if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
470 if ((ecore_time_get () - space_key_time) > DOUBLE_SPACE_INTERVAL)
473 imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
474 if (!imcontext) return;
476 ecore_imf_context_surrounding_get (ctx, &plain_str, NULL);
477 if (!plain_str) goto done;
479 cursor_pos = imcontext->cursor_position;
481 // Convert string from UTF-8 to unicode
482 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
483 if (!ustr) goto done;
485 ulen = eina_unicode_strlen (ustr);
487 if (cursor_pos < 2 || cursor_pos > (int)ulen) {
488 LOGD ("invalid range. cursor pos : %d, length : %zu", cursor_pos, ulen);
492 if (check_space_symbol (ustr[cursor_pos-1])) {
493 // any character (except space & punctuation) + press space key twice in short time
494 if (!(iswpunct (ustr[cursor_pos-2]) || check_space_symbol (ustr[cursor_pos-2])) &&
495 iswprint(ustr[cursor_pos-2])) {
498 // any character (except space & punctuation) + space + press space key twice in short time
499 else if (cursor_pos >= 3 &&
500 check_space_symbol (ustr[cursor_pos-2]) &&
501 !(iswpunct (ustr[cursor_pos-3]) || check_space_symbol (ustr[cursor_pos-3])) &&
502 iswprint(ustr[cursor_pos-3])) {
508 ev.n_chars = del_chars;
509 ev.offset = del_chars * -1;
511 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
513 if (input_lang == INPUT_LANG_OTHER) {
514 fullstop_mark = strdup (".");
517 Eina_Unicode wbuf[2] = {0};
518 wbuf[0] = __language_infos[input_lang].punc_code;
520 fullstop_mark = eina_unicode_unicode_to_utf8 (wbuf, NULL);
523 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)fullstop_mark);
526 free (fullstop_mark);
527 fullstop_mark = NULL;
533 if (plain_str) free (plain_str);
534 if (ustr) free (ustr);
535 space_key_time = ecore_time_get ();
539 check_except_autocapital (Eina_Unicode *ustr, int cursor_pos)
541 const char *except_str[] = {"e.g.", "E.g."};
542 unsigned int i = 0, j = 0, len = 0;
543 for (i = 0; i < (sizeof (except_str) / sizeof (except_str[0])); i++) {
544 len = strlen (except_str[i]);
545 if (cursor_pos < (int)len)
548 for (j = len; j > 0; j--) {
549 if (ustr[cursor_pos-j] != except_str[i][len-j])
553 if (j == 0) return EINA_TRUE;
560 analyze_surrounding_text (Ecore_IMF_Context *ctx)
562 char *plain_str = NULL;
563 Eina_Unicode puncs[] = {'\n','.', '!', '?', 0x00BF /* ¿ */, 0x00A1 /* ¡ */,
564 0x3002 /* 。 */, 0x06D4 /* Urdu */, 0x0964 /* Hindi */,
565 0x0589 /* Armenian */, 0x17D4 /* Khmer */, 0x104A /* Myanmar */};
566 Eina_Unicode *ustr = NULL;
567 Eina_Bool ret = EINA_FALSE;
568 Eina_Bool detect_space = EINA_FALSE;
571 const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
572 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
573 if (!imcontext) return EINA_FALSE;
575 switch (ecore_imf_context_autocapital_type_get (ctx)) {
576 case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
578 case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
584 if (imcontext->preedit_text && strcmp (imcontext->preedit_text, "") != 0)
587 if (imcontext->cursor_position == 0)
590 ecore_imf_context_surrounding_get (ctx, &plain_str, &cursor_pos);
592 if (!plain_str) goto done;
594 if (cursor_pos == 0) {
599 // Convert string from UTF-8 to unicode
600 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
601 if (!ustr) goto done;
603 if (eina_unicode_strlen (ustr) < (size_t)cursor_pos) goto done;
605 if (cursor_pos >= 1) {
606 if (ecore_imf_context_autocapital_type_get (ctx) == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
607 // Check space or no-break space
608 if (check_space_symbol (ustr[cursor_pos-1])) {
614 // Check paragraph separator <PS> or carriage return <br>
615 if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
620 for (i = cursor_pos; i > 0; i--) {
621 // Check space or no-break space
622 if (check_space_symbol (ustr[i-1])) {
623 detect_space = EINA_TRUE;
627 // Check punctuation and following the continuous space(s)
628 if (detect_space && check_symbol (ustr[i-1], puncs, punc_num)) {
629 if (check_except_autocapital (ustr, i))
641 if ((i == 0) && (detect_space == EINA_TRUE)) {
642 // continuous space(s) without any character
649 if (ustr) free (ustr);
650 if (plain_str) free (plain_str);
656 set_autocapital (Ecore_IMF_Context *ctx)
658 Eina_Bool uppercase = EINA_FALSE;
660 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
661 if (!imcontext || !imcontext->text_input || !imcontext->input) return;
663 if (hw_keyboard_mode) return;
665 if (ecore_imf_context_input_panel_layout_get (ctx) != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
668 // Check autocapital type
669 if (ecore_imf_context_input_panel_caps_lock_mode_get (ctx)) {
670 uppercase = EINA_TRUE;
672 if (autocap_allow == EINA_FALSE)
675 uppercase = analyze_surrounding_text (ctx);
678 LOGD ("ctx : %p, auto capital : %d", ctx, uppercase);
679 wl_text_input_set_capital_mode (imcontext->text_input, uppercase);
682 static Ecore_IMF_Context *
685 return (_show_req_ctx ? _show_req_ctx : _focused_ctx);
689 check_hide_key(const char *keyname)
691 if (!keyname) return EINA_FALSE;
694 for (i = 0; i < (sizeof(hide_keys) / sizeof(hide_keys[0])); i++) {
695 if (strcmp(keyname, hide_keys[i]) == 0) {
704 _ecore_key_modifiers_to_ecore_imf_locks(unsigned int modifiers)
706 unsigned int locks = 0;
708 if (modifiers & ECORE_EVENT_LOCK_SCROLL)
709 locks |= ECORE_IMF_KEYBOARD_LOCK_SCROLL;
711 if (modifiers & ECORE_EVENT_LOCK_CAPS)
712 locks |= ECORE_IMF_KEYBOARD_LOCK_CAPS;
714 if (modifiers & ECORE_EVENT_LOCK_NUM)
715 locks |= ECORE_IMF_KEYBOARD_LOCK_NUM;
721 _ecore_key_modifiers_to_ecore_imf_modifiers(unsigned int modifiers)
723 unsigned int mask = 0;
725 /**< "Control" is pressed */
726 if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
727 mask |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
729 /**< "Alt" is pressed */
730 if (modifiers & ECORE_EVENT_MODIFIER_ALT)
731 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
733 /**< "Shift" is pressed */
734 if (modifiers & ECORE_EVENT_MODIFIER_SHIFT)
735 mask |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT;
737 /**< "Win" (between "Ctrl" and "Alt") is pressed */
738 if (modifiers & ECORE_EVENT_MODIFIER_WIN)
739 mask |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
741 /**< "AltGr" is pressed */
742 if (modifiers & ECORE_EVENT_MODIFIER_ALTGR)
743 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
749 _ecore_event_to_ecore_imf_key_down_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Down *imf_event)
751 if (!ecore_event || !imf_event)
754 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
755 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
756 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
757 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
758 imf_event->timestamp = ecore_event->timestamp;
760 if (ecore_event->dev) {
761 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
762 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
763 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
766 imf_event->dev_name = _ecore_imf_event_empty;
767 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
768 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
771 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
772 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
776 _ecore_event_to_ecore_imf_key_up_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Up *imf_event)
778 if (!ecore_event || !imf_event)
781 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
782 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
783 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
784 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
785 imf_event->timestamp = ecore_event->timestamp;
787 if (ecore_event->dev) {
788 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
789 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
790 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
793 imf_event->dev_name = _ecore_imf_event_empty;
794 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
795 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
798 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
799 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
802 static Eina_Bool check_nograb_backkey()
804 char *nograb_backkey = getenv ("ISF_KEY_NOGRAB_BACKKEY");
805 if (nograb_backkey) {
806 if (atoi (nograb_backkey) != 0)
807 return EINA_TRUE; /* the event is kept */
814 key_down_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
816 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
817 if (!ev || !ev->keyname) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
819 Ecore_IMF_Context *active_ctx = get_using_ctx ();
821 if (!active_ctx) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
823 if ((_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW ||
824 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW) &&
825 check_hide_key(ev->keyname)) {
827 if (ev->event_flags & ECORE_EVENT_FLAG_CANCEL) {
828 SECURE_LOGD ("%s key is cancelled.", ev->keyname);
829 return ECORE_CALLBACK_PASS_ON;
832 SECURE_LOGD ("%s key is pressed.", ev->keyname);
834 Ecore_IMF_Event_Key_Down imf_event;
835 Eina_Bool filter_ret = EINA_FALSE;
837 _ecore_event_to_ecore_imf_key_down_event(ev, &imf_event);
840 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_DOWN, (Ecore_IMF_Event *)&imf_event);
843 if (check_nograb_backkey())
844 return ECORE_CALLBACK_PASS_ON; /* the event is kept */
847 SECURE_LOGD ("%s key is pressed. ret : %d", ev->keyname, filter_ret);
848 return ECORE_CALLBACK_DONE; /* the event is removed from the queue */
850 return ECORE_CALLBACK_PASS_ON; /* the event is kept */
854 key_up_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
856 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
857 if (!ev || !ev->keyname) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
859 Ecore_IMF_Context *active_ctx = get_using_ctx ();
861 if (!active_ctx) return ECORE_CALLBACK_PASS_ON; /* the event is kept */
863 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE ||
864 !check_hide_key(ev->keyname))
865 return ECORE_CALLBACK_PASS_ON; /* the event is kept */
867 if (ev->event_flags & ECORE_EVENT_FLAG_CANCEL) {
868 SECURE_LOGD ("%s key is cancelled.", ev->keyname);
869 return ECORE_CALLBACK_PASS_ON;
872 SECURE_LOGD ("%s key is released.", ev->keyname);
874 Ecore_IMF_Event_Key_Up imf_event;
875 Eina_Bool filter_ret = EINA_FALSE;
877 _ecore_event_to_ecore_imf_key_up_event(ev, &imf_event);
880 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_UP, (Ecore_IMF_Event *)&imf_event);
884 SECURE_LOGD ("%s key is released. ret : %d", ev->keyname, filter_ret);
886 return ECORE_CALLBACK_DONE; /* the event is removed from the queue */
889 if (check_nograb_backkey())
890 return ECORE_CALLBACK_PASS_ON; /* the event is kept */
892 ecore_imf_context_reset(active_ctx);
893 _input_panel_hide(active_ctx, EINA_TRUE);
894 return ECORE_CALLBACK_DONE; /* the event is removed from the queue */
899 rotary_event_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
901 Ecore_Event_Detent_Rotate *ev = event;
902 if (!ev) return ECORE_CALLBACK_PASS_ON;
904 Ecore_IMF_Context *active_ctx = NULL;
906 active_ctx = _show_req_ctx;
907 else if (_focused_ctx)
908 active_ctx = _focused_ctx;
910 if (!active_ctx) return ECORE_CALLBACK_PASS_ON;
912 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
913 return ECORE_CALLBACK_PASS_ON;
915 ecore_imf_context_reset(active_ctx);
916 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(active_ctx);
917 if (imcontext && imcontext->input && imcontext->text_input) {
918 isf_device_type_e device_type = find_device_type_from_ecore_event(ECORE_EVENT_DETENT_ROTATE);
922 if (device_buffer_encode((const char*)(event), sizeof(Ecore_Event_Detent_Rotate), &buffer, &buflen) &&
923 buffer && buflen > 0) {
924 wl_text_input_process_input_device_event(imcontext->text_input,
925 (unsigned int)device_type, buffer, buflen);
927 if (buffer) free(buffer);
930 return ECORE_CALLBACK_DONE;
934 _ecore_event_filter_cb(void *data, void *loop_data EINA_UNUSED, int type, void *event)
936 if (type == ECORE_EVENT_KEY_DOWN) {
937 return key_down_filter_cb(data, type, event);
939 else if (type == ECORE_EVENT_KEY_UP) {
940 return key_up_filter_cb(data, type, event);
942 /* The IME needs to process Rotary event prior to client application */
943 else if (type == ECORE_EVENT_DETENT_ROTATE) {
944 return rotary_event_cb(data, type, event);
947 return ECORE_CALLBACK_PASS_ON;
951 register_key_handler()
953 if (!_ecore_event_filter_handler)
954 _ecore_event_filter_handler = ecore_event_filter_add(NULL, _ecore_event_filter_cb, NULL, NULL);
958 unregister_key_handler()
960 if (_ecore_event_filter_handler) {
961 ecore_event_filter_del(_ecore_event_filter_handler);
962 _ecore_event_filter_handler = NULL;
973 LOGD("Delete hide timer");
974 ecore_timer_del(_hide_timer);
982 static void _win_focus_in_handler_del()
984 if (_win_focus_in_handler) {
985 ecore_event_handler_del(_win_focus_in_handler);
986 _win_focus_in_handler = NULL;
990 static void _win_focus_out_handler_del ()
992 if (_win_focus_out_handler) {
993 ecore_event_handler_del (_win_focus_out_handler);
994 _win_focus_out_handler = NULL;
998 static void _conformant_change_handler_del()
1000 if (_conformant_change_handler) {
1001 ecore_event_handler_del(_conformant_change_handler);
1002 _conformant_change_handler = NULL;
1007 _send_input_panel_hide_request(Ecore_IMF_Context *ctx)
1011 // TIZEN_ONLY(20150708): Support back key
1012 _hide_req_ctx = NULL;
1015 _win_focus_out_handler_del ();
1017 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1018 if (imcontext && imcontext->text_input) {
1019 LOGD("Send IME hide request");
1020 wl_text_input_hide_input_panel(imcontext->text_input);
1022 LOGD("creating temporary context for sending hide request");
1023 const char *ctx_id = ecore_imf_context_default_id_get();
1024 Ecore_IMF_Context *temp_context = ecore_imf_context_add(ctx_id);
1026 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(temp_context);
1027 if (imcontext && imcontext->text_input) {
1028 LOGD("Send IME hide request");
1029 wl_text_input_hide_input_panel(imcontext->text_input);
1032 ecore_imf_context_del(temp_context);
1037 static void _conformant_area_free (void *data EINA_UNUSED, void *ev)
1039 Ecore_Wl2_Event_Conformant_Change *e = ev;
1044 static void add_conformant_change_event(Ecore_Wl2_Window *window)
1046 Ecore_Wl2_Event_Conformant_Change *ev;
1047 ev = calloc(1, sizeof(Ecore_Wl2_Event_Conformant_Change));
1049 ev->win = ecore_wl2_window_id_get(window);
1052 ecore_event_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, ev, _conformant_area_free, NULL);
1056 static Eina_Rectangle _conformant_area_backup = { 0, 0, 0, 0 };
1057 static Eina_Bool reset_conformant_area(Ecore_IMF_Context *ctx)
1059 Eina_Bool reset = EINA_FALSE;
1060 Eina_Bool has_conformant = EINA_FALSE;
1061 Ecore_Wl2_Window *window = NULL;
1063 if (!ctx) return EINA_FALSE;
1065 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1067 window = imcontext->window;
1068 has_conformant = imcontext->has_conformant;
1072 int x = 0, y = 0, w = 0, h = 0;
1073 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1076 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w != 0 || h != 0)) {
1078 _conformant_area_backup.x = x;
1079 _conformant_area_backup.y = y;
1080 _conformant_area_backup.w = w;
1081 _conformant_area_backup.h = h;
1085 LOGD("reset %d", reset);
1087 ecore_wl2_window_keyboard_geometry_set(window, 0, 0, 0, 0);
1089 add_conformant_change_event(window);
1091 _conformant_reset_started = EINA_TRUE;
1097 static void restore_conformant_area(Ecore_IMF_Context *ctx)
1099 Eina_Bool restore = EINA_FALSE;
1100 Eina_Bool has_conformant = EINA_FALSE;
1101 Ecore_Wl2_Window *window = NULL;
1105 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1107 window = imcontext->window;
1108 has_conformant = imcontext->has_conformant;
1112 int x = 0, y = 0, w = 0, h = 0;
1113 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1116 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w == 0 || h == 0)) {
1117 restore = EINA_TRUE;
1121 LOGD("restore %d", restore);
1123 ecore_wl2_window_keyboard_geometry_set(window,
1124 _conformant_area_backup.x, _conformant_area_backup.y,
1125 _conformant_area_backup.w, _conformant_area_backup.h);
1127 add_conformant_change_event(window);
1129 _conformant_reset_started = EINA_FALSE;
1134 _send_will_hide_ack(WaylandIMContext *imcontext)
1136 if (!imcontext) return;
1137 if (!(imcontext->text_input)) return;
1139 const char *szWillHideAck = "WILL_HIDE_ACK";
1140 wl_text_input_set_input_panel_data(imcontext->text_input, szWillHideAck, strlen(szWillHideAck));
1141 _received_will_hide_event = EINA_FALSE;
1145 _hide_timer_handler(void *data)
1147 LOGD("Start hide timer");
1148 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1149 _send_input_panel_hide_request(ctx);
1151 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1152 LOGD("No need to reset conformant, sending ACK right away");
1153 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1157 reset_keyboard_geometry();
1160 return ECORE_CALLBACK_CANCEL;
1164 _input_panel_hide_timer_start(void *data)
1167 LOGD("Add timer to hide input panel");
1168 _hide_timer = ecore_timer_add(HIDE_TIMER_INTERVAL, _hide_timer_handler, data);
1173 _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant)
1175 LOGD ("ctx : %p", ctx);
1179 will_hide = EINA_TRUE;
1180 if (instant || (_hide_timer && ecore_timer_pending_get(_hide_timer) <= 0.0)) {
1181 _clear_hide_timer();
1182 _send_input_panel_hide_request(ctx);
1184 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1185 LOGD("No need to reset conformant, sending ACK right away");
1186 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1190 reset_keyboard_geometry();
1192 _input_panel_hide_timer_start(ctx);
1193 // TIZEN_ONLY(20150708): Support back key
1194 _hide_req_ctx = ctx;
1200 utf8_offset_to_characters(const char *str, int offset)
1205 for (; index < offset; i++) {
1206 if (eina_unicode_utf8_next_get(str, &index) == 0)
1214 send_cursor_location(WaylandIMContext *imcontext)
1216 #if ENABLE_SEND_CURSOR_LOCATION
1217 Ecore_Evas *ee = NULL;
1218 int canvas_x = 0, canvas_y = 0;
1220 if (imcontext->canvas) {
1221 ee = ecore_evas_ecore_evas_get(imcontext->canvas);
1223 ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
1226 if (imcontext->input && imcontext->text_input) {
1227 wl_text_input_set_cursor_rectangle(imcontext->text_input,
1228 imcontext->cursor_location.x + canvas_x,
1229 imcontext->cursor_location.y + canvas_y,
1230 imcontext->cursor_location.width,
1231 imcontext->cursor_location.height);
1237 update_state(WaylandIMContext *imcontext)
1239 if (!imcontext->ctx)
1242 send_cursor_location (imcontext);
1244 if (imcontext->input && imcontext->text_input) {
1245 wl_text_input_commit_state(imcontext->text_input, ++imcontext->serial);
1250 check_serial(WaylandIMContext *imcontext, uint32_t serial)
1255 Ecore_IMF_Preedit_Attr *attr;
1257 if ((imcontext->serial - serial) >
1258 (imcontext->serial - imcontext->reset_serial)) {
1259 LOGD("outdated serial: %u, current: %u, reset: %u",
1260 serial, imcontext->serial, imcontext->reset_serial);
1262 imcontext->pending_preedit.cursor = 0;
1264 if (imcontext->pending_preedit.attrs) {
1265 EINA_LIST_FREE(imcontext->pending_preedit.attrs, attr) {
1269 imcontext->pending_preedit.attrs = NULL;
1280 clear_preedit_text(WaylandIMContext *imcontext)
1282 Ecore_IMF_Preedit_Attr *attr = NULL;
1284 imcontext->preedit_cursor = 0;
1286 if (imcontext->preedit_text) {
1287 free(imcontext->preedit_text);
1288 imcontext->preedit_text = NULL;
1291 if (imcontext->preedit_attrs) {
1292 EINA_LIST_FREE(imcontext->preedit_attrs, attr) {
1298 imcontext->preedit_attrs = NULL;
1302 clear_preedit(WaylandIMContext *imcontext)
1304 clear_preedit_text(imcontext);
1306 if (imcontext->preedit_commit) {
1307 free(imcontext->preedit_commit);
1308 imcontext->preedit_commit = NULL;
1313 text_input_commit_string(void *data,
1314 struct wl_text_input *text_input EINA_UNUSED,
1318 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1319 Eina_Bool old_preedit = EINA_FALSE;
1321 SECURE_LOGD("ctx : %p, commit event (text: '%s', current pre-edit: '%s')",
1324 imcontext->preedit_text ? imcontext->preedit_text : "");
1326 if (!imcontext->ctx)
1330 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1332 if (!check_serial(imcontext, serial))
1336 ecore_imf_context_event_callback_call(imcontext->ctx,
1337 ECORE_IMF_CALLBACK_PREEDIT_END,
1341 clear_preedit(imcontext);
1346 Eina_Unicode *ustr = eina_unicode_utf8_to_unicode (text, NULL);
1349 if (eina_unicode_strcmp (ustr, L" ") == 0 ||
1350 eina_unicode_strcmp (ustr, L" ") == 0)
1351 autoperiod_insert (imcontext->ctx);
1356 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)text);
1360 commit_preedit(WaylandIMContext *imcontext)
1362 if (!imcontext->preedit_commit)
1365 if (!imcontext->ctx)
1368 imcontext->pending_preedit.cursor = 0;
1369 clear_preedit_text(imcontext);
1371 size_t commit_len = strlen(imcontext->preedit_commit);
1373 if (commit_len == 0) {
1374 ecore_imf_context_event_callback_call(imcontext->ctx,
1375 ECORE_IMF_CALLBACK_PREEDIT_START,
1378 ecore_imf_context_event_callback_call(imcontext->ctx,
1379 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1382 ecore_imf_context_event_callback_call(imcontext->ctx,
1383 ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
1386 if (commit_len > 0) {
1387 char *commit_str = NULL;
1388 commit_str = strdup(imcontext->preedit_commit);
1389 clear_preedit(imcontext);
1390 ecore_imf_context_event_callback_call(imcontext->ctx,
1391 ECORE_IMF_CALLBACK_COMMIT,
1392 (void *)commit_str);
1398 set_focus(Ecore_IMF_Context *ctx)
1400 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1401 if (!imcontext) return EINA_FALSE;
1403 if (!imcontext->window) {
1404 LOGW("ctx : %p, window is not given", ctx);
1408 if (imcontext->canvas) {
1409 if (!evas_focus_state_get(imcontext->canvas)) {
1410 LOGW("ctx : %p, canvas does not have focus", ctx);
1415 Ecore_Wl2_Input *input = ecore_wl2_window_keyboard_get(imcontext->window);
1417 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1421 struct wl_seat *seat = ecore_wl2_input_seat_get(input);
1423 LOGW("ctx : %p, Can't get Wl_seat", ctx);
1427 imcontext->input = input;
1430 LOGD("ctx : %p, activate wl_text_input : %p", ctx, imcontext->text_input);
1431 wl_text_input_activate(imcontext->text_input, seat,
1432 ecore_wl2_window_surface_get(imcontext->window));
1434 if (g_key_rate_checked == EINA_FALSE && g_desired_key_rate == 0.0) {
1435 char *key_rate = getenv ("ISF_KEY_REPEAT_RATE");
1437 g_desired_key_rate = atof (key_rate);
1438 if (g_desired_key_rate > 0.0) {
1439 if (!ecore_wl2_input_keyboard_repeat_get (input, &g_original_key_rate, &g_original_key_delay)) {
1440 LOGE ("ecore_wl2_input_keyboard_repeat_get failed");
1443 LOGD ("ecore_wl2_input_keyboard_repeat_get original rate=%f, delay=%f. Desired rate=%f",
1444 g_original_key_rate, g_original_key_delay, g_desired_key_rate);
1448 g_key_rate_checked = EINA_TRUE;
1451 if (g_desired_key_rate > 0.0 && g_original_key_delay > 0.0 && !g_focused) {
1452 g_focused = EINA_TRUE;
1453 if (!ecore_wl2_input_keyboard_repeat_set (input, g_desired_key_rate, g_original_key_delay)) {
1454 LOGE ("ecore_wl2_input_keyboard_repeat_set failed");
1457 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_desired_key_rate, g_original_key_delay);
1465 set_focus_out(Ecore_IMF_Context *ctx)
1467 char *surrounding = NULL;
1470 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1471 if (!imcontext || !imcontext->input) return;
1473 if (ecore_imf_context_surrounding_get(ctx, &surrounding, &cursor_pos)) {
1475 wl_text_input_finalize_content(imcontext->text_input, surrounding, cursor_pos);
1480 LOGD("deactivate wl_text_input : %p", imcontext->text_input);
1482 if (imcontext->text_input)
1483 wl_text_input_deactivate(imcontext->text_input,
1484 ecore_wl2_input_seat_get(imcontext->input));
1486 if (ctx == _focused_ctx)
1487 _focused_ctx = NULL;
1489 imcontext->input = NULL;
1490 _preedit_cursor_changed = EINA_FALSE;
1491 g_filter_event_elapsed_time = 0.0;
1492 g_last_key_event_serial = 0;
1494 if (g_desired_key_rate > 0.0 && g_focused) {
1495 g_focused = EINA_FALSE;
1497 Ecore_Wl2_Input *input = ecore_wl2_window_keyboard_get(imcontext->window);
1499 if (!ecore_wl2_input_keyboard_repeat_set (input, g_original_key_rate, g_original_key_delay)) {
1500 LOGE ("ecore_wl2_input_keyboard_repeat_set failed.");
1503 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_original_key_rate, g_original_key_delay);
1507 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1512 // TIZEN_ONLY(20160217): ignore the duplicate show request
1513 static Eina_Bool _compare_context(Ecore_IMF_Context *ctx1, Ecore_IMF_Context *ctx2)
1515 if (!ctx1 || !ctx2) return EINA_FALSE;
1517 if ((ecore_imf_context_autocapital_type_get(ctx1) == ecore_imf_context_autocapital_type_get(ctx2)) &&
1518 (ecore_imf_context_input_panel_layout_get(ctx1) == ecore_imf_context_input_panel_layout_get(ctx2)) &&
1519 (ecore_imf_context_input_panel_layout_variation_get(ctx1) == ecore_imf_context_input_panel_layout_variation_get(ctx2)) &&
1520 (ecore_imf_context_input_panel_language_get(ctx1) == ecore_imf_context_input_panel_language_get(ctx2)) &&
1521 (ecore_imf_context_input_panel_return_key_type_get(ctx1) == ecore_imf_context_input_panel_return_key_type_get(ctx2)) &&
1522 (ecore_imf_context_input_panel_return_key_disabled_get(ctx1) == ecore_imf_context_input_panel_return_key_disabled_get(ctx2)) &&
1523 (ecore_imf_context_input_panel_caps_lock_mode_get(ctx1) == ecore_imf_context_input_panel_caps_lock_mode_get(ctx2)))
1530 static void send_get_hide_permission(WaylandIMContext *imcontext)
1532 if (imcontext->text_input) {
1533 ignore_hide = EINA_FALSE;
1534 wl_text_input_get_hide_permission(imcontext->text_input);
1538 static Eina_Bool _client_window_focus_in_cb(void *data, int ev_type, void *ev)
1540 LOGD("ctx : %p %d", _focus_req_ctx, _focus_req_only);
1542 if (_focus_req_ctx) {
1543 set_focus(_focus_req_ctx);
1544 if (ecore_imf_context_input_panel_enabled_get (_focus_req_ctx) || !_focus_req_only)
1545 if (!ecore_imf_context_input_panel_show_on_demand_get (_focus_req_ctx) || !_focus_req_only)
1546 ecore_imf_context_input_panel_show(_focus_req_ctx);
1548 _win_focus_in_handler_del();
1550 _focus_req_ctx = NULL;
1551 _focus_req_only = EINA_TRUE;
1554 return ECORE_CALLBACK_PASS_ON;
1557 static Eina_Bool _client_window_focus_out_cb(void *data, int ev_type, void *ev)
1559 Ecore_Wl2_Event_Focus_Out *e = (Ecore_Wl2_Event_Focus_Out *)ev;
1560 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1561 if (!ctx || !e) return ECORE_CALLBACK_PASS_ON;
1563 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
1564 if (!imcontext || !imcontext->window) return ECORE_CALLBACK_PASS_ON;
1566 unsigned int client_win_id = ecore_wl2_window_id_get (imcontext->window);
1568 LOGD ("ctx : %p, client_window id : %#x, focus-out win : %#x", ctx, client_win_id, e->window);
1570 if (client_win_id > 0) {
1571 if (e->window == client_win_id) {
1572 LOGD ("window focus out");
1574 if (_focused_ctx == ctx) {
1575 wayland_im_context_focus_out (ctx);
1578 if (_show_req_ctx == ctx) {
1579 send_get_hide_permission(imcontext);
1584 send_get_hide_permission(imcontext);
1587 return ECORE_CALLBACK_PASS_ON;
1590 static void send_will_hide_ack(Ecore_IMF_Context *ctx)
1592 Eina_Bool need_temporary_context = EINA_FALSE;
1593 Eina_Bool has_conformant = EINA_FALSE;
1594 WaylandIMContext *imcontext = NULL;
1597 LOGD("ctx is NULL");
1598 need_temporary_context = EINA_TRUE;
1600 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1602 LOGD("imcontext is NULL :%p", ctx);
1603 need_temporary_context = EINA_TRUE;
1605 has_conformant = imcontext->has_conformant;
1609 /* When the RENDER_POST event is emitted, it is possible that our IMF_Context is already deleted,
1610 meaning that there is no connection available for communicating with the window manager.
1611 So we are creating a temporary context for sending WILL_HIDE_ACK message */
1612 if (need_temporary_context) {
1613 LOGD("creating temporary context for sending WILL_HIDE_ACK");
1614 const char *ctx_id = ecore_imf_context_default_id_get();
1615 ctx = ecore_imf_context_add(ctx_id);
1617 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1621 if (ctx && imcontext) {
1622 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant) {
1623 if (_conformant_reset_done && _received_will_hide_event) {
1624 LOGD("Send will hide ack, _conformant_reset_done = 1, received_will_hide_event = 1");
1625 _send_will_hide_ack(imcontext);
1626 _conformant_reset_done = EINA_FALSE;
1627 _received_will_hide_event = EINA_FALSE;
1629 LOGD ("_conformant_reset_done=%d, received_will_hide_event=%d",
1630 _conformant_reset_done, _received_will_hide_event);
1633 LOGD("Send will hide ack right away, since there is no conformant available : %p %d",
1634 ecore_imf_context_client_canvas_get(ctx), has_conformant);
1635 _send_will_hide_ack (imcontext);
1639 if (need_temporary_context) {
1641 ecore_imf_context_del(ctx);
1646 static void _render_post_cb(void *data, Evas *e, void *event_info)
1648 void *callback = evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1649 _conformant_reset_done = EINA_TRUE;
1650 _conformant_reset_started = EINA_FALSE;
1651 LOGD("[_render_post_cb], _conformant_reset_done = 1 , %p", callback);
1652 send_will_hide_ack(NULL);
1655 static void send_keyboard_geometry_event(Ecore_IMF_Context *ctx)
1657 LOGI ("Send IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
1658 ecore_imf_context_input_panel_event_callback_call(ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
1659 _keyboard_geometry_notified = EINA_TRUE;
1662 static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
1664 Ecore_Wl2_Event_Conformant_Change *e = (Ecore_Wl2_Event_Conformant_Change *)ev;
1665 if (!e) return ECORE_CALLBACK_PASS_ON;
1667 LOGD ("CONFORMANT changed!! part type : %d, state : %d, win : %d", e->part_type, e->state, e->win);
1669 if (_active_context_window_id != e->win)
1670 return ECORE_CALLBACK_PASS_ON;
1672 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1673 if (!wl2_display) return ECORE_CALLBACK_PASS_ON;
1675 Ecore_Wl2_Window *window = ecore_wl2_display_window_find(wl2_display, e->win);
1676 if (!window) return ECORE_CALLBACK_PASS_ON;
1679 LOGD("_conformant_reset_done = 0, registering _render_post_cb : %p %p", _active_context_canvas, window);
1680 _conformant_reset_done = EINA_FALSE;
1681 if (_active_context_canvas && ecore_wl2_window_conformant_get(window) && !_custom_conformant_event) {
1682 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1683 evas_event_callback_add(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb, NULL);
1686 _conformant_reset_done = EINA_FALSE;
1687 if (_active_context_canvas) {
1688 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1691 Eina_Bool result = EINA_FALSE;
1692 int x = 0, y = 0, w = 0, h = 0;
1695 /* TV IME consists of two or three windows, so ecore_wl2_window_keyboard_geometry_get() may return wrong size. */
1696 x = _keyboard_geometry.x, y = _keyboard_geometry.y, w = _keyboard_geometry.w, h = _keyboard_geometry.h;
1697 if (_keyboard_geometry.w == 0 || _keyboard_geometry.h == 0) {
1698 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1701 /* Since the input_panel_geometry is not delivered right at the moment, we use conformant geometry instead */
1702 x = 0, y = 0, w = 0, h = 0;
1703 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1707 Evas_Coord scr_w = 0, scr_h = 0;
1709 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1711 ecore_wl2_display_screen_size_get(wl2_display ,&scr_w, &scr_h);
1712 int rot = ecore_wl2_window_rotation_get(window);
1713 /* Assume we are using keyboard that has the same width to the screen width*/
1716 _keyboard_geometry.h = w;
1717 _keyboard_geometry.w = h;
1718 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1719 _keyboard_geometry.x = 0;
1722 _keyboard_geometry.w = w;
1723 _keyboard_geometry.h = h;
1724 _keyboard_geometry.x = 0;
1725 _keyboard_geometry.y = scr_h - _keyboard_geometry.h;
1728 _keyboard_geometry.h = w;
1729 _keyboard_geometry.w = h;
1730 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1731 _keyboard_geometry.x = 0;
1734 _keyboard_geometry.x = x;
1735 _keyboard_geometry.y = y;
1736 _keyboard_geometry.w = w;
1737 _keyboard_geometry.h = h;
1739 _keyboard_geometry_notified = EINA_FALSE;
1741 LOGI ("[KEYPAD]: scr %dx%d, rot %d, orig (%d,%d, %dx%d)", scr_w, scr_h, rot, x, y, w, h);
1742 LOGI ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
1745 send_keyboard_geometry_event(_show_req_ctx);
1749 return ECORE_CALLBACK_PASS_ON;
1753 get_purpose(Ecore_IMF_Context *ctx)
1755 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1756 uint32_t new_purpose = 0;
1758 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1762 switch (imcontext->content_purpose) {
1763 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
1764 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED)
1765 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED;
1766 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL)
1767 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL;
1768 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL)
1769 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL;
1771 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
1773 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
1774 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY)
1775 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS;
1777 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
1779 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
1780 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME)
1781 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME;
1782 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME)
1783 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NAME;
1785 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
1788 new_purpose = imcontext->content_purpose;
1795 static void _canvas_focus_in_cb(void *data, Evas *e, void *event_info)
1797 LOGD("ctx : %p %d", _focus_req_ctx, _focus_req_only);
1799 if (_focus_req_ctx) {
1800 set_focus(_focus_req_ctx);
1801 if (ecore_imf_context_input_panel_enabled_get (_focus_req_ctx) || !_focus_req_only)
1802 if (!ecore_imf_context_input_panel_show_on_demand_get (_focus_req_ctx) || !_focus_req_only)
1803 ecore_imf_context_input_panel_show(_focus_req_ctx);
1805 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(_focus_req_ctx);
1806 if (imcontext && imcontext->canvas)
1807 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1808 _focus_req_ctx = NULL;
1809 _focus_req_only = EINA_TRUE;
1814 show_input_panel(Ecore_IMF_Context *ctx)
1816 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1818 char *surrounding = NULL;
1821 if ((!imcontext) || (!imcontext->text_input))
1824 if (!imcontext->input) {
1826 if (!imcontext->input) {
1827 _focus_req_ctx = ctx;
1828 _focus_req_only = EINA_FALSE;
1829 if (imcontext->canvas) {
1830 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1831 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
1833 else if (imcontext->window) {
1834 _win_focus_in_handler_del();
1835 _win_focus_in_handler = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_IN, _client_window_focus_in_cb, NULL);
1840 _clear_hide_timer ();
1842 _win_focus_out_handler_del ();
1844 if (!imcontext->input)
1847 ignore_hide = EINA_TRUE;
1849 _win_focus_out_handler = ecore_event_handler_add (ECORE_WL2_EVENT_FOCUS_OUT, _client_window_focus_out_cb, ctx);
1850 _conformant_change_handler_del ();
1851 _conformant_change_handler = ecore_event_handler_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, _conformant_change_cb, NULL);
1853 // TIZEN_ONLY(20160217): ignore the duplicate show request
1854 if ((_show_req_ctx == ctx) && _compare_context(_show_req_ctx, ctx) && (!will_hide)) {
1855 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW ||
1856 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
1857 LOGD("already show. ctx : %p", ctx);
1863 _conformant_reset_started = EINA_FALSE;
1864 will_hide = EINA_FALSE;
1865 _show_req_ctx = ctx;
1866 _input_panel_ctx = ctx;
1867 _active_context_canvas = ecore_imf_context_client_canvas_get(ctx);
1871 // TIZEN_ONLY(20150715): Support input_panel_state_get
1872 int layout = ecore_imf_context_input_panel_layout_get (ctx);
1873 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1876 if (layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
1877 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
1879 wl_text_input_set_content_type(imcontext->text_input,
1880 imcontext->content_hint,
1883 if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos)) {
1884 SECURE_LOGD ("surrounding text : %s", surrounding);
1888 imcontext->cursor_position = cursor_pos;
1889 wl_text_input_set_cursor_position(imcontext->text_input, cursor_pos);
1891 // TIZEN_ONLY(20150716): Support return key type
1892 wl_text_input_set_return_key_type(imcontext->text_input,
1893 imcontext->return_key_type);
1895 wl_text_input_set_return_key_disabled(imcontext->text_input,
1896 imcontext->return_key_disabled);
1898 if (imcontext->imdata_size > 0)
1899 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
1901 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
1903 set_autocapital (ctx);
1905 if (imcontext->mime_type)
1906 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
1908 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
1909 wl_text_input_set_input_panel_position(imcontext->text_input,
1910 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
1912 LOGD ("ctx : %p, layout : %d, layout variation : %d, language : %d, cursor position : %d",
1913 ctx, layout, layout_variation,
1914 ecore_imf_context_input_panel_language_get (ctx),
1916 LOGD ("input hint : %#x, bidi direction : %d, return key type : %d, return key disabled : %d, autocapital type : %d",
1917 ecore_imf_context_input_hint_get (ctx),
1918 imcontext->bidi_direction,
1919 ecore_imf_context_input_panel_return_key_type_get (ctx),
1920 ecore_imf_context_input_panel_return_key_disabled_get (ctx),
1921 ecore_imf_context_autocapital_type_get (ctx));
1922 LOGD ("client_window : %#lx, Ecore_Wl2_Window : %p, password mode : %d, sensitive data mode : %d, prediction_allow : %d, mime_type : %s, input panel position x : %d, y : %d",
1923 (unsigned long int)ecore_imf_context_client_window_get (ctx),
1925 (imcontext->content_hint & WL_TEXT_INPUT_CONTENT_HINT_PASSWORD) ? 1 : 0,
1926 (imcontext->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) ? 1 : 0,
1927 ecore_imf_context_prediction_allow_get (ctx),
1928 imcontext->mime_type,
1929 imcontext->input_panel_position.x,
1930 imcontext->input_panel_position.y);
1932 if (_active_context_canvas && !evas_focus_state_get (_active_context_canvas)) {
1933 LOGW ("Canvas does not have focus!");
1937 if (hw_keyboard_mode) {
1938 LOGD("hw_keyboard_mode is TRUE, returning");
1942 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
1944 wl_text_input_show_input_panel(imcontext->text_input);
1946 if (imcontext->window) {
1947 _active_context_window_id = ecore_wl2_window_id_get(imcontext->window);
1948 imcontext->has_conformant = ecore_wl2_window_conformant_get(imcontext->window);
1950 imcontext->has_conformant = EINA_FALSE;
1956 static void delete_surrounding_text(WaylandIMContext *imcontext, int index, int length)
1958 Ecore_IMF_Event_Delete_Surrounding ev;
1959 LOGD("delete surrounding text (index: %d, length: %u)",
1963 ev.n_chars = length;
1965 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
1969 text_input_preedit_string(void *data,
1970 struct wl_text_input *text_input EINA_UNUSED,
1975 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1976 Eina_Bool old_preedit = EINA_FALSE;
1977 Eina_Bool preedit_changed = EINA_FALSE;
1979 SECURE_LOGD("ctx : %p, preedit event (text: '%s', current pre-edit: '%s')",
1982 imcontext->preedit_text ? imcontext->preedit_text : "");
1984 if (!check_serial(imcontext, serial))
1988 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1990 if (imcontext->preedit_text)
1991 preedit_changed = (strcmp(imcontext->preedit_text, text) != 0);
1993 preedit_changed = (strlen(text) != 0);
1995 if (_preedit_cursor_changed) {
1996 preedit_changed = EINA_TRUE;
1997 _preedit_cursor_changed = EINA_FALSE;
2000 if (imcontext->pending_preedit.attrs)
2001 preedit_changed = EINA_TRUE;
2003 clear_preedit(imcontext);
2005 imcontext->preedit_text = strdup(text);
2006 imcontext->preedit_commit = (strlen(text) > 0 ? strdup(commit) : NULL);
2007 imcontext->preedit_cursor =
2008 utf8_offset_to_characters(text, imcontext->pending_preedit.cursor);
2009 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
2011 imcontext->pending_preedit.attrs = NULL;
2013 if (preedit_changed) {
2015 ecore_imf_context_event_callback_call(imcontext->ctx,
2016 ECORE_IMF_CALLBACK_PREEDIT_START,
2020 ecore_imf_context_event_callback_call(imcontext->ctx,
2021 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
2024 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
2025 ecore_imf_context_event_callback_call(imcontext->ctx,
2026 ECORE_IMF_CALLBACK_PREEDIT_END,
2033 text_input_delete_surrounding_text(void *data,
2034 struct wl_text_input *text_input EINA_UNUSED,
2038 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2039 delete_surrounding_text(imcontext, index, length);
2043 text_input_cursor_position(void *data EINA_UNUSED,
2044 struct wl_text_input *text_input EINA_UNUSED,
2048 LOGD("cursor_position for next commit (index: %d, anchor: %d)",
2053 text_input_preedit_styling(void *data,
2054 struct wl_text_input *text_input EINA_UNUSED,
2059 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2060 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
2065 case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
2066 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_NONE;
2068 case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
2069 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
2071 case WL_TEXT_INPUT_PREEDIT_STYLE_REVERSE:
2072 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
2074 case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
2075 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
2077 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR1:
2078 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
2080 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR2:
2081 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
2083 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR3:
2084 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
2086 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR4:
2087 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
2090 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
2094 attr->start_index = index;
2095 attr->end_index = index + length;
2097 imcontext->pending_preedit.attrs =
2098 eina_list_append(imcontext->pending_preedit.attrs, attr);
2102 text_input_preedit_cursor(void *data,
2103 struct wl_text_input *text_input EINA_UNUSED,
2106 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2108 LOGD("preedit cursor : %d", index);
2110 if (imcontext->pending_preedit.cursor != index) {
2111 imcontext->pending_preedit.cursor = index;
2112 _preedit_cursor_changed = EINA_TRUE;
2116 static xkb_mod_index_t
2117 modifiers_get_index(struct wl_array *modifiers_map, const char *name)
2119 xkb_mod_index_t index = 0;
2120 char *p = modifiers_map->data;
2122 while ((const char *)p < ((const char *)modifiers_map->data + modifiers_map->size))
2124 if (strcmp(p, name) == 0)
2131 return XKB_MOD_INVALID;
2134 static xkb_mod_mask_t
2135 modifiers_get_mask(struct wl_array *modifiers_map,
2138 xkb_mod_index_t index = modifiers_get_index(modifiers_map, name);
2140 if (index == XKB_MOD_INVALID)
2141 return XKB_MOD_INVALID;
2147 text_input_modifiers_map(void *data,
2148 struct wl_text_input *text_input EINA_UNUSED,
2149 struct wl_array *map)
2151 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2152 imcontext->shift_mask = modifiers_get_mask(map, XKB_MOD_NAME_SHIFT);
2153 imcontext->control_mask = modifiers_get_mask(map, XKB_MOD_NAME_CTRL);
2154 imcontext->alt_mask = modifiers_get_mask(map, XKB_MOD_NAME_ALT);
2155 imcontext->super_mask = modifiers_get_mask(map, XKB_MOD_NAME_LOGO);
2156 imcontext->caps_mask = modifiers_get_mask(map, XKB_MOD_NAME_CAPS);
2157 imcontext->num_mask = modifiers_get_mask(map, XKB_MOD_NAME_NUM);
2161 _ecore_keyevent_free (void *data EINA_UNUSED, void *ev)
2163 Ecore_Event_Key *e = ev;
2164 if (e->dev) ecore_device_unref(e->dev);
2170 text_input_keysym(void *data,
2171 struct wl_text_input *text_input EINA_UNUSED,
2172 uint32_t serial EINA_UNUSED,
2178 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2179 char string[32] = {'\0'};
2180 char key[32] = {'\0'};
2181 char keyname[32] = {'\0'};
2184 memset(key, 0, sizeof(key));
2185 xkb_keysym_get_name(sym, key, sizeof(key));
2187 memset(keyname, 0, sizeof(keyname));
2188 xkb_keysym_get_name(sym, keyname, sizeof(keyname));
2189 if (keyname[0] == '\0')
2190 snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
2192 memset(string, 0, sizeof(string));
2193 xkb_keysym_to_utf8(sym, string, 32);
2195 SECURE_LOGD("key event (key: %s)", keyname);
2197 unsigned int key_len = strlen(key);
2198 unsigned int key_name_len = strlen(keyname);
2199 unsigned int key_string_len = strlen(string);
2201 if (key_len > sizeof(key)-1)
2202 key_len = sizeof(key)-1;
2204 if (key_name_len > sizeof(keyname)-1)
2205 key_name_len = sizeof(keyname)-1;
2207 if (key_string_len > sizeof(string)-1)
2208 key_string_len = sizeof(string)-1;
2210 e = calloc(1, sizeof(Ecore_Event_Key) + key_len + key_name_len +
2211 key_string_len + 3);
2214 e->keyname = (char *)(e + 1);
2215 e->key = e->keyname + key_name_len + 1;
2216 e->string = e->key + key_len + 1;
2217 e->compose = e->string;
2219 memcpy((void *)e->keyname, keyname, key_name_len);
2220 *((char *)e->keyname + key_name_len) = '\0';
2221 memcpy((void *)e->key, key, key_len);
2222 *((char *)e->key + key_len) = '\0';
2223 memcpy((void *)e->string, string, key_string_len);
2224 *((char *)e->string + key_string_len) = '\0';
2226 e->window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2227 e->event_window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2228 e->dev = ecore_device_ref(_ime_device);
2229 e->timestamp = 0; /* For distinguishing S/W keyboard event */
2232 if (modifiers & imcontext->shift_mask)
2233 e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
2235 if (modifiers & imcontext->control_mask)
2236 e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
2238 if (modifiers & imcontext->alt_mask)
2239 e->modifiers |= ECORE_EVENT_MODIFIER_ALT;
2241 if (modifiers & imcontext->super_mask)
2242 e->modifiers |= ECORE_EVENT_MODIFIER_WIN;
2244 if (modifiers & MOD_Mod5_MASK)
2245 e->modifiers |= MOD_Mod5_MASK;
2247 if (modifiers & imcontext->caps_mask)
2248 e->modifiers |= ECORE_EVENT_LOCK_CAPS;
2250 if (modifiers & imcontext->num_mask)
2251 e->modifiers |= ECORE_EVENT_LOCK_NUM;
2253 //Save "wl_text_input::keysym" keysym to list if list is not empty,
2254 //if not, send keysym to ecore loop as key event.
2255 //This code let key event which will be filtered by IME one by one.
2256 if (eina_list_count(imcontext->keysym_list)) {
2257 e->data = (void *)(unsigned long int)(state ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP);
2258 imcontext->keysym_list = eina_list_prepend(imcontext->keysym_list, e);
2262 ecore_event_add(ECORE_EVENT_KEY_DOWN, e, _ecore_keyevent_free, NULL);
2264 ecore_event_add(ECORE_EVENT_KEY_UP, e, _ecore_keyevent_free, NULL);
2269 text_input_enter(void *data,
2270 struct wl_text_input *text_input EINA_UNUSED,
2271 struct wl_surface *surface EINA_UNUSED)
2273 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2275 update_state(imcontext);
2277 imcontext->reset_serial = imcontext->serial;
2281 text_input_leave(void *data,
2282 struct wl_text_input *text_input EINA_UNUSED)
2284 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2287 commit_preedit(imcontext);
2288 clear_preedit(imcontext);
2292 text_input_input_panel_state(void *data EINA_UNUSED,
2293 struct wl_text_input *text_input EINA_UNUSED,
2294 uint32_t state EINA_UNUSED)
2296 // TIZEN_ONLY(20150708): Support input panel state callback
2297 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2298 LOGD("input panel state: %d", state);
2300 case WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE:
2301 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2302 if (imcontext->ctx == _show_req_ctx)
2303 _show_req_ctx = NULL;
2305 will_hide = EINA_FALSE;
2307 _received_will_hide_event = EINA_TRUE;
2308 LOGD("_received_will_hide_event = 1");
2309 send_will_hide_ack(imcontext->ctx);
2311 case WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW:
2312 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
2313 _received_will_hide_event = EINA_FALSE;
2315 _show_req_ctx = imcontext->ctx;
2316 LOGD("_received_will_hide_event = 0");
2319 _input_panel_state = (Ecore_IMF_Input_Panel_State)state;
2323 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx,
2324 ECORE_IMF_INPUT_PANEL_STATE_EVENT,
2325 _input_panel_state);
2327 if (state == WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE &&
2328 !(!_keyboard_geometry.x && !_keyboard_geometry.y && !_keyboard_geometry.w && !_keyboard_geometry.h &&
2329 _keyboard_geometry_notified)) {
2330 reset_keyboard_geometry();
2331 send_keyboard_geometry_event(imcontext->ctx);
2336 // TIZEN_ONLY(20151221): Support input panel geometry
2338 text_input_input_panel_geometry(void *data EINA_UNUSED,
2339 struct wl_text_input *text_input EINA_UNUSED,
2345 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2347 if (_keyboard_geometry.x != (int)x || _keyboard_geometry.y != (int)y ||
2348 _keyboard_geometry.w != (int)w || _keyboard_geometry.h != (int)h)
2350 _keyboard_geometry.x = x;
2351 _keyboard_geometry.y = y;
2352 _keyboard_geometry.w = w;
2353 _keyboard_geometry.h = h;
2355 send_keyboard_geometry_event(imcontext->ctx);
2358 if (!_keyboard_geometry_notified) {
2359 send_keyboard_geometry_event(imcontext->ctx);
2362 LOGI ("not to send IME geometry due to same geometry");
2368 text_input_language(void *data,
2369 struct wl_text_input *text_input EINA_UNUSED,
2370 uint32_t serial EINA_UNUSED,
2371 const char *language)
2373 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2374 Eina_Bool changed = EINA_FALSE;
2376 if (!imcontext || !language) return;
2378 if (imcontext->language) {
2379 if (strcmp(imcontext->language, language) != 0) {
2380 changed = EINA_TRUE;
2381 free(imcontext->language);
2385 changed = EINA_TRUE;
2389 imcontext->language = strdup(language);
2392 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, 0);
2397 text_input_text_direction(void *data EINA_UNUSED,
2398 struct wl_text_input *text_input EINA_UNUSED,
2399 uint32_t serial EINA_UNUSED,
2400 uint32_t direction EINA_UNUSED)
2404 // TIZEN_ONLY(20150918): Support to set the selection region
2406 text_input_selection_region(void *data,
2407 struct wl_text_input *text_input EINA_UNUSED,
2408 uint32_t serial EINA_UNUSED,
2412 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2413 if (!imcontext || !imcontext->ctx) return;
2415 Ecore_IMF_Event_Selection ev;
2416 ev.ctx = imcontext->ctx;
2419 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_SELECTION_SET, &ev);
2423 text_input_private_command(void *data,
2424 struct wl_text_input *text_input EINA_UNUSED,
2425 uint32_t serial EINA_UNUSED,
2426 const char *command)
2428 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2429 if (!imcontext || !imcontext->ctx) return;
2431 const char *szConformantReset = "CONFORMANT_RESET";
2432 const char *szConformantRestore = "CONFORMANT_RESTORE";
2433 LOGD("Checking command : %s", command);
2435 if (strncmp(command, szConformantReset, strlen(szConformantReset)) == 0) {
2436 Ecore_Wl2_Window *window = imcontext->window;
2437 if (!window) return;
2439 if (!reset_conformant_area(imcontext->ctx) && !_conformant_reset_started) {
2440 LOGD("Could not reset conformant area, send will_hide_ack right away %d", _conformant_reset_started);
2441 _send_will_hide_ack(imcontext);
2442 } else if (_conformant_reset_done) {
2443 LOGD("Conformant reset has been already finished, send will_hide_ack right away");
2444 _send_will_hide_ack(imcontext);
2446 } else if (strncmp(command, szConformantRestore, strlen(szConformantRestore)) == 0) {
2447 Ecore_Wl2_Window *window = imcontext->window;
2448 if (!window) return;
2450 restore_conformant_area(imcontext->ctx);
2452 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)command);
2457 text_input_commit_content(void *data,
2458 struct wl_text_input *text_input EINA_UNUSED,
2459 uint32_t serial EINA_UNUSED,
2460 const char *content,
2461 const char *description,
2462 const char *mime_types)
2464 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2465 if (!imcontext || !imcontext->ctx) return;
2467 Ecore_IMF_Event_Commit_Content ev;
2468 ev.content_uri = content;
2469 ev.mime_types = mime_types;
2470 ev.description = description;
2472 SECURE_LOGD("commit content : %s, description : %s, mime types : %s", content, description, mime_types);
2474 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT_CONTENT, (void *)&ev);
2478 text_input_input_panel_data(void *data,
2479 struct wl_text_input *text_input EINA_UNUSED,
2480 uint32_t serial EINA_UNUSED,
2481 const char *input_panel_data,
2484 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2485 if (!imcontext || !imcontext->ctx) return;
2487 if (imcontext->input_panel_data)
2488 free (imcontext->input_panel_data);
2490 imcontext->input_panel_data = calloc (1, length);
2491 if (imcontext->input_panel_data)
2492 memcpy (imcontext->input_panel_data, input_panel_data, length);
2494 imcontext->input_panel_data_length = length;
2498 text_input_get_selection_text (void *data,
2499 struct wl_text_input *text_input EINA_UNUSED,
2502 char *selection = NULL;
2504 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2505 if (!imcontext || !imcontext->ctx) {
2506 LOGD ("No context!");
2511 ecore_imf_context_selection_get (imcontext->ctx, &selection);
2512 if (imcontext->text_input) {
2513 SECURE_LOGD ("selection :%s", selection ? selection : "");
2515 char *_selection = selection;
2516 size_t len = strlen (selection);
2518 ssize_t ret = write (fd, _selection, len);
2522 LOGW ("write pipe failed, errno: %d", errno);
2536 text_input_get_surrounding_text (void *data,
2537 struct wl_text_input *text_input EINA_UNUSED,
2538 uint32_t maxlen_before,
2539 uint32_t maxlen_after,
2543 char *surrounding = NULL;
2544 LOGD("fd: %d maxlen_before: %d maxlen_after: %d", fd, maxlen_before, maxlen_after);
2545 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2546 if (!imcontext || !imcontext->ctx) {
2547 LOGD ("No context!");
2552 /* cursor_pos is a byte index */
2553 if (ecore_imf_context_surrounding_get (imcontext->ctx, &surrounding, &cursor_pos)) {
2554 SECURE_LOGD ("surrounding : '%s', cursor: %d", surrounding ? surrounding : "", cursor_pos);
2555 if (imcontext->text_input) {
2556 Eina_Unicode *wide_surrounding = eina_unicode_utf8_to_unicode (surrounding, NULL);
2557 size_t wlen = eina_unicode_strlen (wide_surrounding);
2559 if (cursor_pos > (int)wlen || cursor_pos < 0)
2562 if (maxlen_before > cursor_pos)
2565 maxlen_before = cursor_pos - maxlen_before;
2567 if (maxlen_after > wlen - cursor_pos)
2568 maxlen_after = (uint32_t)wlen;
2570 maxlen_after = cursor_pos + maxlen_after;
2572 char *req_surrounding = eina_unicode_unicode_to_utf8_range (wide_surrounding + maxlen_before, maxlen_after - maxlen_before, NULL);
2574 ssize_t ret = write(fd, &cursor_pos, sizeof(cursor_pos));
2576 LOGW ("write pipe failed, errno: %d", errno);
2577 } else if (req_surrounding) {
2578 char *_surrounding = req_surrounding;
2579 size_t len = strlen(req_surrounding);
2581 ssize_t ret = write(fd, _surrounding, len);
2585 LOGW ("write pipe failed, errno: %d", errno);
2588 _surrounding += ret;
2593 if (req_surrounding)
2594 free (req_surrounding);
2596 if (wide_surrounding)
2597 free (wide_surrounding);
2607 text_input_filter_key_event_done(void *data,
2608 struct wl_text_input *text_input EINA_UNUSED,
2612 LOGD("serial: %d, state: %d", serial, state);
2613 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2614 if (!imcontext) return;
2616 imcontext->last_key_event_filter.serial = serial;
2617 imcontext->last_key_event_filter.state = state;
2621 text_input_hide_permission(void *data,
2622 struct wl_text_input *text_input EINA_UNUSED,
2623 uint32_t permission)
2625 LOGD("permission : %d", permission);
2626 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2627 if (!imcontext || !imcontext->ctx || ignore_hide)
2631 ecore_imf_context_input_panel_hide(imcontext->ctx);
2635 text_input_recapture_string(void *data,
2636 struct wl_text_input *text_input EINA_UNUSED,
2640 const char *preedit,
2641 const char *preedit_commit,
2644 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2645 Eina_Bool old_preedit = EINA_FALSE;
2646 Eina_Bool preedit_changed = EINA_FALSE;
2648 SECURE_LOGD("ctx : %p, index : %d, length : %d, preedit event (preedit: '%s', current pre-edit: '%s')",
2653 imcontext->preedit_text ? imcontext->preedit_text : "");
2655 if (!check_serial(imcontext, serial))
2659 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
2661 if (imcontext->preedit_text)
2662 preedit_changed = (strcmp(imcontext->preedit_text, preedit) != 0);
2664 preedit_changed = (strlen(preedit) != 0);
2666 // send transaction start
2667 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_START");
2668 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_START, NULL);
2670 commit_preedit(imcontext);
2671 clear_preedit(imcontext);
2673 // delete surrounding text
2674 delete_surrounding_text(imcontext, index, length);
2676 // update preedit string
2677 imcontext->preedit_text = strdup(preedit);
2678 imcontext->preedit_commit = (strlen(preedit) > 0 ? strdup(preedit_commit) : NULL);
2679 imcontext->preedit_cursor =
2680 utf8_offset_to_characters(preedit, imcontext->pending_preedit.cursor);
2681 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
2683 imcontext->pending_preedit.attrs = NULL;
2685 if (preedit_changed) {
2687 ecore_imf_context_event_callback_call(imcontext->ctx,
2688 ECORE_IMF_CALLBACK_PREEDIT_START,
2692 ecore_imf_context_event_callback_call(imcontext->ctx,
2693 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
2696 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
2697 ecore_imf_context_event_callback_call(imcontext->ctx,
2698 ECORE_IMF_CALLBACK_PREEDIT_END,
2704 if (commit && strlen(commit) != 0) {
2705 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)commit);
2708 // send transaction end
2709 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_END");
2710 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_END, NULL);
2714 text_input_input_panel_event(void *data,
2715 struct wl_text_input *text_input EINA_UNUSED,
2716 uint32_t serial EINA_UNUSED,
2717 uint32_t event_type,
2720 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2721 if (!imcontext || !imcontext->ctx) return;
2723 LOGD("event type : %d, value : %d", event_type, value);
2725 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, event_type, value);
2729 static const struct wl_text_input_listener text_input_listener =
2733 text_input_modifiers_map,
2734 text_input_input_panel_state,
2735 text_input_preedit_string,
2736 text_input_preedit_styling,
2737 text_input_preedit_cursor,
2738 text_input_commit_string,
2739 text_input_cursor_position,
2740 text_input_delete_surrounding_text,
2742 text_input_language,
2743 text_input_text_direction,
2744 // TIZEN_ONLY(20150918): Support to set the selection region
2745 text_input_selection_region,
2746 text_input_private_command,
2747 text_input_input_panel_geometry,
2748 text_input_input_panel_data,
2749 text_input_get_selection_text,
2750 text_input_get_surrounding_text,
2751 text_input_filter_key_event_done,
2752 text_input_hide_permission,
2753 text_input_recapture_string,
2754 text_input_input_panel_event,
2755 text_input_commit_content
2761 keyboard_mode_changed_cb (keynode_t *key, void* data)
2763 hw_keyboard_mode = vconf_keynode_get_bool (key);
2764 Ecore_IMF_Context *active_ctx = get_using_ctx ();
2766 LOGD ("ctx : %p, input detect : %d", active_ctx, hw_keyboard_mode);
2768 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;
2769 ecore_imf_context_input_panel_event_callback_call (active_ctx, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, input_mode);
2771 if (input_mode == ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE && _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW)
2772 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2774 if ((input_mode == ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE) && _focused_ctx && (active_ctx == _focused_ctx)) {
2775 if (ecore_imf_context_input_panel_enabled_get (active_ctx)) {
2776 ecore_imf_context_input_panel_show (active_ctx);
2783 #ifdef SOCKET_ACTIVATION
2784 static int activate_socket () {
2786 struct sockaddr_un svr;
2792 LOGD("socket_activate start");
2793 s = socket(AF_UNIX, SOCK_STREAM, 0);
2795 LOGW("socket error");
2799 flag = fcntl(s, F_GETFL, NULL);
2801 fcntl(s, F_SETFL, flag);
2803 svr.sun_family = AF_UNIX;
2804 strcpy(svr.sun_path, SOCK_PATH);
2807 r = connect(s, (struct sockaddr *)&svr, len);
2809 LOGD("connect error");
2817 gettimeofday(&s1, NULL);
2818 LOGD("%d %06d\n", (int)s1.tv_sec, (int)s1.tv_usec);
2820 r = send(s, (const void *)&s1, sizeof(s1), 0);
2833 void wayland_im_initialize ()
2835 register_key_handler ();
2837 /* get input language vconf value */
2838 char *input_lang_str = vconf_get_str (VCONFKEY_ISF_INPUT_LANGUAGE);
2839 if (input_lang_str) {
2840 set_input_language (input_lang_str);
2841 free (input_lang_str);
2845 /* get autoperiod allow vconf value */
2847 if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
2848 if (val == EINA_TRUE)
2849 autoperiod_allow = EINA_TRUE;
2852 /* get autocapital allow vconf value */
2853 if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
2854 if (val == EINA_TRUE)
2855 autocap_allow = EINA_TRUE;
2858 /* get hardware keyboard input detected vconf value */
2859 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
2860 if (val == EINA_TRUE)
2861 hw_keyboard_mode = EINA_TRUE;
2864 if (vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL) != 0)
2865 LOGW ("Failed to register callback function for autocapital.");
2867 if (vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL) != 0)
2868 LOGW ("Failed to register callback function for autoperiod.");
2870 if (vconf_notify_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb, NULL) != 0)
2871 LOGW ("Failed to register callback function for input language change.");
2873 if (vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL) != 0)
2874 LOGW ("Failed to register callback function for H/W keyboard input detection.");
2877 _ime_device = ecore_device_add();
2879 ecore_device_name_set (_ime_device, IME_DEVICE_NAME);
2880 ecore_device_description_set (_ime_device, IME_DEVICE_NAME);
2881 ecore_device_identifier_set (_ime_device, IME_DEVICE_NAME);
2882 ecore_device_class_set (_ime_device, ECORE_DEVICE_CLASS_KEYBOARD);
2883 ecore_device_subclass_set (_ime_device, ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD);
2887 void wayland_im_uninitialize ()
2889 _ecore_imf_wayland_imcontext_pair_destroy ();
2891 unregister_key_handler ();
2893 _win_focus_in_handler_del ();
2894 _win_focus_out_handler_del ();
2895 _conformant_change_handler_del ();
2898 vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
2899 vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
2900 vconf_ignore_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb);
2901 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
2905 ecore_device_del (_ime_device);
2909 ecore_event_type_flush(ECORE_EVENT_DEVICE_ADD, ECORE_EVENT_DEVICE_DEL);
2913 wayland_im_context_add(Ecore_IMF_Context *ctx)
2915 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2918 LOGD("ctx : %p", ctx);
2920 if (!imcontext) return;
2922 imcontext->ctx = ctx;
2923 imcontext->input_panel_layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2924 imcontext->keysym_list = NULL;
2926 imcontext->shift_mask = MOD_SHIFT_MASK;
2927 imcontext->control_mask = MOD_CONTROL_MASK;
2928 imcontext->alt_mask = MOD_ALT_MASK;
2929 imcontext->super_mask = MOD_SUPER_MASK;
2930 imcontext->caps_mask = MOD_CAPS_MASK;
2931 imcontext->num_mask = MOD_NUM_MASK;
2933 imcontext->input_panel_position.x = -1;
2934 imcontext->input_panel_position.y = -1;
2936 LOGD("text_input_manager : %p", imcontext->text_input_manager);
2937 imcontext->text_input =
2938 wl_text_input_manager_create_text_input(imcontext->text_input_manager);
2940 if (imcontext->text_input)
2941 wl_text_input_add_listener(imcontext->text_input,
2942 &text_input_listener, imcontext);
2945 LOGD("app id : %s\n", appid);
2947 ecore_imf_context_prediction_hint_hash_set(ctx, "appid", appid ? appid : "");
2954 wayland_im_context_del (Ecore_IMF_Context *ctx)
2956 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2958 Eina_Bool valid = EINA_FALSE;
2959 Ecore_Imf_Wayland_Imcontext_Pair *pair = _ecore_imf_wayland_imcontext_pair_find(ctx);
2960 if (pair && pair->imcontext == imcontext) {
2961 _ecore_imf_wayland_imcontext_pair_del(ctx);
2965 LOGE("The Ecore_Imf %p and WaylandIMContext %p pair not found!! pair : %p, pair->imcontext %p",
2966 ctx, imcontext, pair, pair ? pair->imcontext : NULL);
2967 _ecore_imf_wayland_imcontext_pair_log();
2970 Ecore_Event_Key *ev;
2971 LOGD ("ctx : %p, ctx valid : %d, focused_ctx : %p, show_req_ctx : %p", ctx, valid, _focused_ctx, _show_req_ctx);
2973 if (!imcontext) return;
2975 // TIZEN_ONLY(20150708): Support back key
2976 if (_input_panel_ctx == ctx) {
2977 _clear_hide_timer();
2978 _input_panel_hide(ctx, EINA_TRUE);
2979 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2980 _input_panel_ctx = NULL;
2983 if (_focused_ctx == ctx)
2984 _focused_ctx = NULL;
2986 if (_show_req_ctx == ctx)
2987 _show_req_ctx = NULL;
2989 if (_focus_req_ctx == ctx) {
2990 if (imcontext->canvas)
2991 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
2993 _win_focus_in_handler_del();
2995 _focus_req_ctx = NULL;
2996 _focus_req_only = EINA_TRUE;
3000 if (imcontext->language) {
3001 free (imcontext->language);
3002 imcontext->language = NULL;
3005 // TIZEN_ONLY(20150922): Support to set input panel data
3006 if (imcontext->imdata) {
3007 free (imcontext->imdata);
3008 imcontext->imdata = NULL;
3009 imcontext->imdata_size = 0;
3012 if (imcontext->input_panel_data) {
3013 free (imcontext->input_panel_data);
3014 imcontext->input_panel_data = NULL;
3015 imcontext->input_panel_data_length = 0;
3019 if (imcontext->prediction_hint) {
3020 free (imcontext->prediction_hint);
3021 imcontext->prediction_hint = NULL;
3024 if (imcontext->mime_type) {
3025 free (imcontext->mime_type);
3026 imcontext->mime_type = NULL;
3029 if (imcontext->text_input) {
3030 LOGD("destroy wl_text_input : %p", imcontext->text_input);
3031 wl_text_input_destroy (imcontext->text_input);
3032 imcontext->text_input = NULL;
3035 clear_preedit (imcontext);
3037 EINA_LIST_FREE(imcontext->keysym_list, ev) {
3046 wayland_im_context_reset(Ecore_IMF_Context *ctx)
3048 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3050 LOGD("ctx : %p", ctx);
3052 if (!imcontext) return;
3054 commit_preedit (imcontext);
3056 if (!imcontext->input) return;
3058 if (imcontext->text_input) {
3059 wl_text_input_reset(imcontext->text_input);
3061 update_state(imcontext);
3063 imcontext->reset_serial = imcontext->serial;
3067 _prediction_hint_data_foreach_cb(const Eina_Hash *hash, const void *key,
3068 void *data, void *fdata)
3070 const char *key_str = key;
3071 const char *value = data;
3072 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)fdata;
3073 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3075 SECURE_LOGD("key : %s, value : %s\n", key_str, value);
3077 if (imcontext && imcontext->text_input)
3078 wl_text_input_prediction_hint_data(imcontext->text_input, key_str, value);
3084 wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
3086 LOGD ("ctx : %p. enable : %d, on demand : %d", ctx,
3087 ecore_imf_context_input_panel_enabled_get(ctx),
3088 ecore_imf_context_input_panel_show_on_demand_get (ctx));
3090 #ifdef SOCKET_ACTIVATION
3094 if (!set_focus(ctx)) {
3095 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3096 if (imcontext && !imcontext->input) {
3097 if (_focus_req_ctx != ctx)
3098 _focus_req_only = EINA_TRUE;
3099 _focus_req_ctx = ctx;
3100 if (imcontext->canvas) {
3101 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
3102 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
3104 else if (imcontext->window) {
3105 _win_focus_in_handler_del();
3106 _win_focus_in_handler = ecore_event_handler_add (ECORE_WL2_EVENT_FOCUS_IN, _client_window_focus_in_cb, NULL);
3109 LOGW("ctx : %p. Fail to set focus!", ctx);
3113 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3114 if (imcontext && imcontext->input && imcontext->text_input) {
3115 wl_text_input_set_return_key_disabled(imcontext->text_input,
3116 imcontext->return_key_disabled);
3118 if (imcontext->prediction_hint)
3119 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
3121 if (imcontext->mime_type)
3122 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
3124 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
3125 wl_text_input_set_input_panel_position(imcontext->text_input,
3126 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
3128 const Eina_Hash *hash = ecore_imf_context_prediction_hint_hash_get(ctx);
3130 eina_hash_foreach(hash, _prediction_hint_data_foreach_cb, ctx);
3132 wl_text_input_set_content_type(imcontext->text_input, imcontext->content_hint, get_purpose(ctx));
3134 wl_text_input_input_panel_enabled(imcontext->text_input, ecore_imf_context_input_panel_enabled_get(ctx));
3138 hw_keyboard_mode = EINA_FALSE;
3140 if (ecore_imf_context_input_panel_enabled_get(ctx))
3141 if (!ecore_imf_context_input_panel_show_on_demand_get (ctx))
3142 ecore_imf_context_input_panel_show (ctx);
3144 LOGD ("ctx : %p input panel on demand mode : TRUE", ctx);
3146 LOGD ("ctx : %p input panel enable : FALSE", ctx);
3150 wayland_im_context_focus_out(Ecore_IMF_Context *ctx)
3152 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3154 LOGD("ctx : %p", ctx);
3156 if (_focus_req_ctx == ctx) {
3157 _focus_req_ctx = NULL;
3158 _focus_req_only = EINA_TRUE;
3161 if (!imcontext || !imcontext->input) return;
3163 if (_TV || _WEARABLE) {
3164 if (hw_keyboard_mode == EINA_TRUE) {
3165 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3166 hw_keyboard_mode = EINA_FALSE;
3170 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3171 ecore_imf_context_input_panel_hide(ctx);
3178 wayland_im_context_preedit_string_get(Ecore_IMF_Context *ctx,
3182 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3183 if (!imcontext) return;
3185 SECURE_LOGD("pre-edit string requested (preedit: '%s', preedit cursor : %d)",
3186 imcontext->preedit_text ? imcontext->preedit_text : "", imcontext->preedit_cursor);
3189 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3192 *cursor_pos = imcontext->preedit_cursor;
3196 wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
3201 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3202 if (!imcontext) return;
3204 SECURE_LOGD("pre-edit string with attributes requested (preedit: '%s', preedit cursor : %d)",
3205 imcontext->preedit_text ? imcontext->preedit_text : "", imcontext->preedit_cursor);
3208 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3212 Ecore_IMF_Preedit_Attr *a, *attr;
3214 if (imcontext->preedit_attrs) {
3215 EINA_LIST_FOREACH(imcontext->preedit_attrs, l, a) {
3217 attr = malloc(sizeof(*attr));
3219 attr = memcpy(attr, a, sizeof(*attr));
3220 *attrs = eina_list_append(*attrs, attr);
3226 if (imcontext->preedit_text) {
3227 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
3229 // use REVERSE style as default
3230 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
3231 attr->start_index = 0;
3232 attr->end_index = strlen(imcontext->preedit_text);
3233 *attrs = eina_list_append(*attrs, attr);
3240 *cursor_pos = imcontext->preedit_cursor;
3244 wayland_im_context_cursor_position_set (Ecore_IMF_Context *ctx,
3247 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3248 if (!imcontext) return;
3250 if (imcontext->cursor_position != cursor_pos) {
3251 imcontext->cursor_position = cursor_pos;
3253 if (imcontext->input && imcontext->text_input) {
3254 LOGD ("ctx : %p, cursor pos : %d", ctx, cursor_pos);
3256 set_autocapital (ctx);
3258 if (!imcontext->preedit_text || strlen(imcontext->preedit_text) == 0)
3259 wl_text_input_set_cursor_position (imcontext->text_input, cursor_pos);
3265 wayland_im_context_use_preedit_set(Ecore_IMF_Context *ctx EINA_UNUSED,
3266 Eina_Bool use_preedit EINA_UNUSED)
3271 wayland_im_context_client_window_set(Ecore_IMF_Context *ctx,
3274 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3276 LOGD("client window set (Ecore_Window: %p)", window);
3278 if (imcontext && window) {
3279 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3282 imcontext->window = ecore_wl2_display_window_find(wl2_display, (Ecore_Window)window);
3283 LOGD("client Ecore_Wl2_Window : %p", imcontext->window);
3286 if (_ime_device && imcontext->window)
3287 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3292 wayland_im_context_client_canvas_set(Ecore_IMF_Context *ctx,
3295 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3297 LOGD("client canvas set (canvas: %p)", canvas);
3299 if (imcontext && canvas) {
3300 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3301 imcontext->canvas = canvas;
3303 if (wl2_display && !imcontext->window) {
3304 imcontext->window = ecore_wl2_display_window_find(wl2_display, ecore_evas_window_get(ecore_evas_ecore_evas_get(canvas)));
3305 LOGD("client Ecore_Wl2_Window : %p", imcontext->window);
3308 if (_ime_device && imcontext->window)
3309 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3314 wayland_im_context_show(Ecore_IMF_Context *ctx)
3316 LOGD("ctx : %p", ctx);
3318 show_input_panel(ctx);
3322 wayland_im_context_hide(Ecore_IMF_Context *ctx)
3324 LOGD("ctx : %p", ctx);
3326 if (!get_using_ctx()) {
3327 LOGW("Can't hide input_panel because there is no using context!!");
3331 _input_panel_hide(ctx, EINA_FALSE);
3334 #if !(ENABLE_GRAB_KEYBOARD)
3336 _ecore_imf_lock_to_ecore_key_modifier(unsigned int locks)
3338 unsigned int mask = 0;
3340 if (locks & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
3341 mask |= ECORE_EVENT_LOCK_SCROLL;
3343 if (locks & ECORE_IMF_KEYBOARD_LOCK_CAPS)
3344 mask |= ECORE_EVENT_LOCK_CAPS;
3346 if (locks & ECORE_IMF_KEYBOARD_LOCK_NUM)
3347 mask |= ECORE_EVENT_LOCK_NUM;
3353 _ecore_imf_modifier_to_ecore_key_modifier(Ecore_IMF_Keyboard_Modifiers modifiers)
3355 unsigned int mask = 0;
3357 /**< "Control" is pressed */
3358 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
3359 mask |= ECORE_EVENT_MODIFIER_CTRL;
3361 /**< "Alt" is pressed */
3362 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
3363 mask |= ECORE_EVENT_MODIFIER_ALT;
3365 /**< "Shift" is pressed */
3366 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
3367 mask |= ECORE_EVENT_MODIFIER_SHIFT;
3369 /**< "Win" (between "Ctrl" and "Alt") is pressed */
3370 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
3371 mask |= ECORE_EVENT_MODIFIER_WIN;
3373 /**< "AltGr" is pressed */
3374 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
3375 mask |= ECORE_EVENT_MODIFIER_ALTGR;
3382 _check_filter_event(WaylandIMContext *imcontext)
3384 int next_serial = imcontext->serial + 1;
3385 double waiting_time = g_filter_event_elapsed_time * (next_serial - imcontext->last_key_event_filter.serial);
3387 return (waiting_time > MAX_WAIT_FOR_WL_SERVER ? EINA_FALSE : EINA_TRUE);
3391 wayland_im_context_filter_event(Ecore_IMF_Context *ctx,
3392 Ecore_IMF_Event_Type type,
3393 Ecore_IMF_Event *imf_event)
3396 #if !(ENABLE_GRAB_KEYBOARD)
3397 Eina_Bool ret = EINA_FALSE;
3398 Ecore_Event_Key ecore_key_ev;
3399 char *key_dev_name = NULL;
3400 uint32_t key_dev_class = 0;
3401 uint32_t key_dev_subclass = 0;
3403 if (type == ECORE_IMF_EVENT_MOUSE_UP) {
3404 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3405 LOGD ("[Mouse-up event] ctx : %p", ctx);
3406 if (ctx == _focused_ctx) {
3407 ecore_imf_context_input_panel_show(ctx);
3410 LOGE ("Can't show IME because there is no focus. ctx : %p", ctx);
3413 #if !(ENABLE_GRAB_KEYBOARD)
3414 else if (type == ECORE_IMF_EVENT_KEY_UP) {
3415 Ecore_IMF_Event_Key_Up *key_ev = (Ecore_IMF_Event_Key_Up *)imf_event;
3416 ecore_key_ev.keyname = key_ev->keyname;
3417 ecore_key_ev.key = key_ev->key;
3418 ecore_key_ev.string = key_ev->string;
3419 ecore_key_ev.compose = key_ev->compose;
3420 ecore_key_ev.timestamp = key_ev->timestamp;
3421 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3422 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3423 key_dev_name = (char *)key_ev->dev_name;
3424 key_dev_class = key_ev->dev_class;
3425 key_dev_subclass = key_ev->dev_subclass;
3426 ecore_key_ev.keycode = key_ev->keycode;
3428 else if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3429 Ecore_IMF_Event_Key_Down *key_ev = (Ecore_IMF_Event_Key_Down *)imf_event;
3430 ecore_key_ev.keyname = key_ev->keyname;
3431 ecore_key_ev.key = key_ev->key;
3432 ecore_key_ev.string = key_ev->string;
3433 ecore_key_ev.compose = key_ev->compose;
3434 ecore_key_ev.timestamp = key_ev->timestamp;
3435 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3436 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3437 key_dev_name = (char *)key_ev->dev_name;
3438 key_dev_class = key_ev->dev_class;
3439 key_dev_subclass = key_ev->dev_subclass;
3440 ecore_key_ev.keycode = key_ev->keycode;
3443 if (type == ECORE_IMF_EVENT_KEY_UP || type == ECORE_IMF_EVENT_KEY_DOWN) {
3444 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3445 if (!imcontext || !imcontext->input || !imcontext->text_input)
3448 if (!_focused_ctx) {
3453 if (_focused_ctx != ctx) {
3454 LOGW ("focused context is different from the context used in ecore_imf_context_filter_event.");
3455 LOGW ("focus context : %p, context : %p", _focused_ctx, ctx);
3460 if (!ecore_key_ev.timestamp && (ecore_key_ev.modifiers & MOD_Mod5_MASK)
3461 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD) {
3462 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3463 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3464 strcmp (ecore_key_ev.key, "KP_Space") == 0 ) {
3465 autoperiod_insert (ctx);
3469 LOGD("Return! This is SW keyboard fake event!");
3474 uint32_t modifiers = 0;
3475 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_SHIFT)
3476 modifiers |= imcontext->shift_mask;
3477 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_CTRL)
3478 modifiers |= imcontext->control_mask;
3479 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_ALT)
3480 modifiers |= imcontext->alt_mask;
3481 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_WIN)
3482 modifiers |= imcontext->super_mask;
3483 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_CAPS)
3484 modifiers |= imcontext->caps_mask;
3485 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_NUM)
3486 modifiers |= imcontext->num_mask;
3488 if (g_last_key_event_serial <= imcontext->last_key_event_filter.serial)
3489 g_filter_event_elapsed_time = 0.0;
3491 if (!_check_filter_event(imcontext)) {
3492 LOGE("elapsed time : %.3f ms, serial (last, require) : (%d, %d)", g_filter_event_elapsed_time * 1000, imcontext->last_key_event_filter.serial, imcontext->serial + 1);
3493 ret = modifiers ? EINA_FALSE : EINA_TRUE;
3497 int serial = imcontext->serial++;
3498 g_last_key_event_serial = serial;
3499 double start_time = ecore_time_get();
3501 SECURE_LOGD ("ev:modifiers=0x%x, modifiers=0x%x, shift_mask=0x%x, control_mask=0x%0x, alt_mask=0x%x, super_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->super_mask, imcontext->caps_mask, imcontext->num_mask, ecore_key_ev.keycode);
3502 //Send key event to IME.
3503 wl_text_input_filter_key_event(imcontext->text_input, serial, ecore_key_ev.timestamp, ecore_key_ev.key,
3504 type == ECORE_IMF_EVENT_KEY_UP? WL_KEYBOARD_KEY_STATE_RELEASED : WL_KEYBOARD_KEY_STATE_PRESSED,
3505 modifiers, (key_dev_name ? key_dev_name : ""), key_dev_class, key_dev_subclass, ecore_key_ev.keycode);
3506 //Waiting for filter_key_event_done from IME.
3507 //This function should return IME filtering result with boolean type.
3508 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3509 struct wl_display *display = NULL;
3511 display = ecore_wl2_display_get(wl2_display);
3514 struct wl_event_queue *queue = wl_display_create_queue(display);
3517 while (ecore_time_get() - start_time < WAIT_FOR_FILTER_DONE_SECOND && _focused_ctx == ctx && wl_display_roundtrip_queue(display, queue) != -1) {
3518 wl_display_dispatch_pending(display);
3519 if (imcontext->last_key_event_filter.serial == serial) {
3520 ret = imcontext->last_key_event_filter.state;
3522 } else if (imcontext->last_key_event_filter.serial > serial)
3526 if (ecore_time_get() - start_time > WAIT_FOR_FILTER_DONE_SECOND) {
3527 LOGE("Key processing result not received");
3531 if (imcontext->last_key_event_filter.serial < serial) {
3532 LOGW("Timeout occured");
3536 wl_event_queue_destroy(queue);
3539 if (g_filter_event_elapsed_time == 0)
3540 g_filter_event_elapsed_time = ecore_time_get() - start_time;
3542 g_filter_event_elapsed_time = (g_filter_event_elapsed_time + (ecore_time_get() - start_time)) / 2;
3544 LOGD ("elapsed : %.3f ms, serial (last, require) : (%d, %d)", (ecore_time_get() - start_time)*1000, imcontext->last_key_event_filter.serial, serial);
3548 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3549 if (ret == EINA_FALSE) {
3551 if (strcmp (ecore_key_ev.keyname, "Return") == 0 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_REMOCON) {
3553 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
3555 LOGI ("Changed keyboard mode from H/W to S/W");
3556 hw_keyboard_mode = EINA_FALSE;
3557 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3558 if (ecore_imf_context_input_panel_enabled_get (ctx)) {
3559 ecore_imf_context_input_panel_show (ctx);
3567 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3568 strcmp (ecore_key_ev.key, "KP_Space") == 0) {
3569 autoperiod_insert (ctx);
3574 //Deal with the next key event in list.
3575 Ecore_Event_Key *ev = NULL;
3576 if (eina_list_count (imcontext->keysym_list)) {
3577 Eina_List *n = eina_list_last(imcontext->keysym_list);
3578 ev = (Ecore_Event_Key *)eina_list_data_get(n);
3580 int event_type = (unsigned long int)ev->data;
3583 ecore_event_add(event_type, ev, _ecore_keyevent_free, NULL);
3585 imcontext->keysym_list = eina_list_remove_list(imcontext->keysym_list, n);
3596 wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int width, int height)
3598 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3599 if (!imcontext) return;
3601 if ((imcontext->cursor_location.x != x) ||
3602 (imcontext->cursor_location.y != y) ||
3603 (imcontext->cursor_location.width != width) ||
3604 (imcontext->cursor_location.height != height)) {
3605 imcontext->cursor_location.x = x;
3606 imcontext->cursor_location.y = y;
3607 imcontext->cursor_location.width = width;
3608 imcontext->cursor_location.height = height;
3610 if (_focused_ctx == ctx)
3611 send_cursor_location (imcontext);
3615 void wayland_im_context_autocapital_type_set(Ecore_IMF_Context *ctx,
3616 Ecore_IMF_Autocapital_Type autocapital_type)
3618 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3619 if (!imcontext) return;
3621 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
3622 // TIZEN_ONLY(20160201): Add autocapitalization word
3623 WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION |
3625 WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
3626 WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE);
3628 if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE)
3629 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION;
3630 // TIZEN_ONLY(20160201): Add autocapitalization word
3631 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD)
3632 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
3634 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER)
3635 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE;
3637 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE;
3639 if (imcontext->input && imcontext->text_input) {
3640 LOGD ("ctx : %p. set autocapital type : %d", ctx, autocapital_type);
3641 wl_text_input_set_content_type(imcontext->text_input,
3642 imcontext->content_hint,
3648 wayland_im_context_input_panel_layout_set(Ecore_IMF_Context *ctx,
3649 Ecore_IMF_Input_Panel_Layout layout)
3651 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3652 if (!imcontext) return;
3654 imcontext->input_panel_layout = layout;
3657 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER:
3658 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
3660 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL:
3661 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL;
3663 case ECORE_IMF_INPUT_PANEL_LAYOUT_URL:
3664 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_URL;
3666 case ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER:
3667 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE;
3669 case ECORE_IMF_INPUT_PANEL_LAYOUT_IP:
3670 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3671 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_IP;
3674 case ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH:
3675 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATE;
3677 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY:
3678 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
3680 case ECORE_IMF_INPUT_PANEL_LAYOUT_HEX:
3681 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_HEX;
3683 case ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL:
3684 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL;
3686 case ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD:
3687 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
3688 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3690 case ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME:
3691 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME;
3693 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3694 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON:
3695 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON;
3698 case ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE:
3699 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE;
3702 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
3706 if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
3707 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_PASSWORD;
3709 if (imcontext->input && imcontext->text_input) {
3710 LOGD ("ctx : %p, layout type : %d", ctx, layout);
3711 wl_text_input_set_content_type(imcontext->text_input,
3712 imcontext->content_hint,
3717 Ecore_IMF_Input_Panel_Layout
3718 wayland_im_context_input_panel_layout_get(Ecore_IMF_Context *ctx)
3720 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3721 if (!imcontext) return ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
3723 return imcontext->input_panel_layout;
3727 wayland_im_context_input_mode_set(Ecore_IMF_Context *ctx,
3728 Ecore_IMF_Input_Mode input_mode)
3730 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3731 if (!imcontext) return;
3733 if (input_mode & ECORE_IMF_INPUT_MODE_INVISIBLE)
3734 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3736 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3738 if (imcontext->input && imcontext->text_input) {
3739 LOGD ("ctx : %p, input mode : %d", ctx, input_mode);
3740 wl_text_input_set_content_type(imcontext->text_input,
3741 imcontext->content_hint,
3747 wayland_im_context_input_hint_set(Ecore_IMF_Context *ctx,
3748 Ecore_IMF_Input_Hints input_hints)
3750 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3751 if (!imcontext) return;
3753 if (input_hints & ECORE_IMF_INPUT_HINT_AUTO_COMPLETE)
3754 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3756 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3758 if (input_hints & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA)
3759 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3761 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3763 if (input_hints & ECORE_IMF_INPUT_HINT_MULTILINE)
3764 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3766 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3769 LOGD("autofill hint : %x\n", input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK);
3771 switch(input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK)
3773 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE:
3774 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE;
3776 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY:
3777 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY;
3779 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH:
3780 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH;
3782 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR:
3783 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR;
3785 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_NUMBER:
3786 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_NUMBER;
3788 case ECORE_IMF_INPUT_HINT_AUTOFILL_EMAIL_ADDRESS:
3789 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_EMAIL_ADDRESS;
3791 case ECORE_IMF_INPUT_HINT_AUTOFILL_PHONE:
3792 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_PHONE;
3794 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_ADDRESS:
3795 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_ADDRESS;
3797 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_CODE:
3798 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_CODE;
3800 case ECORE_IMF_INPUT_HINT_AUTOFILL_ID:
3801 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_ID;
3803 case ECORE_IMF_INPUT_HINT_AUTOFILL_NAME:
3804 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_NAME;
3808 if (imcontext->input && imcontext->text_input) {
3809 LOGD("ctx : %p, input hint : %#x", ctx, input_hints);
3810 wl_text_input_set_content_type(imcontext->text_input,
3811 imcontext->content_hint,
3817 wayland_im_context_input_panel_language_set(Ecore_IMF_Context *ctx,
3818 Ecore_IMF_Input_Panel_Lang lang)
3820 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3821 if (!imcontext) return;
3823 if (lang == ECORE_IMF_INPUT_PANEL_LANG_ALPHABET)
3824 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3826 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3828 if (imcontext->input && imcontext->text_input)
3829 wl_text_input_set_content_type(imcontext->text_input,
3830 imcontext->content_hint,
3834 // TIZEN_ONLY(20150708): Support input_panel_state_get
3835 Ecore_IMF_Input_Panel_State
3836 wayland_im_context_input_panel_state_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3838 return _input_panel_state;
3842 wayland_im_context_input_panel_return_key_type_set(Ecore_IMF_Context *ctx,
3843 Ecore_IMF_Input_Panel_Return_Key_Type return_key_type)
3845 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3846 if (!imcontext) return;
3848 imcontext->return_key_type = return_key_type;
3850 if (imcontext->input && imcontext->text_input)
3851 wl_text_input_set_return_key_type(imcontext->text_input,
3852 imcontext->return_key_type);
3856 wayland_im_context_input_panel_return_key_disabled_set(Ecore_IMF_Context *ctx,
3859 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3860 if (!imcontext) return;
3862 imcontext->return_key_disabled = disabled;
3864 if (imcontext->input && imcontext->text_input)
3865 wl_text_input_set_return_key_disabled(imcontext->text_input,
3866 imcontext->return_key_disabled);
3871 wayland_im_context_input_panel_language_locale_get(Ecore_IMF_Context *ctx,
3874 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3875 if (!imcontext) return;
3878 *locale = strdup(imcontext->language ? imcontext->language : "");
3882 wayland_im_context_prediction_allow_set(Ecore_IMF_Context *ctx,
3883 Eina_Bool prediction)
3885 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3886 if (!imcontext) return;
3889 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3891 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3893 if (imcontext->input && imcontext->text_input)
3894 wl_text_input_set_content_type(imcontext->text_input,
3895 imcontext->content_hint,
3899 // TIZEN_ONLY(20151221): Support input panel geometry
3901 wayland_im_context_input_panel_geometry_get(Ecore_IMF_Context *ctx EINA_UNUSED,
3902 int *x, int *y, int *w, int *h)
3905 *x = _keyboard_geometry.x;
3907 *y = _keyboard_geometry.y;
3909 *w = _keyboard_geometry.w;
3911 *h = _keyboard_geometry.h;
3915 wayland_im_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *data, int length)
3917 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3918 if (!imcontext) return;
3920 if (data && length > 0) {
3921 const char *custom_conformant_enabled = "conformant:custom,enabled";
3922 const char *custom_conformant_disabled = "conformant:custom,disabled";
3923 const char *custom_conformant_finished = "conformant:custom,finished";
3925 if (strncmp(data, custom_conformant_enabled, strlen(custom_conformant_enabled)) == 0) {
3926 _custom_conformant_event = EINA_TRUE;
3929 if (strncmp(data, custom_conformant_disabled, strlen(custom_conformant_disabled)) == 0) {
3930 _custom_conformant_event = EINA_FALSE;
3933 if (strncmp(data, custom_conformant_finished, strlen(custom_conformant_finished)) == 0) {
3934 if (_custom_conformant_event) {
3935 _conformant_reset_done = EINA_TRUE;
3936 LOGD("[conformant:custom,finished], _conformant_reset_done = 1");
3937 send_will_hide_ack(NULL);
3943 if (imcontext->imdata)
3944 free(imcontext->imdata);
3946 imcontext->imdata = calloc(1, length + 1);
3947 if (imcontext->imdata && data)
3948 memcpy(imcontext->imdata, data, length);
3950 imcontext->imdata_size = length;
3952 if (imcontext->input && imcontext->text_input && (imcontext->imdata_size > 0))
3953 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
3957 wayland_im_context_input_panel_imdata_get(Ecore_IMF_Context *ctx, void *data, int *length)
3960 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3962 if (imcontext && imcontext->input_panel_data && (imcontext->input_panel_data_length > 0)) {
3964 memcpy(data, imcontext->input_panel_data, imcontext->input_panel_data_length);
3967 *length = imcontext->input_panel_data_length;
3975 // TIZEN_ONLY(20160218): Support BiDi direction
3977 wayland_im_context_bidi_direction_set(Ecore_IMF_Context *ctx, Ecore_IMF_BiDi_Direction bidi_direction)
3979 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3980 if (!imcontext) return;
3982 imcontext->bidi_direction = bidi_direction;
3984 if (imcontext->input && imcontext->text_input) {
3985 LOGD ("ctx : %p, bidi direction : %#x", ctx, bidi_direction);
3986 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
3991 Ecore_IMF_Input_Panel_Keyboard_Mode
3992 wayland_im_context_input_panel_keyboard_mode_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3994 return hw_keyboard_mode ? ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE : ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE;
3998 wayland_im_context_prediction_hint_set (Ecore_IMF_Context *ctx, const char *prediction_hint)
4000 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
4001 if (!imcontext) return;
4003 if (imcontext->prediction_hint)
4004 free(imcontext->prediction_hint);
4006 imcontext->prediction_hint = strdup(prediction_hint ? prediction_hint : "");
4008 if (imcontext->input && imcontext->text_input) {
4009 SECURE_LOGD ("ctx : %p, prediction_hint : %s", ctx, imcontext->prediction_hint);
4010 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
4015 wayland_im_context_mime_type_accept_set (Ecore_IMF_Context *ctx, const char *mime_type)
4017 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
4018 if (!imcontext) return;
4020 if (imcontext->mime_type)
4021 free(imcontext->mime_type);
4023 imcontext->mime_type = strdup(mime_type);
4025 if (imcontext->input && imcontext->text_input && (strlen(mime_type) > 0)) {
4026 LOGD ("ctx : %p, mime_type : %s", ctx, imcontext->mime_type);
4027 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
4032 wayland_im_context_input_panel_position_set (Ecore_IMF_Context *ctx, int x, int y)
4034 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
4035 if (!imcontext) return;
4037 if ((imcontext->input_panel_position.x != x) || (imcontext->input_panel_position.y != y)) {
4038 imcontext->input_panel_position.x = x;
4039 imcontext->input_panel_position.y = y;
4042 if (imcontext->input && imcontext->text_input) {
4043 LOGD ("ctx : %p, x = %d, y = %d", ctx, x, y);
4044 wl_text_input_set_input_panel_position(imcontext->text_input,
4045 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
4049 WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager)
4051 WaylandIMContext *context = calloc(1, sizeof(WaylandIMContext));
4053 LOGD("new context created");
4054 context->text_input_manager = text_input_manager;
4060 void wayland_im_context_pair_set (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
4062 _ecore_imf_wayland_imcontext_pair_add (ctx, imcontext);