2 * Copyright © 2012, 2013 Intel Corporation
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #include "scim_private.h"
27 #include <Ecore_Evas.h>
28 #include <Ecore_Input.h>
29 #define EFL_BETA_API_SUPPORT
30 #include <Ecore_Wl2.h>
33 #include <app_common.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
45 #include "isf_debug.h"
46 #include "wayland_imcontext.h"
47 #include "tizen_profile.h"
48 #include "isf_device_event.h"
53 #define LOG_TAG "IMMODULE"
55 #define IME_DEVICE_NAME "ime"
57 #define HIDE_TIMER_INTERVAL 0.05
58 #define WAIT_FOR_FILTER_DONE_SECOND 2
60 #define MOD_SHIFT_MASK 0x01
61 #define MOD_CAPS_MASK 0x02
62 #define MOD_CONTROL_MASK 0x04
63 #define MOD_ALT_MASK 0x08
64 #define MOD_NUM_MASK 0x100
65 #define MOD_Mod5_MASK 0x80
67 #define VCONFKEY_AUTOPERIOD_ALLOW_BOOL "file/private/isf/autoperiod_allow"
68 #define VCONFKEY_AUTOCAPITAL_ALLOW_BOOL "file/private/isf/autocapital_allow"
69 #define SOCK_PATH "/run/.isf/scim-panel-socket"
74 INPUT_LANG_BENGALI_IN,
75 INPUT_LANG_BENGALI_BD,
90 INPUT_LANG_ASSAMESE_BN,
91 INPUT_LANG_BENGALI_AS,
95 INPUT_LANG_MANIPURI_AS,
96 INPUT_LANG_MANIPURI_BN,
101 const double DOUBLE_SPACE_INTERVAL = 1.0;
103 static Eina_Bool _clear_hide_timer();
104 static Ecore_Timer *_hide_timer = NULL;
106 static const char *_ecore_imf_event_empty = "";
108 // TIZEN_ONLY(20150708): Support back key
109 #define BACK_KEY "XF86Back"
110 #define OLD_BACK_KEY "XF86Stop"
112 static Eina_Bool will_hide = EINA_FALSE;
113 static Eina_Bool ignore_hide = EINA_FALSE;
115 static Ecore_Event_Filter *_ecore_event_filter_handler = NULL;
116 static Ecore_IMF_Context *_focused_ctx = NULL;
117 static Ecore_IMF_Context *_show_req_ctx = NULL;
118 static Ecore_IMF_Context *_hide_req_ctx = NULL;
119 static Ecore_IMF_Context *_focus_req_ctx = NULL;
120 static Ecore_IMF_Context *_input_panel_ctx = NULL;
121 static Eina_Bool _focus_req_only = EINA_TRUE;
123 static Eina_Rectangle _keyboard_geometry = {0, 0, 0, 0};
125 static Ecore_IMF_Input_Panel_State _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
126 static Ecore_Event_Handler *_win_focus_out_handler = NULL;
127 static Ecore_Event_Handler *_conformant_change_handler = NULL;
129 static Eina_Bool _custom_conformant_event = EINA_FALSE;
130 static Eina_Bool _received_will_hide_event = EINA_FALSE;
131 static Eina_Bool _conformant_reset_done = EINA_FALSE;
132 static Eina_Bool _conformant_reset_started = EINA_FALSE;
133 static Evas *_active_context_canvas = NULL;
134 static unsigned int _active_context_window_id = 0;
136 static Ecore_Device *_ime_device = NULL;
138 static double space_key_time = 0.0;
139 static Eina_Bool autoperiod_allow = EINA_FALSE;
140 static Eina_Bool autocap_allow = EINA_FALSE;
141 static Eina_Bool hw_keyboard_mode = EINA_FALSE;
142 static Eina_Bool _preedit_cursor_changed = EINA_FALSE;
144 static Input_Language input_lang = INPUT_LANG_OTHER;
145 static Evas_Coord g_scr_w = 0, g_scr_h = 0;
147 static void set_autocapital (Ecore_IMF_Context *ctx);
149 static Eina_Bool g_key_rate_checked = EINA_FALSE, g_focused = EINA_FALSE;
150 static double g_original_key_rate = 0.0, g_original_key_delay = 0.0, g_desired_key_rate = 0.0;
153 typedef struct __LanguageInfo {
156 Eina_Unicode punc_code;
159 static LanguageInfo __language_infos [] = {
160 { "ur_PK", INPUT_LANG_URDU, 0x06D4 },
161 { "hi_IN", INPUT_LANG_HINDI, 0x0964 },
162 { "bn_IN", INPUT_LANG_BENGALI_IN, 0x0964 },
163 { "bn_BD", INPUT_LANG_BENGALI_BD, 0x0964 },
164 { "as_IN", INPUT_LANG_ASSAMESE, 0x0964 },
165 { "pa_IN", INPUT_LANG_PUNJABI, 0x0964 },
166 { "ne_NP", INPUT_LANG_NEPALI, 0x0964 },
167 { "or_IN", INPUT_LANG_ORIYA, 0x0964 },
168 { "mai_IN", INPUT_LANG_MAITHILI, 0x0964 },
169 { "hy_AM", INPUT_LANG_ARMENIAN, 0x0589 },
170 { "zh_CN", INPUT_LANG_CN, 0x3002 },
171 { "zh_HK", INPUT_LANG_CN_HK, 0x3002 },
172 { "zh_TW", INPUT_LANG_CN_TW, 0x3002 },
173 { "ja_JP", INPUT_LANG_JAPANESE, 0x3002 },
174 { "km_KH", INPUT_LANG_KHMER, 0x17D4 },
175 { "ko_KR", INPUT_LANG_KOREAN, 0x002E },
176 { "asb_IN", INPUT_LANG_ASSAMESE_BN, 0x0964 },
177 { "bna_IN", INPUT_LANG_BENGALI_AS, 0x0964 },
178 { "brx_IN", INPUT_LANG_BODO, 0x0964 },
179 { "doi_IN", INPUT_LANG_DOGRI, 0x0964 },
180 { "mni_IN", INPUT_LANG_MANIPURI, 0xabeb },
181 { "mnia_IN",INPUT_LANG_MANIPURI_AS, 0x0964 },
182 { "mnib_IN",INPUT_LANG_MANIPURI_BN, 0x0964 },
183 { "kok_IN", INPUT_LANG_KONKANI, 0x0964 },
184 { "sd_IN", INPUT_LANG_SINDHI, 0x0964 },
187 struct _WaylandIMContext
189 Ecore_IMF_Context *ctx;
191 struct wl_text_input_manager *text_input_manager;
192 struct wl_text_input *text_input;
194 Ecore_Wl2_Window *window;
195 Ecore_Wl2_Input *input;
199 char *preedit_commit;
201 Eina_List *preedit_attrs;
202 int32_t preedit_cursor;
210 int32_t cursor_position;
220 xkb_mod_mask_t control_mask;
221 xkb_mod_mask_t alt_mask;
222 xkb_mod_mask_t shift_mask;
223 xkb_mod_mask_t caps_mask;
224 xkb_mod_mask_t num_mask;
227 uint32_t content_purpose;
228 uint32_t content_hint;
229 Ecore_IMF_Input_Panel_Layout input_panel_layout;
231 // TIZEN_ONLY(20150716): Support return key type
232 uint32_t return_key_type;
234 Eina_Bool return_key_disabled;
237 uint32_t imdata_size;
239 uint32_t bidi_direction;
241 void *input_panel_data;
242 uint32_t input_panel_data_length;
248 } last_key_event_filter;
249 Eina_List *keysym_list;
251 uint32_t reset_serial;
253 Eina_Bool has_conformant;
254 char *prediction_hint;
261 } input_panel_position;
266 Ecore_IMF_Context *ctx;
267 WaylandIMContext *imcontext;
268 } Ecore_Imf_Wayland_Imcontext_Pair;
269 Eina_List *_ecore_imf_wayland_imcontext_pair_list = NULL;
271 static void _ecore_imf_wayland_imcontext_pair_add (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
273 Ecore_Imf_Wayland_Imcontext_Pair *pair = malloc (sizeof (Ecore_Imf_Wayland_Imcontext_Pair));
276 pair->imcontext = imcontext;
278 _ecore_imf_wayland_imcontext_pair_list = eina_list_append (_ecore_imf_wayland_imcontext_pair_list, pair);
282 static Ecore_Imf_Wayland_Imcontext_Pair* _ecore_imf_wayland_imcontext_pair_find (Ecore_IMF_Context *ctx)
285 Ecore_Imf_Wayland_Imcontext_Pair *pair;
286 EINA_LIST_FOREACH (_ecore_imf_wayland_imcontext_pair_list, l, pair)
287 if (pair->ctx == ctx) {
290 LOGE("The Ecore_Imf %p if not found in Ecore_IMF-WaylandIMContext pair list!!", ctx);
294 static void _ecore_imf_wayland_imcontext_pair_del (Ecore_IMF_Context *ctx)
298 Ecore_Imf_Wayland_Imcontext_Pair *pair;
300 EINA_LIST_FOREACH_SAFE (_ecore_imf_wayland_imcontext_pair_list, l, l_next, pair)
301 if (ctx == pair->ctx) {
303 _ecore_imf_wayland_imcontext_pair_list = eina_list_remove_list (_ecore_imf_wayland_imcontext_pair_list, l);
307 static void _ecore_imf_wayland_imcontext_pair_destroy ()
309 if (_ecore_imf_wayland_imcontext_pair_list) {
310 Ecore_Imf_Wayland_Imcontext_Pair *pair;
311 EINA_LIST_FREE (_ecore_imf_wayland_imcontext_pair_list, pair)
313 _ecore_imf_wayland_imcontext_pair_list = NULL;
317 static int _ecore_imf_wayland_imcontext_pair_log ()
319 char buffer[255] = { '\0' };
322 Ecore_Imf_Wayland_Imcontext_Pair *pair;
323 EINA_LIST_FOREACH(_ecore_imf_wayland_imcontext_pair_list, l, pair) {
325 snprintf(buffer + strlen(buffer), 255 - strlen(buffer), "%s[%p/%p]", (count ? "," : ""), pair->ctx, pair->imcontext);
330 LOGD("No Ecore_Imf / Wayland_Imcontext pair found");
332 LOGD("%d Pair(s) : %s", count, buffer);
338 // TIZEN_ONLY(20150708): Support back key
339 static void _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant);
340 static Eina_Bool show_input_panel(Ecore_IMF_Context *ctx);
343 reset_keyboard_geometry ()
345 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
346 if (wl2_display && (g_scr_w == 0 || g_scr_h == 0)) {
348 ecore_wl2_display_screen_size_get(wl2_display, &g_scr_w, &g_scr_h);
350 _keyboard_geometry.x = 0;
351 _keyboard_geometry.y = g_scr_h;
352 _keyboard_geometry.w = 0;
353 _keyboard_geometry.h = 0;
357 _device_info_free (void *data EINA_UNUSED, void *ev)
359 Ecore_Event_Device_Info *e;
362 eina_stringshare_del (e->name);
363 eina_stringshare_del (e->identifier);
364 eina_stringshare_del (e->seatname);
370 _device_info_send (unsigned int window, Eina_Bool flag)
372 Ecore_Event_Device_Info *e;
374 if (!(e = calloc (1, sizeof (Ecore_Event_Device_Info)))) return;
376 e->name = eina_stringshare_ref (IME_DEVICE_NAME);
377 e->identifier = eina_stringshare_ref (IME_DEVICE_NAME);
378 e->seatname = eina_stringshare_ref (IME_DEVICE_NAME);
379 e->clas = ECORE_DEVICE_CLASS_KEYBOARD;
380 e->subclas = ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD;
384 ecore_event_add (ECORE_EVENT_DEVICE_ADD, e, _device_info_free, NULL);
386 ecore_event_add (ECORE_EVENT_DEVICE_DEL, e, _device_info_free, NULL);
390 set_input_language (const char *input_lang_str)
393 input_lang = INPUT_LANG_OTHER;
395 for (i = 0; i < (sizeof (__language_infos) / sizeof (__language_infos[0])); i++) {
396 if (strcmp (input_lang_str, __language_infos[i].code) == 0) {
397 input_lang = __language_infos[i].lang;
403 static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
405 autoperiod_allow = vconf_keynode_get_bool (key);
408 static void autocapital_allow_changed_cb (keynode_t *key, void* data)
410 autocap_allow = vconf_keynode_get_bool (key);
413 static void input_language_changed_cb (keynode_t *key, void* data)
415 char *input_lang = vconf_keynode_get_str (key);
417 set_input_language (input_lang);
418 LOGD("input lang : %s", input_lang);
423 check_symbol (Eina_Unicode ucode, Eina_Unicode symbols[], int symbol_num)
426 for (i = 0; i < symbol_num; i++) {
428 if (ucode == symbols[i])
436 check_space_symbol (Eina_Unicode uchar)
438 Eina_Unicode space_symbols[] = {' ', 0x00A0 /* no-break space */, 0x3000 /* ideographic space */};
439 const int symbol_num = sizeof (space_symbols) / sizeof (space_symbols[0]);
441 return check_symbol (uchar, space_symbols, symbol_num);
445 autoperiod_insert (Ecore_IMF_Context *ctx)
447 char *plain_str = NULL;
449 Eina_Unicode *ustr = NULL;
450 Ecore_IMF_Event_Delete_Surrounding ev;
451 char *fullstop_mark = NULL;
454 WaylandIMContext *imcontext = NULL;
456 if (autoperiod_allow == EINA_FALSE)
461 Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
462 if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
465 if ((ecore_time_get () - space_key_time) > DOUBLE_SPACE_INTERVAL)
468 imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
469 if (!imcontext) return;
471 ecore_imf_context_surrounding_get (ctx, &plain_str, NULL);
472 if (!plain_str) goto done;
474 cursor_pos = imcontext->cursor_position;
476 // Convert string from UTF-8 to unicode
477 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
478 if (!ustr) goto done;
480 ulen = eina_unicode_strlen (ustr);
482 if (cursor_pos < 2 || cursor_pos > (int)ulen) {
483 LOGD ("invalid range. cursor pos : %d, length : %zu", cursor_pos, ulen);
487 if (check_space_symbol (ustr[cursor_pos-1])) {
488 // any character (except space & punctuation) + press space key twice in short time
489 if (!(iswpunct (ustr[cursor_pos-2]) || check_space_symbol (ustr[cursor_pos-2])) &&
490 iswprint(ustr[cursor_pos-2])) {
493 // any character (except space & punctuation) + space + press space key twice in short time
494 else if (cursor_pos >= 3 &&
495 check_space_symbol (ustr[cursor_pos-2]) &&
496 !(iswpunct (ustr[cursor_pos-3]) || check_space_symbol (ustr[cursor_pos-3])) &&
497 iswprint(ustr[cursor_pos-3])) {
503 ev.n_chars = del_chars;
504 ev.offset = del_chars * -1;
506 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
508 if (input_lang == INPUT_LANG_OTHER) {
509 fullstop_mark = strdup (".");
512 Eina_Unicode wbuf[2] = {0};
513 wbuf[0] = __language_infos[input_lang].punc_code;
515 fullstop_mark = eina_unicode_unicode_to_utf8 (wbuf, NULL);
518 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)fullstop_mark);
521 free (fullstop_mark);
522 fullstop_mark = NULL;
528 if (plain_str) free (plain_str);
529 if (ustr) free (ustr);
530 space_key_time = ecore_time_get ();
534 check_except_autocapital (Eina_Unicode *ustr, int cursor_pos)
536 const char *except_str[] = {"e.g.", "E.g."};
537 unsigned int i = 0, j = 0, len = 0;
538 for (i = 0; i < (sizeof (except_str) / sizeof (except_str[0])); i++) {
539 len = strlen (except_str[i]);
540 if (cursor_pos < (int)len)
543 for (j = len; j > 0; j--) {
544 if (ustr[cursor_pos-j] != except_str[i][len-j])
548 if (j == 0) return EINA_TRUE;
555 analyze_surrounding_text (Ecore_IMF_Context *ctx)
557 char *plain_str = NULL;
558 Eina_Unicode puncs[] = {'\n','.', '!', '?', 0x00BF /* ¿ */, 0x00A1 /* ¡ */,
559 0x3002 /* 。 */, 0x06D4 /* Urdu */, 0x0964 /* Hindi */,
560 0x0589 /* Armenian */, 0x17D4 /* Khmer */, 0x104A /* Myanmar */};
561 Eina_Unicode *ustr = NULL;
562 Eina_Bool ret = EINA_FALSE;
563 Eina_Bool detect_space = EINA_FALSE;
566 const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
567 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
568 if (!imcontext) return EINA_FALSE;
570 switch (ecore_imf_context_autocapital_type_get (ctx)) {
571 case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
573 case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
579 if (imcontext->preedit_text && strcmp (imcontext->preedit_text, "") != 0)
582 if (imcontext->cursor_position == 0)
585 ecore_imf_context_surrounding_get (ctx, &plain_str, &cursor_pos);
587 if (!plain_str) goto done;
589 if (cursor_pos == 0) {
594 // Convert string from UTF-8 to unicode
595 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
596 if (!ustr) goto done;
598 if (eina_unicode_strlen (ustr) < (size_t)cursor_pos) goto done;
600 if (cursor_pos >= 1) {
601 if (ecore_imf_context_autocapital_type_get (ctx) == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
602 // Check space or no-break space
603 if (check_space_symbol (ustr[cursor_pos-1])) {
609 // Check paragraph separator <PS> or carriage return <br>
610 if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
615 for (i = cursor_pos; i > 0; i--) {
616 // Check space or no-break space
617 if (check_space_symbol (ustr[i-1])) {
618 detect_space = EINA_TRUE;
622 // Check punctuation and following the continuous space(s)
623 if (detect_space && check_symbol (ustr[i-1], puncs, punc_num)) {
624 if (check_except_autocapital (ustr, i))
636 if ((i == 0) && (detect_space == EINA_TRUE)) {
637 // continuous space(s) without any character
644 if (ustr) free (ustr);
645 if (plain_str) free (plain_str);
651 set_autocapital (Ecore_IMF_Context *ctx)
653 Eina_Bool uppercase = EINA_FALSE;
655 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
656 if (!imcontext || !imcontext->text_input || !imcontext->input) return;
658 if (hw_keyboard_mode) return;
660 if (ecore_imf_context_input_panel_layout_get (ctx) != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
663 // Check autocapital type
664 if (ecore_imf_context_input_panel_caps_lock_mode_get (ctx)) {
665 uppercase = EINA_TRUE;
667 if (autocap_allow == EINA_FALSE)
670 uppercase = analyze_surrounding_text (ctx);
673 LOGD ("ctx : %p, auto capital : %d", ctx, uppercase);
674 wl_text_input_set_capital_mode (imcontext->text_input, uppercase);
677 static Ecore_IMF_Context *
680 return (_show_req_ctx ? _show_req_ctx : _focused_ctx);
684 check_hide_key(const char *keyname)
686 if (!keyname) return EINA_FALSE;
688 if (strcmp(keyname, "Escape") == 0 ||
689 strcmp(keyname, BACK_KEY) == 0 ||
690 strcmp(keyname, OLD_BACK_KEY) == 0)
697 _ecore_key_modifiers_to_ecore_imf_locks(unsigned int modifiers)
699 unsigned int locks = 0;
701 if (modifiers & ECORE_EVENT_LOCK_SCROLL)
702 locks |= ECORE_IMF_KEYBOARD_LOCK_SCROLL;
704 if (modifiers & ECORE_EVENT_LOCK_CAPS)
705 locks |= ECORE_IMF_KEYBOARD_LOCK_CAPS;
707 if (modifiers & ECORE_EVENT_LOCK_NUM)
708 locks |= ECORE_IMF_KEYBOARD_LOCK_NUM;
714 _ecore_key_modifiers_to_ecore_imf_modifiers(unsigned int modifiers)
716 unsigned int mask = 0;
718 /**< "Control" is pressed */
719 if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
720 mask |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
722 /**< "Alt" is pressed */
723 if (modifiers & ECORE_EVENT_MODIFIER_ALT)
724 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
726 /**< "Shift" is pressed */
727 if (modifiers & ECORE_EVENT_MODIFIER_SHIFT)
728 mask |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT;
730 /**< "Win" (between "Ctrl" and "Alt") is pressed */
731 if (modifiers & ECORE_EVENT_MODIFIER_WIN)
732 mask |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
734 /**< "AltGr" is pressed */
735 if (modifiers & ECORE_EVENT_MODIFIER_ALTGR)
736 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
742 _ecore_event_to_ecore_imf_key_down_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Down *imf_event)
744 if (!ecore_event || !imf_event)
747 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
748 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
749 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
750 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
751 imf_event->timestamp = ecore_event->timestamp;
753 if (ecore_event->dev) {
754 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
755 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
756 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
759 imf_event->dev_name = _ecore_imf_event_empty;
760 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
761 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
764 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
765 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
769 _ecore_event_to_ecore_imf_key_up_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Up *imf_event)
771 if (!ecore_event || !imf_event)
774 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
775 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
776 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
777 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
778 imf_event->timestamp = ecore_event->timestamp;
780 if (ecore_event->dev) {
781 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
782 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
783 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
786 imf_event->dev_name = _ecore_imf_event_empty;
787 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
788 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
791 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
792 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
795 static Eina_Bool check_nograb_backkey()
797 char *nograb_backkey = getenv ("ISF_KEY_NOGRAB_BACKKEY");
798 if (nograb_backkey) {
799 if (atoi (nograb_backkey) != 0)
800 return EINA_TRUE; /* the event is kept */
807 key_down_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
809 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
810 if (!ev || !ev->keyname) return EINA_TRUE; /* the event is kept */
812 Ecore_IMF_Context *active_ctx = get_using_ctx ();
814 if (!active_ctx) return EINA_TRUE; /* the event is kept */
816 if (check_nograb_backkey()) return EINA_TRUE; /* the event is kept */
818 if ((_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW ||
819 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW) &&
820 check_hide_key(ev->keyname)) {
822 SECURE_LOGD ("%s key is pressed.", ev->keyname);
824 Ecore_IMF_Event_Key_Down imf_event;
825 Eina_Bool filter_ret = EINA_FALSE;
827 _ecore_event_to_ecore_imf_key_down_event(ev, &imf_event);
830 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_DOWN, (Ecore_IMF_Event *)&imf_event);
834 SECURE_LOGD ("%s key is pressed. ret : %d", ev->keyname, filter_ret);
835 return EINA_FALSE; /* the event is removed from the queue */
837 return EINA_TRUE; /* the event is kept */
841 key_up_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
843 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
844 if (!ev || !ev->keyname) return EINA_TRUE; /* the event is kept */
846 Ecore_IMF_Context *active_ctx = get_using_ctx ();
848 if (!active_ctx) return EINA_TRUE; /* the event is kept */
850 if (check_nograb_backkey()) return EINA_TRUE; /* the event is kept */
852 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE ||
853 !check_hide_key(ev->keyname))
854 return EINA_TRUE; /* the event is kept */
856 SECURE_LOGD ("%s key is released.", ev->keyname);
858 Ecore_IMF_Event_Key_Up imf_event;
859 Eina_Bool filter_ret = EINA_FALSE;
861 _ecore_event_to_ecore_imf_key_up_event(ev, &imf_event);
864 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_UP, (Ecore_IMF_Event *)&imf_event);
868 SECURE_LOGD ("%s key is released. ret : %d", ev->keyname, filter_ret);
870 return EINA_FALSE; /* the event is removed from the queue */
873 ecore_imf_context_reset(active_ctx);
874 _input_panel_hide(active_ctx, EINA_TRUE);
875 return EINA_FALSE; /* the event is removed from the queue */
880 rotary_event_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
882 Ecore_Event_Detent_Rotate *ev = event;
883 if (!ev) return EINA_TRUE;
885 Ecore_IMF_Context *active_ctx = NULL;
887 active_ctx = _show_req_ctx;
888 else if (_focused_ctx)
889 active_ctx = _focused_ctx;
891 if (!active_ctx) return EINA_TRUE;
893 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
896 ecore_imf_context_reset(active_ctx);
897 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(active_ctx);
898 if (imcontext && imcontext->input && imcontext->text_input) {
899 isf_device_type_e device_type = find_device_type_from_ecore_event(ECORE_EVENT_DETENT_ROTATE);
903 if (device_buffer_encode((const char*)(event), sizeof(Ecore_Event_Detent_Rotate), &buffer, &buflen) &&
904 buffer && buflen > 0) {
905 wl_text_input_process_input_device_event(imcontext->text_input,
906 (unsigned int)device_type, buffer, buflen);
908 if (buffer) free(buffer);
915 _ecore_event_filter_cb(void *data, void *loop_data EINA_UNUSED, int type, void *event)
917 if (type == ECORE_EVENT_KEY_DOWN) {
918 return key_down_filter_cb(data, type, event);
920 else if (type == ECORE_EVENT_KEY_UP) {
921 return key_up_filter_cb(data, type, event);
923 /* The IME needs to process Rotary event prior to client application */
924 else if (type == ECORE_EVENT_DETENT_ROTATE) {
925 return rotary_event_cb(data, type, event);
932 register_key_handler()
934 if (!_ecore_event_filter_handler)
935 _ecore_event_filter_handler = ecore_event_filter_add(NULL, _ecore_event_filter_cb, NULL, NULL);
939 unregister_key_handler()
941 if (_ecore_event_filter_handler) {
942 ecore_event_filter_del(_ecore_event_filter_handler);
943 _ecore_event_filter_handler = NULL;
954 LOGD("Delete hide timer");
955 ecore_timer_del(_hide_timer);
963 static void _win_focus_out_handler_del ()
965 if (_win_focus_out_handler) {
966 ecore_event_handler_del (_win_focus_out_handler);
967 _win_focus_out_handler = NULL;
971 static void _conformant_change_handler_del()
973 if (_conformant_change_handler) {
974 ecore_event_handler_del(_conformant_change_handler);
975 _conformant_change_handler = NULL;
980 _send_input_panel_hide_request(Ecore_IMF_Context *ctx)
984 // TIZEN_ONLY(20150708): Support back key
985 _hide_req_ctx = NULL;
988 _win_focus_out_handler_del ();
990 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
991 if (imcontext && imcontext->text_input) {
992 LOGD("Send IME hide request");
993 wl_text_input_hide_input_panel(imcontext->text_input);
995 LOGD("creating temporary context for sending hide request");
996 const char *ctx_id = ecore_imf_context_default_id_get();
997 Ecore_IMF_Context *temp_context = ecore_imf_context_add(ctx_id);
999 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(temp_context);
1000 if (imcontext && imcontext->text_input) {
1001 LOGD("Send IME hide request");
1002 wl_text_input_hide_input_panel(imcontext->text_input);
1005 ecore_imf_context_del(temp_context);
1010 static void _conformant_area_free (void *data EINA_UNUSED, void *ev)
1012 Ecore_Wl2_Event_Conformant_Change *e = ev;
1017 static void add_conformant_change_event(Ecore_Wl2_Window *window)
1019 Ecore_Wl2_Event_Conformant_Change *ev;
1020 ev = calloc(1, sizeof(Ecore_Wl2_Event_Conformant_Change));
1022 ev->win = ecore_wl2_window_id_get(window);
1025 ecore_event_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, ev, _conformant_area_free, NULL);
1029 static Eina_Rectangle _conformant_area_backup = { 0, 0, 0, 0 };
1030 static Eina_Bool reset_conformant_area(Ecore_IMF_Context *ctx)
1032 Eina_Bool reset = EINA_FALSE;
1033 Eina_Bool has_conformant = EINA_FALSE;
1034 Ecore_Wl2_Window *window = NULL;
1036 if (!ctx) return EINA_FALSE;
1038 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1040 window = imcontext->window;
1041 has_conformant = imcontext->has_conformant;
1045 int x = 0, y = 0, w = 0, h = 0;
1046 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1049 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w != 0 || h != 0)) {
1051 _conformant_area_backup.x = x;
1052 _conformant_area_backup.y = y;
1053 _conformant_area_backup.w = w;
1054 _conformant_area_backup.h = h;
1058 LOGD("reset %d", reset);
1060 ecore_wl2_window_keyboard_geometry_set(window, 0, 0, 0, 0);
1062 add_conformant_change_event(window);
1064 _conformant_reset_started = EINA_TRUE;
1070 static void restore_conformant_area(Ecore_IMF_Context *ctx)
1072 Eina_Bool restore = EINA_FALSE;
1073 Eina_Bool has_conformant = EINA_FALSE;
1074 Ecore_Wl2_Window *window = NULL;
1078 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1080 window = imcontext->window;
1081 has_conformant = imcontext->has_conformant;
1085 int x = 0, y = 0, w = 0, h = 0;
1086 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1089 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w == 0 || h == 0)) {
1090 restore = EINA_TRUE;
1094 LOGD("restore %d", restore);
1096 ecore_wl2_window_keyboard_geometry_set(window,
1097 _conformant_area_backup.x, _conformant_area_backup.y,
1098 _conformant_area_backup.w, _conformant_area_backup.h);
1100 add_conformant_change_event(window);
1102 _conformant_reset_started = EINA_FALSE;
1107 _send_will_hide_ack(WaylandIMContext *imcontext)
1109 if (!imcontext) return;
1110 if (!(imcontext->text_input)) return;
1112 const char *szWillHideAck = "WILL_HIDE_ACK";
1113 wl_text_input_set_input_panel_data(imcontext->text_input, szWillHideAck, strlen(szWillHideAck));
1114 _received_will_hide_event = EINA_FALSE;
1118 _hide_timer_handler(void *data)
1120 LOGD("Start hide timer");
1121 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1122 _send_input_panel_hide_request(ctx);
1124 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1125 LOGD("No need to reset conformant, sending ACK right away");
1126 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1130 reset_keyboard_geometry();
1133 return ECORE_CALLBACK_CANCEL;
1137 _input_panel_hide_timer_start(void *data)
1140 LOGD("Add timer to hide input panel");
1141 _hide_timer = ecore_timer_add(HIDE_TIMER_INTERVAL, _hide_timer_handler, data);
1146 _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant)
1148 LOGD ("ctx : %p", ctx);
1152 will_hide = EINA_TRUE;
1153 _conformant_reset_started = EINA_FALSE;
1155 if (instant || (_hide_timer && ecore_timer_pending_get(_hide_timer) <= 0.0)) {
1156 _clear_hide_timer();
1157 _send_input_panel_hide_request(ctx);
1159 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1160 LOGD("No need to reset conformant, sending ACK right away");
1161 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1165 reset_keyboard_geometry();
1167 _input_panel_hide_timer_start(ctx);
1168 // TIZEN_ONLY(20150708): Support back key
1169 _hide_req_ctx = ctx;
1175 utf8_offset_to_characters(const char *str, int offset)
1180 for (; index < offset; i++) {
1181 if (eina_unicode_utf8_next_get(str, &index) == 0)
1189 send_cursor_location(WaylandIMContext *imcontext)
1191 #if ENABLE_SEND_CURSOR_LOCATION
1192 Ecore_Evas *ee = NULL;
1193 int canvas_x = 0, canvas_y = 0;
1195 if (imcontext->canvas) {
1196 ee = ecore_evas_ecore_evas_get(imcontext->canvas);
1198 ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
1201 if (imcontext->input && imcontext->text_input) {
1202 wl_text_input_set_cursor_rectangle(imcontext->text_input,
1203 imcontext->cursor_location.x + canvas_x,
1204 imcontext->cursor_location.y + canvas_y,
1205 imcontext->cursor_location.width,
1206 imcontext->cursor_location.height);
1212 update_state(WaylandIMContext *imcontext)
1214 if (!imcontext->ctx)
1217 send_cursor_location (imcontext);
1219 if (imcontext->input && imcontext->text_input) {
1220 wl_text_input_commit_state(imcontext->text_input, ++imcontext->serial);
1225 check_serial(WaylandIMContext *imcontext, uint32_t serial)
1230 Ecore_IMF_Preedit_Attr *attr;
1232 if ((imcontext->serial - serial) >
1233 (imcontext->serial - imcontext->reset_serial)) {
1234 LOGD("outdated serial: %u, current: %u, reset: %u",
1235 serial, imcontext->serial, imcontext->reset_serial);
1237 imcontext->pending_preedit.cursor = 0;
1239 if (imcontext->pending_preedit.attrs) {
1240 EINA_LIST_FREE(imcontext->pending_preedit.attrs, attr) {
1244 imcontext->pending_preedit.attrs = NULL;
1255 clear_preedit_text(WaylandIMContext *imcontext)
1257 Ecore_IMF_Preedit_Attr *attr = NULL;
1259 imcontext->preedit_cursor = 0;
1261 if (imcontext->preedit_text) {
1262 free(imcontext->preedit_text);
1263 imcontext->preedit_text = NULL;
1266 if (imcontext->preedit_attrs) {
1267 EINA_LIST_FREE(imcontext->preedit_attrs, attr) {
1273 imcontext->preedit_attrs = NULL;
1277 clear_preedit(WaylandIMContext *imcontext)
1279 clear_preedit_text(imcontext);
1281 if (imcontext->preedit_commit) {
1282 free(imcontext->preedit_commit);
1283 imcontext->preedit_commit = NULL;
1288 text_input_commit_string(void *data,
1289 struct wl_text_input *text_input EINA_UNUSED,
1293 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1294 Eina_Bool old_preedit = EINA_FALSE;
1296 SECURE_LOGD("ctx : %p, commit event (text: '%s', current pre-edit: '%s')",
1299 imcontext->preedit_text ? imcontext->preedit_text : "");
1301 if (!imcontext->ctx)
1305 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1307 if (!check_serial(imcontext, serial))
1311 ecore_imf_context_event_callback_call(imcontext->ctx,
1312 ECORE_IMF_CALLBACK_PREEDIT_END,
1316 clear_preedit(imcontext);
1321 Eina_Unicode *ustr = eina_unicode_utf8_to_unicode (text, NULL);
1324 if (eina_unicode_strcmp (ustr, L" ") == 0 ||
1325 eina_unicode_strcmp (ustr, L" ") == 0)
1326 autoperiod_insert (imcontext->ctx);
1331 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)text);
1335 commit_preedit(WaylandIMContext *imcontext)
1337 if (!imcontext->preedit_commit)
1340 if (!imcontext->ctx)
1343 imcontext->pending_preedit.cursor = 0;
1344 clear_preedit_text(imcontext);
1346 size_t commit_len = strlen(imcontext->preedit_commit);
1348 if (commit_len == 0) {
1349 ecore_imf_context_event_callback_call(imcontext->ctx,
1350 ECORE_IMF_CALLBACK_PREEDIT_START,
1353 ecore_imf_context_event_callback_call(imcontext->ctx,
1354 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1357 ecore_imf_context_event_callback_call(imcontext->ctx,
1358 ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
1361 if (commit_len > 0) {
1362 char *commit_str = NULL;
1363 commit_str = strdup(imcontext->preedit_commit);
1364 clear_preedit(imcontext);
1365 ecore_imf_context_event_callback_call(imcontext->ctx,
1366 ECORE_IMF_CALLBACK_COMMIT,
1367 (void *)commit_str);
1373 set_focus(Ecore_IMF_Context *ctx)
1375 LOGD("ctx : %p", ctx);
1376 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1377 if (!imcontext) return EINA_FALSE;
1379 if (!imcontext->window) {
1380 LOGW("window is not given");
1384 Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
1386 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1390 struct wl_seat *seat = ecore_wl2_input_seat_get(input);
1392 LOGW("ctx : %p, Can't get Wl_seat", ctx);
1396 imcontext->input = input;
1399 wl_text_input_activate(imcontext->text_input, seat,
1400 ecore_wl2_window_surface_get(imcontext->window));
1402 if (g_key_rate_checked == EINA_FALSE && g_desired_key_rate == 0.0) {
1403 char *key_rate = getenv ("ISF_KEY_REPEAT_RATE");
1405 g_desired_key_rate = atof (key_rate);
1406 if (g_desired_key_rate > 0.0) {
1407 if (!ecore_wl2_input_keyboard_repeat_get (input, &g_original_key_rate, &g_original_key_delay)) {
1408 LOGE ("ecore_wl2_input_keyboard_repeat_get failed");
1411 LOGD ("ecore_wl2_input_keyboard_repeat_get original rate=%f, delay=%f. Desired rate=%f",
1412 g_original_key_rate, g_original_key_delay, g_desired_key_rate);
1416 g_key_rate_checked = EINA_TRUE;
1419 if (g_desired_key_rate > 0.0 && g_original_key_delay > 0.0 && !g_focused) {
1420 g_focused = EINA_TRUE;
1421 if (!ecore_wl2_input_keyboard_repeat_set (input, g_desired_key_rate, g_original_key_delay)) {
1422 LOGE ("ecore_wl2_input_keyboard_repeat_set failed");
1425 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_desired_key_rate, g_original_key_delay);
1433 set_focus_out(Ecore_IMF_Context *ctx)
1435 char *surrounding = NULL;
1438 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1439 if (!imcontext || !imcontext->input) return;
1441 if (ecore_imf_context_surrounding_get(ctx, &surrounding, &cursor_pos)) {
1443 wl_text_input_finalize_content(imcontext->text_input, surrounding, cursor_pos);
1449 if (imcontext->text_input)
1450 wl_text_input_deactivate(imcontext->text_input,
1451 ecore_wl2_input_seat_get(imcontext->input));
1453 if (ctx == _focused_ctx)
1454 _focused_ctx = NULL;
1456 imcontext->input = NULL;
1457 _preedit_cursor_changed = EINA_FALSE;
1459 if (g_desired_key_rate > 0.0 && g_focused) {
1460 g_focused = EINA_FALSE;
1462 Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
1464 if (!ecore_wl2_input_keyboard_repeat_set (input, g_original_key_rate, g_original_key_delay)) {
1465 LOGE ("ecore_wl2_input_keyboard_repeat_set failed.");
1468 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_original_key_rate, g_original_key_delay);
1472 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1477 // TIZEN_ONLY(20160217): ignore the duplicate show request
1478 static Eina_Bool _compare_context(Ecore_IMF_Context *ctx1, Ecore_IMF_Context *ctx2)
1480 if (!ctx1 || !ctx2) return EINA_FALSE;
1482 if ((ecore_imf_context_autocapital_type_get(ctx1) == ecore_imf_context_autocapital_type_get(ctx2)) &&
1483 (ecore_imf_context_input_panel_layout_get(ctx1) == ecore_imf_context_input_panel_layout_get(ctx2)) &&
1484 (ecore_imf_context_input_panel_layout_variation_get(ctx1) == ecore_imf_context_input_panel_layout_variation_get(ctx2)) &&
1485 (ecore_imf_context_input_panel_language_get(ctx1) == ecore_imf_context_input_panel_language_get(ctx2)) &&
1486 (ecore_imf_context_input_panel_return_key_type_get(ctx1) == ecore_imf_context_input_panel_return_key_type_get(ctx2)) &&
1487 (ecore_imf_context_input_panel_return_key_disabled_get(ctx1) == ecore_imf_context_input_panel_return_key_disabled_get(ctx2)) &&
1488 (ecore_imf_context_input_panel_caps_lock_mode_get(ctx1) == ecore_imf_context_input_panel_caps_lock_mode_get(ctx2)))
1495 static void send_get_hide_permission(WaylandIMContext *imcontext)
1497 if (imcontext->text_input) {
1498 ignore_hide = EINA_FALSE;
1499 wl_text_input_get_hide_permission(imcontext->text_input);
1503 static Eina_Bool _client_window_focus_out_cb(void *data, int ev_type, void *ev)
1505 Ecore_Wl2_Event_Focus_Out *e = (Ecore_Wl2_Event_Focus_Out *)ev;
1506 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1507 if (!ctx || !e) return ECORE_CALLBACK_PASS_ON;
1509 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
1510 if (!imcontext || !imcontext->window) return ECORE_CALLBACK_PASS_ON;
1512 unsigned int client_win_id = ecore_wl2_window_id_get (imcontext->window);
1514 LOGD ("ctx : %p, client_window id : %#x, focus-out win : %#x", ctx, client_win_id, e->window);
1516 if (client_win_id > 0) {
1517 if (e->window == client_win_id) {
1518 LOGD ("window focus out");
1520 if (_focused_ctx == ctx) {
1521 wayland_im_context_focus_out (ctx);
1524 if (_show_req_ctx == ctx) {
1525 send_get_hide_permission(imcontext);
1530 send_get_hide_permission(imcontext);
1533 return ECORE_CALLBACK_PASS_ON;
1536 static void send_will_hide_ack(Ecore_IMF_Context *ctx)
1538 Eina_Bool need_temporary_context = EINA_FALSE;
1539 Eina_Bool has_conformant = EINA_FALSE;
1540 WaylandIMContext *imcontext = NULL;
1543 LOGD("ctx is NULL");
1544 need_temporary_context = EINA_TRUE;
1546 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1548 LOGD("imcontext is NULL :%p", ctx);
1549 need_temporary_context = EINA_TRUE;
1551 has_conformant = imcontext->has_conformant;
1555 /* When the RENDER_POST event is emitted, it is possible that our IMF_Context is already deleted,
1556 meaning that there is no connection available for communicating with the window manager.
1557 So we are creating a temporary context for sending WILL_HIDE_ACK message */
1558 if (need_temporary_context) {
1559 LOGD("creating temporary context for sending WILL_HIDE_ACK");
1560 const char *ctx_id = ecore_imf_context_default_id_get();
1561 ctx = ecore_imf_context_add(ctx_id);
1563 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1567 if (ctx && imcontext) {
1568 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant) {
1569 if (_conformant_reset_done && _received_will_hide_event) {
1570 LOGD("Send will hide ack, _conformant_reset_done = 1, received_will_hide_event = 1");
1571 _send_will_hide_ack(imcontext);
1572 _conformant_reset_done = EINA_FALSE;
1573 _received_will_hide_event = EINA_FALSE;
1575 LOGD ("_conformant_reset_done=%d, received_will_hide_event=%d",
1576 _conformant_reset_done, _received_will_hide_event);
1579 LOGD("Send will hide ack right away, since there is no conformant available : %p %d",
1580 ecore_imf_context_client_canvas_get(ctx), has_conformant);
1581 _send_will_hide_ack (imcontext);
1585 if (need_temporary_context) {
1587 ecore_imf_context_del(ctx);
1592 static void _render_post_cb(void *data, Evas *e, void *event_info)
1594 void *callback = evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1595 _conformant_reset_done = EINA_TRUE;
1596 _conformant_reset_started = EINA_FALSE;
1597 LOGD("[_render_post_cb], _conformant_reset_done = 1 , %p", callback);
1598 send_will_hide_ack(NULL);
1601 static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
1603 Ecore_Wl2_Event_Conformant_Change *e = (Ecore_Wl2_Event_Conformant_Change *)ev;
1604 if (!e) return ECORE_CALLBACK_PASS_ON;
1606 LOGD ("CONFORMANT changed!! part type : %d, state : %d, win : %d", e->part_type, e->state, e->win);
1608 if (_active_context_window_id != e->win)
1609 return ECORE_CALLBACK_PASS_ON;
1611 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1612 if (!wl2_display) return ECORE_CALLBACK_PASS_ON;
1614 Ecore_Wl2_Window *window = ecore_wl2_display_window_find(wl2_display, e->win);
1615 if (!window) return ECORE_CALLBACK_PASS_ON;
1618 LOGD("_conformant_reset_done = 0, registering _render_post_cb : %p %p", _active_context_canvas, window);
1619 _conformant_reset_done = EINA_FALSE;
1620 if (_active_context_canvas && ecore_wl2_window_conformant_get(window) && !_custom_conformant_event) {
1621 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1622 evas_event_callback_add(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb, NULL);
1625 _conformant_reset_done = EINA_FALSE;
1626 if (_active_context_canvas) {
1627 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1630 Eina_Bool result = EINA_FALSE;
1631 int x = 0, y = 0, w = 0, h = 0;
1634 /* TV IME consists of two or three windows, so ecore_wl2_window_keyboard_geometry_get() may return wrong size. */
1635 x = _keyboard_geometry.x, y = _keyboard_geometry.y, w = _keyboard_geometry.w, h = _keyboard_geometry.h;
1636 if (_keyboard_geometry.w == 0 || _keyboard_geometry.h == 0) {
1637 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1640 /* Since the input_panel_geometry is not delivered right at the moment, we use conformant geometry instead */
1641 x = 0, y = 0, w = 0, h = 0;
1642 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1646 Evas_Coord scr_w = 0, scr_h = 0;
1648 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1650 ecore_wl2_display_screen_size_get(wl2_display ,&scr_w, &scr_h);
1651 int rot = ecore_wl2_window_rotation_get(window);
1652 /* Assume we are using keyboard that has the same width to the screen width*/
1655 _keyboard_geometry.h = w;
1656 _keyboard_geometry.w = h;
1657 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1658 _keyboard_geometry.x = 0;
1661 _keyboard_geometry.w = w;
1662 _keyboard_geometry.h = h;
1663 _keyboard_geometry.x = 0;
1664 _keyboard_geometry.y = scr_h - _keyboard_geometry.h;
1667 _keyboard_geometry.h = w;
1668 _keyboard_geometry.w = h;
1669 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1670 _keyboard_geometry.x = 0;
1673 _keyboard_geometry.x = x;
1674 _keyboard_geometry.y = y;
1675 _keyboard_geometry.w = w;
1676 _keyboard_geometry.h = h;
1678 LOGD("[KEYPAD]: scr %dx%d, rot %d, orig (%d,%d, %dx%d)", scr_w, scr_h, rot, x, y, w, h);
1679 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
1682 ecore_imf_context_input_panel_event_callback_call(_show_req_ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
1686 return ECORE_CALLBACK_PASS_ON;
1690 get_purpose(Ecore_IMF_Context *ctx)
1692 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1693 uint32_t new_purpose = 0;
1695 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1699 switch (imcontext->content_purpose) {
1700 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
1701 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED)
1702 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED;
1703 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL)
1704 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL;
1705 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL)
1706 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL;
1708 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
1710 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
1711 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY)
1712 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS;
1714 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
1716 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
1717 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME)
1718 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME;
1719 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME)
1720 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NAME;
1722 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
1725 new_purpose = imcontext->content_purpose;
1732 static void _canvas_focus_in_cb(void *data, Evas *e, void *event_info)
1734 LOGD("ctx : %p %d", _focus_req_ctx, _focus_req_only);
1736 if (_focus_req_ctx) {
1737 set_focus(_focus_req_ctx);
1738 if (ecore_imf_context_input_panel_enabled_get (_focus_req_ctx) || !_focus_req_only)
1739 if (!ecore_imf_context_input_panel_show_on_demand_get (_focus_req_ctx) || !_focus_req_only)
1740 show_input_panel (_focus_req_ctx);
1742 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(_focus_req_ctx);
1743 if (imcontext && imcontext->canvas)
1744 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1745 _focus_req_ctx = NULL;
1746 _focus_req_only = EINA_TRUE;
1751 show_input_panel(Ecore_IMF_Context *ctx)
1753 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1755 char *surrounding = NULL;
1758 if ((!imcontext) || (!imcontext->text_input))
1761 if (!imcontext->input) {
1763 if (!imcontext->input) {
1764 _focus_req_ctx = ctx;
1765 _focus_req_only = EINA_FALSE;
1766 if (imcontext->canvas) {
1767 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1768 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
1773 _clear_hide_timer ();
1775 _win_focus_out_handler_del ();
1777 if (!imcontext->input)
1780 ignore_hide = EINA_TRUE;
1782 _win_focus_out_handler = ecore_event_handler_add (ECORE_WL2_EVENT_FOCUS_OUT, _client_window_focus_out_cb, ctx);
1783 _conformant_change_handler_del ();
1784 _conformant_change_handler = ecore_event_handler_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, _conformant_change_cb, NULL);
1786 // TIZEN_ONLY(20160217): ignore the duplicate show request
1787 if ((_show_req_ctx == ctx) && _compare_context(_show_req_ctx, ctx) && (!will_hide)) {
1788 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW ||
1789 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
1790 LOGD("already show. ctx : %p", ctx);
1796 will_hide = EINA_FALSE;
1797 _show_req_ctx = ctx;
1798 _input_panel_ctx = ctx;
1799 _active_context_canvas = ecore_imf_context_client_canvas_get(ctx);
1803 // TIZEN_ONLY(20150715): Support input_panel_state_get
1804 int layout = ecore_imf_context_input_panel_layout_get (ctx);
1805 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1808 if (layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
1809 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
1811 wl_text_input_set_content_type(imcontext->text_input,
1812 imcontext->content_hint,
1815 if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos)) {
1816 SECURE_LOGD ("surrounding text : %s", surrounding);
1820 imcontext->cursor_position = cursor_pos;
1821 wl_text_input_set_cursor_position(imcontext->text_input, cursor_pos);
1823 // TIZEN_ONLY(20150716): Support return key type
1824 wl_text_input_set_return_key_type(imcontext->text_input,
1825 imcontext->return_key_type);
1827 wl_text_input_set_return_key_disabled(imcontext->text_input,
1828 imcontext->return_key_disabled);
1830 if (imcontext->imdata_size > 0)
1831 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
1833 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
1835 set_autocapital (ctx);
1837 if (imcontext->mime_type)
1838 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
1840 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
1841 wl_text_input_set_input_panel_position(imcontext->text_input,
1842 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
1844 LOGD ("ctx : %p, layout : %d, layout variation : %d, language : %d, cursor position : %d",
1845 ctx, layout, layout_variation,
1846 ecore_imf_context_input_panel_language_get (ctx),
1848 LOGD ("input hint : %#x, bidi direction : %d, return key type : %d, return key disabled : %d, autocapital type : %d",
1849 ecore_imf_context_input_hint_get (ctx),
1850 imcontext->bidi_direction,
1851 ecore_imf_context_input_panel_return_key_type_get (ctx),
1852 ecore_imf_context_input_panel_return_key_disabled_get (ctx),
1853 ecore_imf_context_autocapital_type_get (ctx));
1854 LOGD ("client_window : %#lx, password mode : %d, prediction_allow : %d, mime_type : %s, input panel position x : %d, y : %d",
1855 (unsigned long int)ecore_imf_context_client_window_get (ctx),
1856 (imcontext->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) ? 1 : 0,
1857 ecore_imf_context_prediction_allow_get (ctx),
1858 imcontext->mime_type,
1859 imcontext->input_panel_position.x,
1860 imcontext->input_panel_position.y);
1862 if (_active_context_canvas && !evas_focus_state_get (_active_context_canvas)) {
1863 LOGW ("Canvas does not have focus!");
1867 if (hw_keyboard_mode) {
1868 LOGD("hw_keyboard_mode is TRUE, returning");
1872 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
1874 wl_text_input_show_input_panel(imcontext->text_input);
1876 if (imcontext->window) {
1877 _active_context_window_id = ecore_wl2_window_id_get(imcontext->window);
1878 imcontext->has_conformant = ecore_wl2_window_conformant_get(imcontext->window);
1880 imcontext->has_conformant = EINA_FALSE;
1886 static void delete_surrounding_text(WaylandIMContext *imcontext, int index, int length)
1888 Ecore_IMF_Event_Delete_Surrounding ev;
1889 LOGD("delete surrounding text (index: %d, length: %u)",
1893 ev.n_chars = length;
1895 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
1899 text_input_preedit_string(void *data,
1900 struct wl_text_input *text_input EINA_UNUSED,
1905 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1906 Eina_Bool old_preedit = EINA_FALSE;
1907 Eina_Bool preedit_changed = EINA_FALSE;
1909 SECURE_LOGD("ctx : %p, preedit event (text: '%s', current pre-edit: '%s')",
1912 imcontext->preedit_text ? imcontext->preedit_text : "");
1914 if (!check_serial(imcontext, serial))
1918 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1920 if (imcontext->preedit_text)
1921 preedit_changed = (strcmp(imcontext->preedit_text, text) != 0);
1923 preedit_changed = (strlen(text) != 0);
1925 if (_preedit_cursor_changed) {
1926 preedit_changed = EINA_TRUE;
1927 _preedit_cursor_changed = EINA_FALSE;
1930 if (imcontext->pending_preedit.attrs)
1931 preedit_changed = EINA_TRUE;
1933 clear_preedit(imcontext);
1935 imcontext->preedit_text = strdup(text);
1936 imcontext->preedit_commit = (strlen(text) > 0 ? strdup(commit) : NULL);
1937 imcontext->preedit_cursor =
1938 utf8_offset_to_characters(text, imcontext->pending_preedit.cursor);
1939 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
1941 imcontext->pending_preedit.attrs = NULL;
1943 if (preedit_changed) {
1945 ecore_imf_context_event_callback_call(imcontext->ctx,
1946 ECORE_IMF_CALLBACK_PREEDIT_START,
1950 ecore_imf_context_event_callback_call(imcontext->ctx,
1951 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1954 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
1955 ecore_imf_context_event_callback_call(imcontext->ctx,
1956 ECORE_IMF_CALLBACK_PREEDIT_END,
1963 text_input_delete_surrounding_text(void *data,
1964 struct wl_text_input *text_input EINA_UNUSED,
1968 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1969 delete_surrounding_text(imcontext, index, length);
1973 text_input_cursor_position(void *data EINA_UNUSED,
1974 struct wl_text_input *text_input EINA_UNUSED,
1978 LOGD("cursor_position for next commit (index: %d, anchor: %d)",
1983 text_input_preedit_styling(void *data,
1984 struct wl_text_input *text_input EINA_UNUSED,
1989 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1990 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
1995 case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
1996 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_NONE;
1998 case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
1999 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
2001 case WL_TEXT_INPUT_PREEDIT_STYLE_REVERSE:
2002 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
2004 case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
2005 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
2007 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR1:
2008 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
2010 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR2:
2011 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
2013 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR3:
2014 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
2016 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR4:
2017 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
2020 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
2024 attr->start_index = index;
2025 attr->end_index = index + length;
2027 imcontext->pending_preedit.attrs =
2028 eina_list_append(imcontext->pending_preedit.attrs, attr);
2032 text_input_preedit_cursor(void *data,
2033 struct wl_text_input *text_input EINA_UNUSED,
2036 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2038 LOGD("preedit cursor : %d", index);
2040 if (imcontext->pending_preedit.cursor != index) {
2041 imcontext->pending_preedit.cursor = index;
2042 _preedit_cursor_changed = EINA_TRUE;
2046 static xkb_mod_index_t
2047 modifiers_get_index(struct wl_array *modifiers_map, const char *name)
2049 xkb_mod_index_t index = 0;
2050 char *p = modifiers_map->data;
2052 while ((const char *)p < ((const char *)modifiers_map->data + modifiers_map->size))
2054 if (strcmp(p, name) == 0)
2061 return XKB_MOD_INVALID;
2064 static xkb_mod_mask_t
2065 modifiers_get_mask(struct wl_array *modifiers_map,
2068 xkb_mod_index_t index = modifiers_get_index(modifiers_map, name);
2070 if (index == XKB_MOD_INVALID)
2071 return XKB_MOD_INVALID;
2077 text_input_modifiers_map(void *data,
2078 struct wl_text_input *text_input EINA_UNUSED,
2079 struct wl_array *map)
2081 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2082 imcontext->shift_mask = modifiers_get_mask(map, XKB_MOD_NAME_SHIFT);
2083 imcontext->control_mask = modifiers_get_mask(map, XKB_MOD_NAME_CTRL);
2084 imcontext->alt_mask = modifiers_get_mask(map, XKB_MOD_NAME_ALT);
2085 imcontext->caps_mask = modifiers_get_mask(map, XKB_MOD_NAME_CAPS);
2086 imcontext->num_mask = modifiers_get_mask(map, XKB_MOD_NAME_NUM);
2090 _ecore_keyevent_free (void *data EINA_UNUSED, void *ev)
2092 Ecore_Event_Key *e = ev;
2093 if (e->dev) ecore_device_unref(e->dev);
2099 text_input_keysym(void *data,
2100 struct wl_text_input *text_input EINA_UNUSED,
2101 uint32_t serial EINA_UNUSED,
2107 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2108 char string[32] = {'\0'};
2109 char key[32] = {'\0'};
2110 char keyname[32] = {'\0'};
2113 memset(key, 0, sizeof(key));
2114 xkb_keysym_get_name(sym, key, sizeof(key));
2116 memset(keyname, 0, sizeof(keyname));
2117 xkb_keysym_get_name(sym, keyname, sizeof(keyname));
2118 if (keyname[0] == '\0')
2119 snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
2121 memset(string, 0, sizeof(string));
2122 xkb_keysym_to_utf8(sym, string, 32);
2124 SECURE_LOGD("key event (key: %s)", keyname);
2126 unsigned int key_len = strlen(key);
2127 unsigned int key_name_len = strlen(keyname);
2128 unsigned int key_string_len = strlen(string);
2130 if (key_len > sizeof(key)-1)
2131 key_len = sizeof(key)-1;
2133 if (key_name_len > sizeof(keyname)-1)
2134 key_name_len = sizeof(keyname)-1;
2136 if (key_string_len > sizeof(string)-1)
2137 key_string_len = sizeof(string)-1;
2139 e = calloc(1, sizeof(Ecore_Event_Key) + key_len + key_name_len +
2140 key_string_len + 3);
2143 e->keyname = (char *)(e + 1);
2144 e->key = e->keyname + key_name_len + 1;
2145 e->string = e->key + key_len + 1;
2146 e->compose = e->string;
2148 memcpy((void *)e->keyname, keyname, key_name_len);
2149 *((char *)e->keyname + key_name_len) = '\0';
2150 memcpy((void *)e->key, key, key_len);
2151 *((char *)e->key + key_len) = '\0';
2152 memcpy((void *)e->string, string, key_string_len);
2153 *((char *)e->string + key_string_len) = '\0';
2155 e->window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2156 e->event_window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2157 e->dev = ecore_device_ref(_ime_device);
2158 e->timestamp = 0; /* For distinguishing S/W keyboard event */
2161 if (modifiers & imcontext->shift_mask)
2162 e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
2164 if (modifiers & imcontext->control_mask)
2165 e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
2167 if (modifiers & imcontext->alt_mask)
2168 e->modifiers |= ECORE_EVENT_MODIFIER_ALT;
2170 if (modifiers & MOD_Mod5_MASK)
2171 e->modifiers |= MOD_Mod5_MASK;
2173 if (modifiers & imcontext->caps_mask)
2174 e->modifiers |= ECORE_EVENT_LOCK_CAPS;
2176 if (modifiers & imcontext->num_mask)
2177 e->modifiers |= ECORE_EVENT_LOCK_NUM;
2179 //Save "wl_text_input::keysym" keysym to list if list is not empty,
2180 //if not, send keysym to ecore loop as key event.
2181 //This code let key event which will be filtered by IME one by one.
2182 if (eina_list_count(imcontext->keysym_list)) {
2183 e->data = (void *)(unsigned long int)(state ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP);
2184 imcontext->keysym_list = eina_list_prepend(imcontext->keysym_list, e);
2188 ecore_event_add(ECORE_EVENT_KEY_DOWN, e, _ecore_keyevent_free, NULL);
2190 ecore_event_add(ECORE_EVENT_KEY_UP, e, _ecore_keyevent_free, NULL);
2195 text_input_enter(void *data,
2196 struct wl_text_input *text_input EINA_UNUSED,
2197 struct wl_surface *surface EINA_UNUSED)
2199 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2201 update_state(imcontext);
2203 imcontext->reset_serial = imcontext->serial;
2207 text_input_leave(void *data,
2208 struct wl_text_input *text_input EINA_UNUSED)
2210 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2213 commit_preedit(imcontext);
2214 clear_preedit(imcontext);
2218 text_input_input_panel_state(void *data EINA_UNUSED,
2219 struct wl_text_input *text_input EINA_UNUSED,
2220 uint32_t state EINA_UNUSED)
2222 // TIZEN_ONLY(20150708): Support input panel state callback
2223 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2224 LOGD("input panel state: %d", state);
2226 case WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE:
2227 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2228 if (imcontext->ctx == _show_req_ctx)
2229 _show_req_ctx = NULL;
2231 will_hide = EINA_FALSE;
2233 _received_will_hide_event = EINA_TRUE;
2234 LOGD("_received_will_hide_event = 1");
2235 send_will_hide_ack(imcontext->ctx);
2237 case WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW:
2238 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
2239 _received_will_hide_event = EINA_FALSE;
2241 _show_req_ctx = imcontext->ctx;
2242 LOGD("_received_will_hide_event = 0");
2245 _input_panel_state = (Ecore_IMF_Input_Panel_State)state;
2249 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx,
2250 ECORE_IMF_INPUT_PANEL_STATE_EVENT,
2251 _input_panel_state);
2253 if (state == WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE) {
2254 reset_keyboard_geometry();
2255 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2256 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2261 // TIZEN_ONLY(20151221): Support input panel geometry
2263 text_input_input_panel_geometry(void *data EINA_UNUSED,
2264 struct wl_text_input *text_input EINA_UNUSED,
2270 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2272 if (_keyboard_geometry.x != (int)x || _keyboard_geometry.y != (int)y ||
2273 _keyboard_geometry.w != (int)w || _keyboard_geometry.h != (int)h)
2275 _keyboard_geometry.x = x;
2276 _keyboard_geometry.y = y;
2277 _keyboard_geometry.w = w;
2278 _keyboard_geometry.h = h;
2279 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2280 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2286 text_input_language(void *data,
2287 struct wl_text_input *text_input EINA_UNUSED,
2288 uint32_t serial EINA_UNUSED,
2289 const char *language)
2291 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2292 Eina_Bool changed = EINA_FALSE;
2294 if (!imcontext || !language) return;
2296 if (imcontext->language) {
2297 if (strcmp(imcontext->language, language) != 0) {
2298 changed = EINA_TRUE;
2299 free(imcontext->language);
2303 changed = EINA_TRUE;
2307 imcontext->language = strdup(language);
2310 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, 0);
2315 text_input_text_direction(void *data EINA_UNUSED,
2316 struct wl_text_input *text_input EINA_UNUSED,
2317 uint32_t serial EINA_UNUSED,
2318 uint32_t direction EINA_UNUSED)
2322 // TIZEN_ONLY(20150918): Support to set the selection region
2324 text_input_selection_region(void *data,
2325 struct wl_text_input *text_input EINA_UNUSED,
2326 uint32_t serial EINA_UNUSED,
2330 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2331 if (!imcontext || !imcontext->ctx) return;
2333 Ecore_IMF_Event_Selection ev;
2334 ev.ctx = imcontext->ctx;
2337 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_SELECTION_SET, &ev);
2341 text_input_private_command(void *data,
2342 struct wl_text_input *text_input EINA_UNUSED,
2343 uint32_t serial EINA_UNUSED,
2344 const char *command)
2346 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2347 if (!imcontext || !imcontext->ctx) return;
2349 const char *szConformantReset = "CONFORMANT_RESET";
2350 const char *szConformantRestore = "CONFORMANT_RESTORE";
2351 LOGD("Checking command : %s", command);
2353 if (strncmp(command, szConformantReset, strlen(szConformantReset)) == 0) {
2354 Ecore_Wl2_Window *window = imcontext->window;
2355 if (!window) return;
2357 if (!reset_conformant_area(imcontext->ctx) && !_conformant_reset_started) {
2358 LOGD("Could not reset conformant area, send will_hide_ack right away %d", _conformant_reset_started);
2359 _send_will_hide_ack(imcontext);
2360 } else if (_conformant_reset_done) {
2361 LOGD("Conformant reset has been already finished, send will_hide_ack right away");
2362 _send_will_hide_ack(imcontext);
2364 } else if (strncmp(command, szConformantRestore, strlen(szConformantRestore)) == 0) {
2365 Ecore_Wl2_Window *window = imcontext->window;
2366 if (!window) return;
2368 restore_conformant_area(imcontext->ctx);
2370 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)command);
2375 text_input_commit_content(void *data,
2376 struct wl_text_input *text_input EINA_UNUSED,
2377 uint32_t serial EINA_UNUSED,
2378 const char *content,
2379 const char *description,
2380 const char *mime_types)
2382 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2383 if (!imcontext || !imcontext->ctx) return;
2385 Ecore_IMF_Event_Commit_Content ev;
2386 ev.content_uri = content;
2387 ev.mime_types = mime_types;
2388 ev.description = description;
2390 SECURE_LOGD("commit content : %s, description : %s, mime types : %s", content, description, mime_types);
2392 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT_CONTENT, (void *)&ev);
2396 text_input_input_panel_data(void *data,
2397 struct wl_text_input *text_input EINA_UNUSED,
2398 uint32_t serial EINA_UNUSED,
2399 const char *input_panel_data,
2402 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2403 if (!imcontext || !imcontext->ctx) return;
2405 if (imcontext->input_panel_data)
2406 free (imcontext->input_panel_data);
2408 imcontext->input_panel_data = calloc (1, length);
2409 if (imcontext->input_panel_data)
2410 memcpy (imcontext->input_panel_data, input_panel_data, length);
2412 imcontext->input_panel_data_length = length;
2416 text_input_get_selection_text (void *data,
2417 struct wl_text_input *text_input EINA_UNUSED,
2420 char *selection = NULL;
2422 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2423 if (!imcontext || !imcontext->ctx) {
2424 LOGD ("No context!");
2429 ecore_imf_context_selection_get (imcontext->ctx, &selection);
2430 if (imcontext->text_input) {
2431 SECURE_LOGD ("selection :%s", selection ? selection : "");
2433 char *_selection = selection;
2434 size_t len = strlen (selection);
2436 ssize_t ret = write (fd, _selection, len);
2440 LOGW ("write pipe failed, errno: %d", errno);
2454 text_input_get_surrounding_text (void *data,
2455 struct wl_text_input *text_input EINA_UNUSED,
2456 uint32_t maxlen_before,
2457 uint32_t maxlen_after,
2461 char *surrounding = NULL;
2462 LOGD("fd: %d maxlen_before: %d maxlen_after: %d", fd, maxlen_before, maxlen_after);
2463 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2464 if (!imcontext || !imcontext->ctx) {
2465 LOGD ("No context!");
2470 /* cursor_pos is a byte index */
2471 if (ecore_imf_context_surrounding_get (imcontext->ctx, &surrounding, &cursor_pos)) {
2472 SECURE_LOGD ("surrounding : '%s', cursor: %d", surrounding ? surrounding : "", cursor_pos);
2473 if (imcontext->text_input) {
2474 Eina_Unicode *wide_surrounding = eina_unicode_utf8_to_unicode (surrounding, NULL);
2475 size_t wlen = eina_unicode_strlen (wide_surrounding);
2477 if (cursor_pos > (int)wlen || cursor_pos < 0)
2480 if (maxlen_before > cursor_pos)
2483 maxlen_before = cursor_pos - maxlen_before;
2485 if (maxlen_after > wlen - cursor_pos)
2486 maxlen_after = (uint32_t)wlen;
2488 maxlen_after = cursor_pos + maxlen_after;
2490 char *req_surrounding = eina_unicode_unicode_to_utf8_range (wide_surrounding + maxlen_before, maxlen_after - maxlen_before, NULL);
2492 ssize_t ret = write(fd, &cursor_pos, sizeof(cursor_pos));
2494 LOGW ("write pipe failed, errno: %d", errno);
2495 } else if (req_surrounding) {
2496 char *_surrounding = req_surrounding;
2497 size_t len = strlen(req_surrounding);
2499 ssize_t ret = write(fd, _surrounding, len);
2503 LOGW ("write pipe failed, errno: %d", errno);
2506 _surrounding += ret;
2511 if (req_surrounding)
2512 free (req_surrounding);
2514 if (wide_surrounding)
2515 free (wide_surrounding);
2525 text_input_filter_key_event_done(void *data,
2526 struct wl_text_input *text_input EINA_UNUSED,
2530 LOGD("serial: %d, state: %d", serial, state);
2531 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2532 if (!imcontext) return;
2534 imcontext->last_key_event_filter.serial = serial;
2535 imcontext->last_key_event_filter.state = state;
2539 text_input_hide_permission(void *data,
2540 struct wl_text_input *text_input EINA_UNUSED,
2541 uint32_t permission)
2543 LOGD("permission : %d", permission);
2544 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2545 if (!imcontext || !imcontext->ctx || ignore_hide)
2549 ecore_imf_context_input_panel_hide(imcontext->ctx);
2553 text_input_recapture_string(void *data,
2554 struct wl_text_input *text_input EINA_UNUSED,
2558 const char *preedit,
2559 const char *preedit_commit,
2562 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2563 Eina_Bool old_preedit = EINA_FALSE;
2564 Eina_Bool preedit_changed = EINA_FALSE;
2566 SECURE_LOGD("ctx : %p, index : %d, length : %d, preedit event (preedit: '%s', current pre-edit: '%s')",
2571 imcontext->preedit_text ? imcontext->preedit_text : "");
2573 if (!check_serial(imcontext, serial))
2577 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
2579 if (imcontext->preedit_text)
2580 preedit_changed = (strcmp(imcontext->preedit_text, preedit) != 0);
2582 preedit_changed = (strlen(preedit) != 0);
2584 // send transaction start
2585 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_START");
2586 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_START, NULL);
2588 commit_preedit(imcontext);
2589 clear_preedit(imcontext);
2591 // delete surrounding text
2592 delete_surrounding_text(imcontext, index, length);
2594 // update preedit string
2595 imcontext->preedit_text = strdup(preedit);
2596 imcontext->preedit_commit = (strlen(preedit) > 0 ? strdup(preedit_commit) : NULL);
2597 imcontext->preedit_cursor =
2598 utf8_offset_to_characters(preedit, imcontext->pending_preedit.cursor);
2599 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
2601 imcontext->pending_preedit.attrs = NULL;
2603 if (preedit_changed) {
2605 ecore_imf_context_event_callback_call(imcontext->ctx,
2606 ECORE_IMF_CALLBACK_PREEDIT_START,
2610 ecore_imf_context_event_callback_call(imcontext->ctx,
2611 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
2614 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
2615 ecore_imf_context_event_callback_call(imcontext->ctx,
2616 ECORE_IMF_CALLBACK_PREEDIT_END,
2622 if (commit && strlen(commit) != 0) {
2623 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)commit);
2626 // send transaction end
2627 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_END");
2628 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_END, NULL);
2632 text_input_input_panel_event(void *data,
2633 struct wl_text_input *text_input EINA_UNUSED,
2634 uint32_t serial EINA_UNUSED,
2635 uint32_t event_type,
2638 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2639 if (!imcontext || !imcontext->ctx) return;
2641 LOGD("event type : %d, value : %d", event_type, value);
2643 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, event_type, value);
2647 static const struct wl_text_input_listener text_input_listener =
2651 text_input_modifiers_map,
2652 text_input_input_panel_state,
2653 text_input_preedit_string,
2654 text_input_preedit_styling,
2655 text_input_preedit_cursor,
2656 text_input_commit_string,
2657 text_input_cursor_position,
2658 text_input_delete_surrounding_text,
2660 text_input_language,
2661 text_input_text_direction,
2662 // TIZEN_ONLY(20150918): Support to set the selection region
2663 text_input_selection_region,
2664 text_input_private_command,
2665 text_input_input_panel_geometry,
2666 text_input_input_panel_data,
2667 text_input_get_selection_text,
2668 text_input_get_surrounding_text,
2669 text_input_filter_key_event_done,
2670 text_input_hide_permission,
2671 text_input_recapture_string,
2672 text_input_input_panel_event,
2673 text_input_commit_content
2679 keyboard_mode_changed_cb (keynode_t *key, void* data)
2681 hw_keyboard_mode = vconf_keynode_get_bool (key);
2682 Ecore_IMF_Context *active_ctx = get_using_ctx ();
2684 LOGD ("ctx : %p, input detect : %d", active_ctx, hw_keyboard_mode);
2686 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;
2687 ecore_imf_context_input_panel_event_callback_call (active_ctx, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, input_mode);
2689 if (input_mode == ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE && _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW)
2690 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2692 if ((input_mode == ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE) && _focused_ctx && (active_ctx == _focused_ctx)) {
2693 if (ecore_imf_context_input_panel_enabled_get (active_ctx)) {
2694 ecore_imf_context_input_panel_show (active_ctx);
2701 #ifdef SOCKET_ACTIVATION
2702 static int activate_socket () {
2704 struct sockaddr_un svr;
2710 LOGD("socket_activate start");
2711 s = socket(AF_UNIX, SOCK_STREAM, 0);
2713 LOGW("socket error");
2717 flag = fcntl(s, F_GETFL, NULL);
2719 fcntl(s, F_SETFL, flag);
2721 svr.sun_family = AF_UNIX;
2722 strcpy(svr.sun_path, SOCK_PATH);
2725 r = connect(s, (struct sockaddr *)&svr, len);
2727 LOGD("connect error");
2735 gettimeofday(&s1, NULL);
2736 LOGD("%d %06d\n", (int)s1.tv_sec, (int)s1.tv_usec);
2738 r = send(s, (const void *)&s1, sizeof(s1), 0);
2751 void wayland_im_initialize ()
2753 register_key_handler ();
2755 /* get input language vconf value */
2756 char *input_lang_str = vconf_get_str (VCONFKEY_ISF_INPUT_LANGUAGE);
2757 if (input_lang_str) {
2758 set_input_language (input_lang_str);
2759 free (input_lang_str);
2763 /* get autoperiod allow vconf value */
2765 if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
2766 if (val == EINA_TRUE)
2767 autoperiod_allow = EINA_TRUE;
2770 /* get autocapital allow vconf value */
2771 if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
2772 if (val == EINA_TRUE)
2773 autocap_allow = EINA_TRUE;
2776 /* get hardware keyboard input detected vconf value */
2777 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
2778 if (val == EINA_TRUE)
2779 hw_keyboard_mode = EINA_TRUE;
2782 vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL);
2783 vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL);
2784 vconf_notify_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb, NULL);
2785 vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
2788 _ime_device = ecore_device_add();
2790 ecore_device_name_set (_ime_device, IME_DEVICE_NAME);
2791 ecore_device_description_set (_ime_device, IME_DEVICE_NAME);
2792 ecore_device_identifier_set (_ime_device, IME_DEVICE_NAME);
2793 ecore_device_class_set (_ime_device, ECORE_DEVICE_CLASS_KEYBOARD);
2794 ecore_device_subclass_set (_ime_device, ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD);
2798 void wayland_im_uninitialize ()
2800 _ecore_imf_wayland_imcontext_pair_destroy ();
2802 unregister_key_handler ();
2804 _win_focus_out_handler_del ();
2805 _conformant_change_handler_del ();
2808 vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
2809 vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
2810 vconf_ignore_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb);
2811 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
2815 ecore_device_del (_ime_device);
2819 ecore_event_type_flush(ECORE_EVENT_DEVICE_ADD, ECORE_EVENT_DEVICE_DEL);
2823 wayland_im_context_add(Ecore_IMF_Context *ctx)
2825 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2828 LOGD("ctx : %p", ctx);
2830 if (!imcontext) return;
2832 imcontext->ctx = ctx;
2833 imcontext->input_panel_layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2834 imcontext->keysym_list = NULL;
2836 imcontext->shift_mask = MOD_SHIFT_MASK;
2837 imcontext->control_mask = MOD_CONTROL_MASK;
2838 imcontext->alt_mask = MOD_ALT_MASK;
2839 imcontext->caps_mask = MOD_CAPS_MASK;
2840 imcontext->num_mask = MOD_NUM_MASK;
2842 imcontext->input_panel_position.x = -1;
2843 imcontext->input_panel_position.y = -1;
2845 LOGD("text_input_manager : %p", imcontext->text_input_manager);
2846 imcontext->text_input =
2847 wl_text_input_manager_create_text_input(imcontext->text_input_manager);
2849 if (imcontext->text_input)
2850 wl_text_input_add_listener(imcontext->text_input,
2851 &text_input_listener, imcontext);
2854 LOGD("app id : %s\n", appid);
2856 ecore_imf_context_prediction_hint_hash_set(ctx, "appid", appid ? appid : "");
2863 wayland_im_context_del (Ecore_IMF_Context *ctx)
2865 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2867 Eina_Bool valid = EINA_FALSE;
2868 Ecore_Imf_Wayland_Imcontext_Pair *pair = _ecore_imf_wayland_imcontext_pair_find(ctx);
2869 if (pair && pair->imcontext == imcontext) {
2870 _ecore_imf_wayland_imcontext_pair_del(ctx);
2874 LOGE("The Ecore_Imf %p and WaylandIMContext %p pair not found!! pair : %p, pair->imcontext %p",
2875 ctx, imcontext, pair, pair ? pair->imcontext : NULL);
2876 _ecore_imf_wayland_imcontext_pair_log();
2879 Ecore_Event_Key *ev;
2880 LOGD ("ctx : %p, ctx valid : %d, focused_ctx : %p, show_req_ctx : %p", ctx, valid, _focused_ctx, _show_req_ctx);
2882 if (!imcontext) return;
2884 // TIZEN_ONLY(20150708): Support back key
2885 if (_input_panel_ctx == ctx) {
2886 _clear_hide_timer();
2887 _input_panel_hide(ctx, EINA_TRUE);
2888 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2889 _input_panel_ctx = NULL;
2892 if (_focused_ctx == ctx)
2893 _focused_ctx = NULL;
2895 if (_show_req_ctx == ctx)
2896 _show_req_ctx = NULL;
2898 if (_focus_req_ctx == ctx) {
2899 if (imcontext->canvas)
2900 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
2902 _focus_req_ctx = NULL;
2903 _focus_req_only = EINA_TRUE;
2907 if (imcontext->language) {
2908 free (imcontext->language);
2909 imcontext->language = NULL;
2912 // TIZEN_ONLY(20150922): Support to set input panel data
2913 if (imcontext->imdata) {
2914 free (imcontext->imdata);
2915 imcontext->imdata = NULL;
2916 imcontext->imdata_size = 0;
2919 if (imcontext->input_panel_data) {
2920 free (imcontext->input_panel_data);
2921 imcontext->input_panel_data = NULL;
2922 imcontext->input_panel_data_length = 0;
2926 if (imcontext->prediction_hint) {
2927 free (imcontext->prediction_hint);
2928 imcontext->prediction_hint = NULL;
2931 if (imcontext->mime_type) {
2932 free (imcontext->mime_type);
2933 imcontext->mime_type = NULL;
2936 if (imcontext->text_input)
2937 wl_text_input_destroy (imcontext->text_input);
2939 clear_preedit (imcontext);
2941 EINA_LIST_FREE(imcontext->keysym_list, ev) {
2950 wayland_im_context_reset(Ecore_IMF_Context *ctx)
2952 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2954 LOGD("ctx : %p", ctx);
2956 if (!imcontext) return;
2958 commit_preedit (imcontext);
2960 if (!imcontext->input) return;
2962 if (imcontext->text_input) {
2963 wl_text_input_reset(imcontext->text_input);
2965 update_state(imcontext);
2967 imcontext->reset_serial = imcontext->serial;
2971 _prediction_hint_data_foreach_cb(const Eina_Hash *hash, const void *key,
2972 void *data, void *fdata)
2974 const char *key_str = key;
2975 const char *value = data;
2976 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)fdata;
2977 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2979 SECURE_LOGD("key : %s, value : %s\n", key_str, value);
2981 if (imcontext && imcontext->text_input)
2982 wl_text_input_prediction_hint_data(imcontext->text_input, key_str, value);
2988 wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
2990 LOGD ("ctx : %p. enable : %d, on demand : %d", ctx,
2991 ecore_imf_context_input_panel_enabled_get(ctx),
2992 ecore_imf_context_input_panel_show_on_demand_get (ctx));
2994 #ifdef SOCKET_ACTIVATION
2998 if (!set_focus(ctx)) {
2999 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3000 if (imcontext && !imcontext->input) {
3001 if (_focus_req_ctx != ctx)
3002 _focus_req_only = EINA_TRUE;
3003 _focus_req_ctx = ctx;
3004 if (imcontext->canvas) {
3005 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
3006 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
3009 LOGW("ctx : %p. Fail to set focus!", ctx);
3013 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3014 if (imcontext && imcontext->input && imcontext->text_input) {
3015 wl_text_input_set_return_key_disabled(imcontext->text_input,
3016 imcontext->return_key_disabled);
3018 if (imcontext->prediction_hint)
3019 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
3021 if (imcontext->mime_type)
3022 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
3024 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
3025 wl_text_input_set_input_panel_position(imcontext->text_input,
3026 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
3028 const Eina_Hash *hash = ecore_imf_context_prediction_hint_hash_get(ctx);
3030 eina_hash_foreach(hash, _prediction_hint_data_foreach_cb, ctx);
3032 wl_text_input_set_content_type(imcontext->text_input, imcontext->content_hint, get_purpose(ctx));
3036 hw_keyboard_mode = EINA_FALSE;
3038 if (ecore_imf_context_input_panel_enabled_get(ctx))
3039 if (!ecore_imf_context_input_panel_show_on_demand_get (ctx))
3040 show_input_panel(ctx);
3042 LOGD ("ctx : %p input panel on demand mode : TRUE", ctx);
3044 LOGD ("ctx : %p input panel enable : FALSE", ctx);
3048 wayland_im_context_focus_out(Ecore_IMF_Context *ctx)
3050 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3052 LOGD("ctx : %p", ctx);
3054 if (_focus_req_ctx == ctx) {
3055 _focus_req_ctx = NULL;
3056 _focus_req_only = EINA_TRUE;
3059 if (!imcontext || !imcontext->input) return;
3062 if (hw_keyboard_mode == EINA_TRUE) {
3063 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3064 hw_keyboard_mode = EINA_FALSE;
3068 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3069 ecore_imf_context_input_panel_hide(ctx);
3076 wayland_im_context_preedit_string_get(Ecore_IMF_Context *ctx,
3080 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3081 if (!imcontext) return;
3083 SECURE_LOGD("pre-edit string requested (preedit: '%s', preedit cursor : %d)",
3084 imcontext->preedit_text ? imcontext->preedit_text : "", imcontext->preedit_cursor);
3087 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3090 *cursor_pos = imcontext->preedit_cursor;
3094 wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
3099 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3100 if (!imcontext) return;
3102 SECURE_LOGD("pre-edit string with attributes requested (preedit: '%s', preedit cursor : %d)",
3103 imcontext->preedit_text ? imcontext->preedit_text : "", imcontext->preedit_cursor);
3106 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3110 Ecore_IMF_Preedit_Attr *a, *attr;
3112 if (imcontext->preedit_attrs) {
3113 EINA_LIST_FOREACH(imcontext->preedit_attrs, l, a) {
3114 attr = malloc(sizeof(*attr));
3116 attr = memcpy(attr, a, sizeof(*attr));
3117 *attrs = eina_list_append(*attrs, attr);
3122 if (imcontext->preedit_text) {
3123 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
3125 // use REVERSE style as default
3126 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
3127 attr->start_index = 0;
3128 attr->end_index = strlen(imcontext->preedit_text);
3129 *attrs = eina_list_append(*attrs, attr);
3136 *cursor_pos = imcontext->preedit_cursor;
3140 wayland_im_context_cursor_position_set (Ecore_IMF_Context *ctx,
3143 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3144 if (!imcontext) return;
3146 if (imcontext->cursor_position != cursor_pos) {
3147 imcontext->cursor_position = cursor_pos;
3149 if (imcontext->input && imcontext->text_input) {
3150 LOGD ("ctx : %p, cursor pos : %d", ctx, cursor_pos);
3152 set_autocapital (ctx);
3154 if (!imcontext->preedit_text || strlen(imcontext->preedit_text) == 0)
3155 wl_text_input_set_cursor_position (imcontext->text_input, cursor_pos);
3161 wayland_im_context_use_preedit_set(Ecore_IMF_Context *ctx EINA_UNUSED,
3162 Eina_Bool use_preedit EINA_UNUSED)
3167 wayland_im_context_client_window_set(Ecore_IMF_Context *ctx,
3170 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3172 LOGD("client window set (window: %p)", window);
3174 if (imcontext && window) {
3175 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3178 imcontext->window = ecore_wl2_display_window_find(wl2_display, (Ecore_Window)window);
3180 if (_ime_device && imcontext->window)
3181 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3186 wayland_im_context_client_canvas_set(Ecore_IMF_Context *ctx,
3189 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3191 LOGD("client canvas set (canvas: %p)", canvas);
3193 if (imcontext && canvas) {
3194 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3195 imcontext->canvas = canvas;
3197 if (wl2_display && !imcontext->window)
3198 imcontext->window = ecore_wl2_display_window_find(wl2_display, ecore_evas_window_get(ecore_evas_ecore_evas_get(canvas)));
3200 if (_ime_device && imcontext->window)
3201 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3206 wayland_im_context_show(Ecore_IMF_Context *ctx)
3208 LOGD("ctx : %p", ctx);
3210 show_input_panel(ctx);
3214 wayland_im_context_hide(Ecore_IMF_Context *ctx)
3216 LOGD("ctx : %p", ctx);
3218 if (!get_using_ctx()) {
3219 LOGW("Can't hide input_panel because there is no using context!!");
3223 _input_panel_hide(ctx, EINA_FALSE);
3226 #if !(ENABLE_GRAB_KEYBOARD)
3228 _ecore_imf_lock_to_ecore_key_modifier(unsigned int locks)
3230 unsigned int mask = 0;
3232 if (locks & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
3233 mask |= ECORE_EVENT_LOCK_SCROLL;
3235 if (locks & ECORE_IMF_KEYBOARD_LOCK_CAPS)
3236 mask |= ECORE_EVENT_LOCK_CAPS;
3238 if (locks & ECORE_IMF_KEYBOARD_LOCK_NUM)
3239 mask |= ECORE_EVENT_LOCK_NUM;
3245 _ecore_imf_modifier_to_ecore_key_modifier(Ecore_IMF_Keyboard_Modifiers modifiers)
3247 unsigned int mask = 0;
3249 /**< "Control" is pressed */
3250 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
3251 mask |= ECORE_EVENT_MODIFIER_CTRL;
3253 /**< "Alt" is pressed */
3254 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
3255 mask |= ECORE_EVENT_MODIFIER_ALT;
3257 /**< "Shift" is pressed */
3258 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
3259 mask |= ECORE_EVENT_MODIFIER_SHIFT;
3261 /**< "Win" (between "Ctrl" and "Alt") is pressed */
3262 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
3263 mask |= ECORE_EVENT_MODIFIER_WIN;
3265 /**< "AltGr" is pressed */
3266 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
3267 mask |= ECORE_EVENT_MODIFIER_ALTGR;
3274 wayland_im_context_filter_event(Ecore_IMF_Context *ctx,
3275 Ecore_IMF_Event_Type type,
3276 Ecore_IMF_Event *imf_event)
3279 #if !(ENABLE_GRAB_KEYBOARD)
3280 Eina_Bool ret = EINA_FALSE;
3281 Ecore_Event_Key ecore_key_ev;
3282 char *key_dev_name = NULL;
3283 uint32_t key_dev_class = 0;
3284 uint32_t key_dev_subclass = 0;
3286 if (type == ECORE_IMF_EVENT_MOUSE_UP) {
3287 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3288 LOGD ("[Mouse-up event] ctx : %p", ctx);
3289 if (ctx == _focused_ctx) {
3290 ecore_imf_context_input_panel_show(ctx);
3293 LOGE ("Can't show IME because there is no focus. ctx : %p", ctx);
3296 #if !(ENABLE_GRAB_KEYBOARD)
3297 else if (type == ECORE_IMF_EVENT_KEY_UP) {
3298 Ecore_IMF_Event_Key_Up *key_ev = (Ecore_IMF_Event_Key_Up *)imf_event;
3299 ecore_key_ev.keyname = key_ev->keyname;
3300 ecore_key_ev.key = key_ev->key;
3301 ecore_key_ev.string = key_ev->string;
3302 ecore_key_ev.compose = key_ev->compose;
3303 ecore_key_ev.timestamp = key_ev->timestamp;
3304 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3305 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3306 key_dev_name = (char *)key_ev->dev_name;
3307 key_dev_class = key_ev->dev_class;
3308 key_dev_subclass = key_ev->dev_subclass;
3309 ecore_key_ev.keycode = key_ev->keycode;
3311 else if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3312 Ecore_IMF_Event_Key_Down *key_ev = (Ecore_IMF_Event_Key_Down *)imf_event;
3313 ecore_key_ev.keyname = key_ev->keyname;
3314 ecore_key_ev.key = key_ev->key;
3315 ecore_key_ev.string = key_ev->string;
3316 ecore_key_ev.compose = key_ev->compose;
3317 ecore_key_ev.timestamp = key_ev->timestamp;
3318 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3319 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3320 key_dev_name = (char *)key_ev->dev_name;
3321 key_dev_class = key_ev->dev_class;
3322 key_dev_subclass = key_ev->dev_subclass;
3323 ecore_key_ev.keycode = key_ev->keycode;
3326 if (type == ECORE_IMF_EVENT_KEY_UP || type == ECORE_IMF_EVENT_KEY_DOWN) {
3327 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3328 if (!imcontext || !imcontext->input || !imcontext->text_input)
3331 if (!_focused_ctx) {
3336 if (_focused_ctx != ctx) {
3337 LOGW ("focused context is different from the context used in ecore_imf_context_filter_event.");
3338 LOGW ("focus context : %p, context : %p", _focused_ctx, ctx);
3343 if (!ecore_key_ev.timestamp && (ecore_key_ev.modifiers & MOD_Mod5_MASK)
3344 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD) {
3345 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3346 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3347 strcmp (ecore_key_ev.key, "KP_Space") == 0 ) {
3348 autoperiod_insert (ctx);
3352 LOGD("Return! This is SW keyboard fake event!");
3356 int serial = imcontext->serial++;
3357 double start_time = ecore_time_get();
3360 uint32_t modifiers = 0;
3361 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_SHIFT)
3362 modifiers |= imcontext->shift_mask;
3363 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_CTRL)
3364 modifiers |= imcontext->control_mask;
3365 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_ALT)
3366 modifiers |= imcontext->alt_mask;
3367 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_CAPS)
3368 modifiers |= imcontext->caps_mask;
3369 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_NUM)
3370 modifiers |= imcontext->num_mask;
3372 SECURE_LOGD ("ev:modifiers=0x%x, modifiers=0x%x, shift_mask=0x%x, control_mask=0x%0x, alt_mask=0x%x, caps_mask=0x%x, num_mask=0x%x, keycode=%u", ecore_key_ev.modifiers, modifiers, imcontext->shift_mask, imcontext->control_mask, imcontext->alt_mask, imcontext->caps_mask, imcontext->num_mask, ecore_key_ev.keycode);
3373 //Send key event to IME.
3374 wl_text_input_filter_key_event(imcontext->text_input, serial, ecore_key_ev.timestamp, ecore_key_ev.key,
3375 type == ECORE_IMF_EVENT_KEY_UP? WL_KEYBOARD_KEY_STATE_RELEASED : WL_KEYBOARD_KEY_STATE_PRESSED,
3376 modifiers, (key_dev_name ? key_dev_name : ""), key_dev_class, key_dev_subclass, ecore_key_ev.keycode);
3377 //Waiting for filter_key_event_done from IME.
3378 //This function should return IME filtering result with boolean type.
3379 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3380 struct wl_display *display = NULL;
3382 display = ecore_wl2_display_get(wl2_display);
3385 struct wl_event_queue *queue = wl_display_create_queue(display);
3388 while (ecore_time_get() - start_time < WAIT_FOR_FILTER_DONE_SECOND && _focused_ctx == ctx && wl_display_roundtrip_queue(display, queue) != -1) {
3389 wl_display_dispatch_pending(display);
3390 if (imcontext->last_key_event_filter.serial == serial) {
3391 ret = imcontext->last_key_event_filter.state;
3393 } else if (imcontext->last_key_event_filter.serial > serial)
3397 if (imcontext->last_key_event_filter.serial < serial) {
3398 LOGW("Timeout occured");
3402 wl_event_queue_destroy(queue);
3405 LOGD ("elapsed : %.3f ms, serial (last, require) : (%d, %d)", (ecore_time_get() - start_time)*1000, imcontext->last_key_event_filter.serial, serial);
3409 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3410 if (ret == EINA_FALSE) {
3412 if (strcmp (ecore_key_ev.keyname, "Return") == 0 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_REMOCON) {
3414 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
3416 LOGD ("Changed keyboard mode from H/W to S/W ");
3417 hw_keyboard_mode = EINA_FALSE;
3418 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3419 if (ecore_imf_context_input_panel_enabled_get (ctx)) {
3420 ecore_imf_context_input_panel_show (ctx);
3427 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3428 strcmp (ecore_key_ev.key, "KP_Space") == 0) {
3429 autoperiod_insert (ctx);
3434 //Deal with the next key event in list.
3435 Ecore_Event_Key *ev = NULL;
3436 if (eina_list_count (imcontext->keysym_list)) {
3437 Eina_List *n = eina_list_last(imcontext->keysym_list);
3438 ev = (Ecore_Event_Key *)eina_list_data_get(n);
3439 int event_type = (unsigned long int)ev->data;
3442 ecore_event_add(event_type, ev, _ecore_keyevent_free, NULL);
3443 imcontext->keysym_list = eina_list_remove_list(imcontext->keysym_list, n);
3454 wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int width, int height)
3456 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3457 if (!imcontext) return;
3459 if ((imcontext->cursor_location.x != x) ||
3460 (imcontext->cursor_location.y != y) ||
3461 (imcontext->cursor_location.width != width) ||
3462 (imcontext->cursor_location.height != height)) {
3463 imcontext->cursor_location.x = x;
3464 imcontext->cursor_location.y = y;
3465 imcontext->cursor_location.width = width;
3466 imcontext->cursor_location.height = height;
3468 if (_focused_ctx == ctx)
3469 send_cursor_location (imcontext);
3473 void wayland_im_context_autocapital_type_set(Ecore_IMF_Context *ctx,
3474 Ecore_IMF_Autocapital_Type autocapital_type)
3476 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3477 if (!imcontext) return;
3479 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
3480 // TIZEN_ONLY(20160201): Add autocapitalization word
3481 WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION |
3483 WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
3484 WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE);
3486 if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE)
3487 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION;
3488 // TIZEN_ONLY(20160201): Add autocapitalization word
3489 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD)
3490 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
3492 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER)
3493 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE;
3495 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE;
3497 if (imcontext->input && imcontext->text_input) {
3498 LOGD ("ctx : %p. set autocapital type : %d", ctx, autocapital_type);
3499 wl_text_input_set_content_type(imcontext->text_input,
3500 imcontext->content_hint,
3506 wayland_im_context_input_panel_layout_set(Ecore_IMF_Context *ctx,
3507 Ecore_IMF_Input_Panel_Layout layout)
3509 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3510 if (!imcontext) return;
3512 imcontext->input_panel_layout = layout;
3515 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER:
3516 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
3518 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL:
3519 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL;
3521 case ECORE_IMF_INPUT_PANEL_LAYOUT_URL:
3522 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_URL;
3524 case ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER:
3525 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE;
3527 case ECORE_IMF_INPUT_PANEL_LAYOUT_IP:
3528 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3529 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_IP;
3532 case ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH:
3533 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATE;
3535 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY:
3536 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
3538 case ECORE_IMF_INPUT_PANEL_LAYOUT_HEX:
3539 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_HEX;
3541 case ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL:
3542 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL;
3544 case ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD:
3545 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
3546 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3548 case ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME:
3549 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME;
3551 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3552 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON:
3553 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON;
3556 case ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE:
3557 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE;
3560 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
3564 if (imcontext->input && imcontext->text_input) {
3565 LOGD ("ctx : %p, layout type : %d", ctx, layout);
3566 wl_text_input_set_content_type(imcontext->text_input,
3567 imcontext->content_hint,
3572 Ecore_IMF_Input_Panel_Layout
3573 wayland_im_context_input_panel_layout_get(Ecore_IMF_Context *ctx)
3575 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3576 if (!imcontext) return ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
3578 return imcontext->input_panel_layout;
3582 wayland_im_context_input_mode_set(Ecore_IMF_Context *ctx,
3583 Ecore_IMF_Input_Mode input_mode)
3585 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3586 if (!imcontext) return;
3588 if (input_mode & ECORE_IMF_INPUT_MODE_INVISIBLE)
3589 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3591 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3593 if (imcontext->input && imcontext->text_input) {
3594 LOGD ("ctx : %p, input mode : %d", ctx, input_mode);
3595 wl_text_input_set_content_type(imcontext->text_input,
3596 imcontext->content_hint,
3602 wayland_im_context_input_hint_set(Ecore_IMF_Context *ctx,
3603 Ecore_IMF_Input_Hints input_hints)
3605 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3606 if (!imcontext) return;
3608 if (input_hints & ECORE_IMF_INPUT_HINT_AUTO_COMPLETE)
3609 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3611 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3613 if (input_hints & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA)
3614 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3616 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3618 if (input_hints & ECORE_IMF_INPUT_HINT_MULTILINE)
3619 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3621 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3624 LOGD("autofill hint : %x\n", input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK);
3626 switch(input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK)
3628 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE:
3629 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE;
3631 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY:
3632 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY;
3634 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH:
3635 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH;
3637 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR:
3638 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR;
3640 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_NUMBER:
3641 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_NUMBER;
3643 case ECORE_IMF_INPUT_HINT_AUTOFILL_EMAIL_ADDRESS:
3644 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_EMAIL_ADDRESS;
3646 case ECORE_IMF_INPUT_HINT_AUTOFILL_PHONE:
3647 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_PHONE;
3649 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_ADDRESS:
3650 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_ADDRESS;
3652 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_CODE:
3653 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_CODE;
3655 case ECORE_IMF_INPUT_HINT_AUTOFILL_ID:
3656 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_ID;
3658 case ECORE_IMF_INPUT_HINT_AUTOFILL_NAME:
3659 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_NAME;
3663 if (imcontext->input && imcontext->text_input) {
3664 LOGD("ctx : %p, input hint : %#x", ctx, input_hints);
3665 wl_text_input_set_content_type(imcontext->text_input,
3666 imcontext->content_hint,
3672 wayland_im_context_input_panel_language_set(Ecore_IMF_Context *ctx,
3673 Ecore_IMF_Input_Panel_Lang lang)
3675 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3676 if (!imcontext) return;
3678 if (lang == ECORE_IMF_INPUT_PANEL_LANG_ALPHABET)
3679 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3681 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3683 if (imcontext->input && imcontext->text_input)
3684 wl_text_input_set_content_type(imcontext->text_input,
3685 imcontext->content_hint,
3689 // TIZEN_ONLY(20150708): Support input_panel_state_get
3690 Ecore_IMF_Input_Panel_State
3691 wayland_im_context_input_panel_state_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3693 return _input_panel_state;
3697 wayland_im_context_input_panel_return_key_type_set(Ecore_IMF_Context *ctx,
3698 Ecore_IMF_Input_Panel_Return_Key_Type return_key_type)
3700 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3701 if (!imcontext) return;
3703 imcontext->return_key_type = return_key_type;
3705 if (imcontext->input && imcontext->text_input)
3706 wl_text_input_set_return_key_type(imcontext->text_input,
3707 imcontext->return_key_type);
3711 wayland_im_context_input_panel_return_key_disabled_set(Ecore_IMF_Context *ctx,
3714 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3715 if (!imcontext) return;
3717 imcontext->return_key_disabled = disabled;
3719 if (imcontext->input && imcontext->text_input)
3720 wl_text_input_set_return_key_disabled(imcontext->text_input,
3721 imcontext->return_key_disabled);
3726 wayland_im_context_input_panel_language_locale_get(Ecore_IMF_Context *ctx,
3729 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3730 if (!imcontext) return;
3733 *locale = strdup(imcontext->language ? imcontext->language : "");
3737 wayland_im_context_prediction_allow_set(Ecore_IMF_Context *ctx,
3738 Eina_Bool prediction)
3740 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3741 if (!imcontext) return;
3744 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3746 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3748 if (imcontext->input && imcontext->text_input)
3749 wl_text_input_set_content_type(imcontext->text_input,
3750 imcontext->content_hint,
3754 // TIZEN_ONLY(20151221): Support input panel geometry
3756 wayland_im_context_input_panel_geometry_get(Ecore_IMF_Context *ctx EINA_UNUSED,
3757 int *x, int *y, int *w, int *h)
3760 *x = _keyboard_geometry.x;
3762 *y = _keyboard_geometry.y;
3764 *w = _keyboard_geometry.w;
3766 *h = _keyboard_geometry.h;
3770 wayland_im_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *data, int length)
3772 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3773 if (!imcontext) return;
3775 if (data && length > 0) {
3776 const char *custom_conformant_enabled = "conformant:custom,enabled";
3777 const char *custom_conformant_disabled = "conformant:custom,disabled";
3778 const char *custom_conformant_finished = "conformant:custom,finished";
3780 if (strncmp(data, custom_conformant_enabled, strlen(custom_conformant_enabled)) == 0) {
3781 _custom_conformant_event = EINA_TRUE;
3784 if (strncmp(data, custom_conformant_disabled, strlen(custom_conformant_disabled)) == 0) {
3785 _custom_conformant_event = EINA_FALSE;
3788 if (strncmp(data, custom_conformant_finished, strlen(custom_conformant_finished)) == 0) {
3789 if (_custom_conformant_event) {
3790 _conformant_reset_done = EINA_TRUE;
3791 LOGD("[conformant:custom,finished], _conformant_reset_done = 1");
3792 send_will_hide_ack(NULL);
3798 if (imcontext->imdata)
3799 free(imcontext->imdata);
3801 imcontext->imdata = calloc(1, length);
3802 if (imcontext->imdata && data)
3803 memcpy(imcontext->imdata, data, length);
3805 imcontext->imdata_size = length;
3807 if (imcontext->input && imcontext->text_input && (imcontext->imdata_size > 0))
3808 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
3812 wayland_im_context_input_panel_imdata_get(Ecore_IMF_Context *ctx, void *data, int *length)
3815 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3817 if (imcontext && imcontext->input_panel_data && (imcontext->input_panel_data_length > 0)) {
3819 memcpy(data, imcontext->input_panel_data, imcontext->input_panel_data_length);
3822 *length = imcontext->input_panel_data_length;
3830 // TIZEN_ONLY(20160218): Support BiDi direction
3832 wayland_im_context_bidi_direction_set(Ecore_IMF_Context *ctx, Ecore_IMF_BiDi_Direction bidi_direction)
3834 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3835 if (!imcontext) return;
3837 imcontext->bidi_direction = bidi_direction;
3839 if (imcontext->input && imcontext->text_input) {
3840 LOGD ("ctx : %p, bidi direction : %#x", ctx, bidi_direction);
3841 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
3846 Ecore_IMF_Input_Panel_Keyboard_Mode
3847 wayland_im_context_input_panel_keyboard_mode_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3849 return hw_keyboard_mode ? ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE : ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE;
3853 wayland_im_context_prediction_hint_set (Ecore_IMF_Context *ctx, const char *prediction_hint)
3855 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3856 if (!imcontext) return;
3858 imcontext->prediction_hint = strdup(prediction_hint ? prediction_hint : "");
3860 if (imcontext->input && imcontext->text_input) {
3861 SECURE_LOGD ("ctx : %p, prediction_hint : %s", ctx, imcontext->prediction_hint);
3862 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
3867 wayland_im_context_mime_type_accept_set (Ecore_IMF_Context *ctx, const char *mime_type)
3869 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3870 if (!imcontext) return;
3872 imcontext->mime_type = strdup(mime_type);
3874 if (imcontext->input && imcontext->text_input && (strlen(mime_type) > 0)) {
3875 LOGD ("ctx : %p, mime_type : %s", ctx, imcontext->mime_type);
3876 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
3881 wayland_im_context_input_panel_position_set (Ecore_IMF_Context *ctx, int x, int y)
3883 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3884 if (!imcontext) return;
3886 if ((imcontext->input_panel_position.x != x) || (imcontext->input_panel_position.y != y)) {
3887 imcontext->input_panel_position.x = x;
3888 imcontext->input_panel_position.y = y;
3891 if (imcontext->input && imcontext->text_input) {
3892 LOGD ("ctx : %p, x = %d, y = %d", ctx, x, y);
3893 wl_text_input_set_input_panel_position(imcontext->text_input,
3894 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
3898 WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager)
3900 WaylandIMContext *context = calloc(1, sizeof(WaylandIMContext));
3902 LOGD("new context created");
3903 context->text_input_manager = text_input_manager;
3909 void wayland_im_context_pair_set (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
3911 _ecore_imf_wayland_imcontext_pair_add (ctx, imcontext);