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 : %d", 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_delete_surrounding_event_add (ctx, ev.offset, ev.n_chars);
507 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
509 if (input_lang == INPUT_LANG_OTHER) {
510 fullstop_mark = strdup (".");
513 Eina_Unicode wbuf[2] = {0};
514 wbuf[0] = __language_infos[input_lang].punc_code;
516 fullstop_mark = eina_unicode_unicode_to_utf8 (wbuf, NULL);
519 ecore_imf_context_commit_event_add (ctx, fullstop_mark);
520 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)fullstop_mark);
523 free (fullstop_mark);
524 fullstop_mark = NULL;
530 if (plain_str) free (plain_str);
531 if (ustr) free (ustr);
532 space_key_time = ecore_time_get ();
536 check_except_autocapital (Eina_Unicode *ustr, int cursor_pos)
538 const char *except_str[] = {"e.g.", "E.g."};
539 unsigned int i = 0, j = 0, len = 0;
540 for (i = 0; i < (sizeof (except_str) / sizeof (except_str[0])); i++) {
541 len = strlen (except_str[i]);
542 if (cursor_pos < (int)len)
545 for (j = len; j > 0; j--) {
546 if (ustr[cursor_pos-j] != except_str[i][len-j])
550 if (j == 0) return EINA_TRUE;
557 analyze_surrounding_text (Ecore_IMF_Context *ctx)
559 char *plain_str = NULL;
560 Eina_Unicode puncs[] = {'\n','.', '!', '?', 0x00BF /* ¿ */, 0x00A1 /* ¡ */,
561 0x3002 /* 。 */, 0x06D4 /* Urdu */, 0x0964 /* Hindi */,
562 0x0589 /* Armenian */, 0x17D4 /* Khmer */, 0x104A /* Myanmar */};
563 Eina_Unicode *ustr = NULL;
564 Eina_Bool ret = EINA_FALSE;
565 Eina_Bool detect_space = EINA_FALSE;
568 const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
569 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
570 if (!imcontext) return EINA_FALSE;
572 switch (ecore_imf_context_autocapital_type_get (ctx)) {
573 case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
575 case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
581 if (imcontext->preedit_text && strcmp (imcontext->preedit_text, "") != 0)
584 if (imcontext->cursor_position == 0)
587 ecore_imf_context_surrounding_get (ctx, &plain_str, &cursor_pos);
589 if (!plain_str) goto done;
591 if (cursor_pos == 0) {
596 // Convert string from UTF-8 to unicode
597 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
598 if (!ustr) goto done;
600 if (eina_unicode_strlen (ustr) < (size_t)cursor_pos) goto done;
602 if (cursor_pos >= 1) {
603 if (ecore_imf_context_autocapital_type_get (ctx) == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
604 // Check space or no-break space
605 if (check_space_symbol (ustr[cursor_pos-1])) {
611 // Check paragraph separator <PS> or carriage return <br>
612 if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
617 for (i = cursor_pos; i > 0; i--) {
618 // Check space or no-break space
619 if (check_space_symbol (ustr[i-1])) {
620 detect_space = EINA_TRUE;
624 // Check punctuation and following the continuous space(s)
625 if (detect_space && check_symbol (ustr[i-1], puncs, punc_num)) {
626 if (check_except_autocapital (ustr, i))
638 if ((i == 0) && (detect_space == EINA_TRUE)) {
639 // continuous space(s) without any character
646 if (ustr) free (ustr);
647 if (plain_str) free (plain_str);
653 set_autocapital (Ecore_IMF_Context *ctx)
655 Eina_Bool uppercase = EINA_FALSE;
657 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
658 if (!imcontext || !imcontext->text_input || !imcontext->input) return;
660 if (hw_keyboard_mode) return;
662 if (ecore_imf_context_input_panel_layout_get (ctx) != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
665 // Check autocapital type
666 if (ecore_imf_context_input_panel_caps_lock_mode_get (ctx)) {
667 uppercase = EINA_TRUE;
669 if (autocap_allow == EINA_FALSE)
672 uppercase = analyze_surrounding_text (ctx);
675 LOGD ("ctx : %p, auto capital : %d", ctx, uppercase);
676 wl_text_input_set_capital_mode (imcontext->text_input, uppercase);
679 static Ecore_IMF_Context *
682 return (_show_req_ctx ? _show_req_ctx : _focused_ctx);
686 check_hide_key(const char *keyname)
688 if (!keyname) return EINA_FALSE;
690 if (strcmp(keyname, "Escape") == 0 ||
691 strcmp(keyname, BACK_KEY) == 0 ||
692 strcmp(keyname, OLD_BACK_KEY) == 0)
699 _ecore_key_modifiers_to_ecore_imf_locks(unsigned int modifiers)
701 unsigned int locks = 0;
703 if (modifiers & ECORE_EVENT_LOCK_SCROLL)
704 locks |= ECORE_IMF_KEYBOARD_LOCK_SCROLL;
706 if (modifiers & ECORE_EVENT_LOCK_CAPS)
707 locks |= ECORE_IMF_KEYBOARD_LOCK_CAPS;
709 if (modifiers & ECORE_EVENT_LOCK_NUM)
710 locks |= ECORE_IMF_KEYBOARD_LOCK_NUM;
716 _ecore_key_modifiers_to_ecore_imf_modifiers(unsigned int modifiers)
718 unsigned int mask = 0;
720 /**< "Control" is pressed */
721 if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
722 mask |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
724 /**< "Alt" is pressed */
725 if (modifiers & ECORE_EVENT_MODIFIER_ALT)
726 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
728 /**< "Shift" is pressed */
729 if (modifiers & ECORE_EVENT_MODIFIER_SHIFT)
730 mask |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT;
732 /**< "Win" (between "Ctrl" and "Alt") is pressed */
733 if (modifiers & ECORE_EVENT_MODIFIER_WIN)
734 mask |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
736 /**< "AltGr" is pressed */
737 if (modifiers & ECORE_EVENT_MODIFIER_ALTGR)
738 mask |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
744 _ecore_event_to_ecore_imf_key_down_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Down *imf_event)
746 if (!ecore_event || !imf_event)
749 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
750 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
751 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
752 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
753 imf_event->timestamp = ecore_event->timestamp;
755 if (ecore_event->dev) {
756 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
757 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
758 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
761 imf_event->dev_name = _ecore_imf_event_empty;
762 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
763 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
766 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
767 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
771 _ecore_event_to_ecore_imf_key_up_event(Ecore_Event_Key *ecore_event, Ecore_IMF_Event_Key_Up *imf_event)
773 if (!ecore_event || !imf_event)
776 imf_event->keyname = ecore_event->keyname ? ecore_event->keyname : _ecore_imf_event_empty;
777 imf_event->key = ecore_event->key ? ecore_event->key : _ecore_imf_event_empty;
778 imf_event->string = ecore_event->string ? ecore_event->string : _ecore_imf_event_empty;
779 imf_event->compose = ecore_event->compose ? ecore_event->compose : _ecore_imf_event_empty;
780 imf_event->timestamp = ecore_event->timestamp;
782 if (ecore_event->dev) {
783 imf_event->dev_name = ecore_device_name_get(ecore_event->dev) ? ecore_device_name_get(ecore_event->dev) : _ecore_imf_event_empty;
784 imf_event->dev_class = (Ecore_IMF_Device_Class)ecore_device_class_get(ecore_event->dev);
785 imf_event->dev_subclass = (Ecore_IMF_Device_Subclass)ecore_device_subclass_get(ecore_event->dev);
788 imf_event->dev_name = _ecore_imf_event_empty;
789 imf_event->dev_class = ECORE_IMF_DEVICE_CLASS_NONE;
790 imf_event->dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
793 imf_event->modifiers = _ecore_key_modifiers_to_ecore_imf_modifiers(ecore_event->modifiers);
794 imf_event->locks = _ecore_key_modifiers_to_ecore_imf_locks(ecore_event->modifiers);
798 key_down_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
800 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
801 if (!ev || !ev->keyname) return EINA_TRUE; /* the event is kept */
803 Ecore_IMF_Context *active_ctx = get_using_ctx ();
805 if (!active_ctx) return EINA_TRUE; /* the event is kept */
807 if ((_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW ||
808 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW) &&
809 check_hide_key(ev->keyname)) {
811 SECURE_LOGD ("%s key is pressed.", ev->keyname);
813 Ecore_IMF_Event_Key_Down imf_event;
814 Eina_Bool filter_ret = EINA_FALSE;
816 _ecore_event_to_ecore_imf_key_down_event(ev, &imf_event);
819 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_DOWN, (Ecore_IMF_Event *)&imf_event);
823 SECURE_LOGD ("%s key is pressed. ret : %d", ev->keyname, filter_ret);
824 return EINA_FALSE; /* the event is removed from the queue */
826 return EINA_TRUE; /* the event is kept */
830 key_up_filter_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
832 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
833 if (!ev || !ev->keyname) return EINA_TRUE; /* the event is kept */
835 Ecore_IMF_Context *active_ctx = get_using_ctx ();
837 if (!active_ctx) return EINA_TRUE; /* the event is kept */
839 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE ||
840 !check_hide_key(ev->keyname))
841 return EINA_TRUE; /* the event is kept */
843 SECURE_LOGD ("%s key is released.", ev->keyname);
845 Ecore_IMF_Event_Key_Up imf_event;
846 Eina_Bool filter_ret = EINA_FALSE;
848 _ecore_event_to_ecore_imf_key_up_event(ev, &imf_event);
851 filter_ret = ecore_imf_context_filter_event(_focused_ctx, ECORE_IMF_EVENT_KEY_UP, (Ecore_IMF_Event *)&imf_event);
855 SECURE_LOGD ("%s key is released. ret : %d", ev->keyname, filter_ret);
857 return EINA_FALSE; /* the event is removed from the queue */
860 ecore_imf_context_reset(active_ctx);
861 _input_panel_hide(active_ctx, EINA_TRUE);
862 return EINA_FALSE; /* the event is removed from the queue */
867 rotary_event_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
869 Ecore_Event_Detent_Rotate *ev = event;
870 if (!ev) return EINA_TRUE;
872 Ecore_IMF_Context *active_ctx = NULL;
874 active_ctx = _show_req_ctx;
875 else if (_focused_ctx)
876 active_ctx = _focused_ctx;
878 if (!active_ctx) return EINA_TRUE;
880 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
883 ecore_imf_context_reset(active_ctx);
884 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(active_ctx);
885 if (imcontext && imcontext->input && imcontext->text_input) {
886 isf_device_type_e device_type = find_device_type_from_ecore_event(ECORE_EVENT_DETENT_ROTATE);
890 if (device_buffer_encode((const char*)(event), sizeof(Ecore_Event_Detent_Rotate), &buffer, &buflen) &&
891 buffer && buflen > 0) {
892 wl_text_input_process_input_device_event(imcontext->text_input,
893 (unsigned int)device_type, buffer, buflen);
895 if (buffer) free(buffer);
902 _ecore_event_filter_cb(void *data, void *loop_data EINA_UNUSED, int type, void *event)
904 if (type == ECORE_EVENT_KEY_DOWN) {
905 return key_down_filter_cb(data, type, event);
907 else if (type == ECORE_EVENT_KEY_UP) {
908 return key_up_filter_cb(data, type, event);
910 /* The IME needs to process Rotary event prior to client application */
911 else if (type == ECORE_EVENT_DETENT_ROTATE) {
912 return rotary_event_cb(data, type, event);
919 register_key_handler()
921 if (!_ecore_event_filter_handler)
922 _ecore_event_filter_handler = ecore_event_filter_add(NULL, _ecore_event_filter_cb, NULL, NULL);
926 unregister_key_handler()
928 if (_ecore_event_filter_handler) {
929 ecore_event_filter_del(_ecore_event_filter_handler);
930 _ecore_event_filter_handler = NULL;
941 ecore_timer_del(_hide_timer);
949 static void _win_focus_out_handler_del ()
951 if (_win_focus_out_handler) {
952 ecore_event_handler_del (_win_focus_out_handler);
953 _win_focus_out_handler = NULL;
957 static void _conformant_change_handler_del()
959 if (_conformant_change_handler) {
960 ecore_event_handler_del(_conformant_change_handler);
961 _conformant_change_handler = NULL;
966 _send_input_panel_hide_request(Ecore_IMF_Context *ctx)
970 // TIZEN_ONLY(20150708): Support back key
971 _hide_req_ctx = NULL;
974 _win_focus_out_handler_del ();
976 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
977 if (imcontext && imcontext->text_input) {
978 wl_text_input_hide_input_panel(imcontext->text_input);
980 LOGD("creating temporary context for sending hide request");
981 const char *ctx_id = ecore_imf_context_default_id_get();
982 Ecore_IMF_Context *temp_context = ecore_imf_context_add(ctx_id);
984 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(temp_context);
985 if (imcontext && imcontext->text_input)
986 wl_text_input_hide_input_panel(imcontext->text_input);
988 ecore_imf_context_del(temp_context);
993 static void _conformant_area_free (void *data EINA_UNUSED, void *ev)
995 Ecore_Wl2_Event_Conformant_Change *e = ev;
1000 static void add_conformant_change_event(Ecore_Wl2_Window *window)
1002 Ecore_Wl2_Event_Conformant_Change *ev;
1003 ev = calloc(1, sizeof(Ecore_Wl2_Event_Conformant_Change));
1005 ev->win = ecore_wl2_window_id_get(window);
1008 ecore_event_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, ev, _conformant_area_free, NULL);
1012 static Eina_Rectangle _conformant_area_backup = { 0, 0, 0, 0 };
1013 static Eina_Bool reset_conformant_area(Ecore_IMF_Context *ctx)
1015 Eina_Bool reset = EINA_FALSE;
1016 Eina_Bool has_conformant = EINA_FALSE;
1017 Ecore_Wl2_Window *window = NULL;
1019 if (!ctx) return EINA_FALSE;
1021 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1023 window = imcontext->window;
1024 has_conformant = imcontext->has_conformant;
1028 int x = 0, y = 0, w = 0, h = 0;
1029 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1032 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w != 0 || h != 0)) {
1034 _conformant_area_backup.x = x;
1035 _conformant_area_backup.y = y;
1036 _conformant_area_backup.w = w;
1037 _conformant_area_backup.h = h;
1041 LOGD("reset %d", reset);
1043 ecore_wl2_window_keyboard_geometry_set(window, 0, 0, 0, 0);
1045 add_conformant_change_event(window);
1047 _conformant_reset_started = EINA_TRUE;
1053 static void restore_conformant_area(Ecore_IMF_Context *ctx)
1055 Eina_Bool restore = EINA_FALSE;
1056 Eina_Bool has_conformant = EINA_FALSE;
1057 Ecore_Wl2_Window *window = NULL;
1061 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1063 window = imcontext->window;
1064 has_conformant = imcontext->has_conformant;
1068 int x = 0, y = 0, w = 0, h = 0;
1069 Eina_Bool result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1072 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant && (w == 0 || h == 0)) {
1073 restore = EINA_TRUE;
1077 LOGD("restore %d", restore);
1079 ecore_wl2_window_keyboard_geometry_set(window,
1080 _conformant_area_backup.x, _conformant_area_backup.y,
1081 _conformant_area_backup.w, _conformant_area_backup.h);
1083 add_conformant_change_event(window);
1085 _conformant_reset_started = EINA_FALSE;
1090 _send_will_hide_ack(WaylandIMContext *imcontext)
1092 if (!imcontext) return;
1093 if (!(imcontext->text_input)) return;
1095 const char *szWillHideAck = "WILL_HIDE_ACK";
1096 wl_text_input_set_input_panel_data(imcontext->text_input, szWillHideAck, strlen(szWillHideAck));
1097 _received_will_hide_event = EINA_FALSE;
1101 _hide_timer_handler(void *data)
1103 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1104 _send_input_panel_hide_request(ctx);
1106 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1107 LOGD("No need to reset conformant, sending ACK right away");
1108 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1112 reset_keyboard_geometry();
1115 return ECORE_CALLBACK_CANCEL;
1119 _input_panel_hide_timer_start(void *data)
1122 _hide_timer = ecore_timer_add(HIDE_TIMER_INTERVAL, _hide_timer_handler, data);
1126 _input_panel_hide(Ecore_IMF_Context *ctx, Eina_Bool instant)
1128 LOGD ("ctx : %p", ctx);
1132 will_hide = EINA_TRUE;
1133 _conformant_reset_started = EINA_FALSE;
1135 if (instant || (_hide_timer && ecore_timer_pending_get(_hide_timer) <= 0.0)) {
1136 _clear_hide_timer();
1137 _send_input_panel_hide_request(ctx);
1139 if (!reset_conformant_area(ctx) && !_conformant_reset_started) {
1140 LOGD("No need to reset conformant, sending ACK right away");
1141 _send_will_hide_ack((WaylandIMContext *)ecore_imf_context_data_get(ctx));
1145 reset_keyboard_geometry();
1147 _input_panel_hide_timer_start(ctx);
1148 // TIZEN_ONLY(20150708): Support back key
1149 _hide_req_ctx = ctx;
1155 utf8_offset_to_characters(const char *str, int offset)
1160 for (; index < offset; i++) {
1161 if (eina_unicode_utf8_next_get(str, &index) == 0)
1169 send_cursor_location(WaylandIMContext *imcontext)
1171 #if ENABLE_SEND_CURSOR_LOCATION
1172 Ecore_Evas *ee = NULL;
1173 int canvas_x = 0, canvas_y = 0;
1175 if (imcontext->canvas) {
1176 ee = ecore_evas_ecore_evas_get(imcontext->canvas);
1178 ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
1181 if (imcontext->input && imcontext->text_input) {
1182 wl_text_input_set_cursor_rectangle(imcontext->text_input,
1183 imcontext->cursor_location.x + canvas_x,
1184 imcontext->cursor_location.y + canvas_y,
1185 imcontext->cursor_location.width,
1186 imcontext->cursor_location.height);
1192 update_state(WaylandIMContext *imcontext)
1194 if (!imcontext->ctx)
1197 send_cursor_location (imcontext);
1199 if (imcontext->input && imcontext->text_input) {
1200 wl_text_input_commit_state(imcontext->text_input, ++imcontext->serial);
1205 check_serial(WaylandIMContext *imcontext, uint32_t serial)
1210 Ecore_IMF_Preedit_Attr *attr;
1212 if ((imcontext->serial - serial) >
1213 (imcontext->serial - imcontext->reset_serial)) {
1214 LOGD("outdated serial: %u, current: %u, reset: %u",
1215 serial, imcontext->serial, imcontext->reset_serial);
1217 imcontext->pending_preedit.cursor = 0;
1219 if (imcontext->pending_preedit.attrs) {
1220 EINA_LIST_FREE(imcontext->pending_preedit.attrs, attr) free(attr);
1221 imcontext->pending_preedit.attrs = NULL;
1232 clear_preedit_text(WaylandIMContext *imcontext)
1234 Ecore_IMF_Preedit_Attr *attr = NULL;
1236 imcontext->preedit_cursor = 0;
1238 if (imcontext->preedit_text) {
1239 free(imcontext->preedit_text);
1240 imcontext->preedit_text = NULL;
1243 if (imcontext->preedit_attrs) {
1244 EINA_LIST_FREE(imcontext->preedit_attrs, attr)
1248 imcontext->preedit_attrs = NULL;
1252 clear_preedit(WaylandIMContext *imcontext)
1254 clear_preedit_text(imcontext);
1256 if (imcontext->preedit_commit) {
1257 free(imcontext->preedit_commit);
1258 imcontext->preedit_commit = NULL;
1263 text_input_commit_string(void *data,
1264 struct wl_text_input *text_input EINA_UNUSED,
1268 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1269 Eina_Bool old_preedit = EINA_FALSE;
1271 SECURE_LOGD("ctx : %p, commit event (text: '%s', current pre-edit: '%s')",
1274 imcontext->preedit_text ? imcontext->preedit_text : "");
1276 if (!imcontext->ctx)
1280 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1282 if (!check_serial(imcontext, serial))
1286 ecore_imf_context_preedit_end_event_add(imcontext->ctx);
1287 ecore_imf_context_event_callback_call(imcontext->ctx,
1288 ECORE_IMF_CALLBACK_PREEDIT_END,
1292 clear_preedit(imcontext);
1297 Eina_Unicode *ustr = eina_unicode_utf8_to_unicode (text, NULL);
1300 if (eina_unicode_strcmp (ustr, L" ") == 0 ||
1301 eina_unicode_strcmp (ustr, L" ") == 0)
1302 autoperiod_insert (imcontext->ctx);
1307 ecore_imf_context_commit_event_add(imcontext->ctx, text);
1308 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)text);
1312 commit_preedit(WaylandIMContext *imcontext)
1314 if (!imcontext->preedit_commit)
1317 if (!imcontext->ctx)
1320 imcontext->pending_preedit.cursor = 0;
1321 clear_preedit_text(imcontext);
1323 size_t commit_len = strlen(imcontext->preedit_commit);
1325 if (commit_len == 0) {
1326 ecore_imf_context_preedit_start_event_add(imcontext->ctx);
1327 ecore_imf_context_event_callback_call(imcontext->ctx,
1328 ECORE_IMF_CALLBACK_PREEDIT_START,
1331 ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
1332 ecore_imf_context_event_callback_call(imcontext->ctx,
1333 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1336 ecore_imf_context_preedit_end_event_add(imcontext->ctx);
1337 ecore_imf_context_event_callback_call(imcontext->ctx,
1338 ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
1341 if (commit_len > 0) {
1342 char *commit_str = NULL;
1343 commit_str = strdup(imcontext->preedit_commit);
1344 clear_preedit(imcontext);
1345 ecore_imf_context_commit_event_add(imcontext->ctx,
1347 ecore_imf_context_event_callback_call(imcontext->ctx,
1348 ECORE_IMF_CALLBACK_COMMIT,
1349 (void *)commit_str);
1355 set_focus(Ecore_IMF_Context *ctx)
1357 LOGD("ctx : %p", ctx);
1358 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1359 if (!imcontext) return EINA_FALSE;
1361 if (!imcontext->window) {
1362 LOGW("window is not given");
1366 Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
1368 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1372 struct wl_seat *seat = ecore_wl2_input_seat_get(input);
1374 LOGW("ctx : %p, Can't get Wl_seat", ctx);
1378 imcontext->input = input;
1381 wl_text_input_activate(imcontext->text_input, seat,
1382 ecore_wl2_window_surface_get(imcontext->window));
1384 if (g_key_rate_checked == EINA_FALSE && g_desired_key_rate == 0.0) {
1385 char *key_rate = getenv ("ISF_KEY_REPEAT_RATE");
1387 g_desired_key_rate = atof (key_rate);
1388 if (g_desired_key_rate > 0.0) {
1389 if (!ecore_wl2_input_keyboard_repeat_get (input, &g_original_key_rate, &g_original_key_delay)) {
1390 LOGE ("ecore_wl2_input_keyboard_repeat_get failed");
1393 LOGD ("ecore_wl2_input_keyboard_repeat_get original rate=%f, delay=%f. Desired rate=%f",
1394 g_original_key_rate, g_original_key_delay, g_desired_key_rate);
1398 g_key_rate_checked = EINA_TRUE;
1401 if (g_desired_key_rate > 0.0 && g_original_key_delay > 0.0 && !g_focused) {
1402 g_focused = EINA_TRUE;
1403 if (!ecore_wl2_input_keyboard_repeat_set (input, g_desired_key_rate, g_original_key_delay)) {
1404 LOGE ("ecore_wl2_input_keyboard_repeat_set failed");
1407 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_desired_key_rate, g_original_key_delay);
1415 set_focus_out(Ecore_IMF_Context *ctx)
1417 char *surrounding = NULL;
1420 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1421 if (!imcontext || !imcontext->input) return;
1423 if (ecore_imf_context_surrounding_get(ctx, &surrounding, &cursor_pos)) {
1425 wl_text_input_finalize_content(imcontext->text_input, surrounding, cursor_pos);
1431 if (imcontext->text_input)
1432 wl_text_input_deactivate(imcontext->text_input,
1433 ecore_wl2_input_seat_get(imcontext->input));
1435 if (ctx == _focused_ctx)
1436 _focused_ctx = NULL;
1438 imcontext->input = NULL;
1439 _preedit_cursor_changed = EINA_FALSE;
1441 if (g_desired_key_rate > 0.0 && g_focused) {
1442 g_focused = EINA_FALSE;
1444 Ecore_Wl2_Input *input = ecore_wl2_window_input_get(imcontext->window);
1446 if (!ecore_wl2_input_keyboard_repeat_set (input, g_original_key_rate, g_original_key_delay)) {
1447 LOGE ("ecore_wl2_input_keyboard_repeat_set failed.");
1450 LOGD ("ecore_wl2_input_keyboard_repeat_set(%f, %f)", g_original_key_rate, g_original_key_delay);
1454 LOGW("ctx : %p, Can't get Wl_Input", ctx);
1459 // TIZEN_ONLY(20160217): ignore the duplicate show request
1460 static Eina_Bool _compare_context(Ecore_IMF_Context *ctx1, Ecore_IMF_Context *ctx2)
1462 if (!ctx1 || !ctx2) return EINA_FALSE;
1464 if ((ecore_imf_context_autocapital_type_get(ctx1) == ecore_imf_context_autocapital_type_get(ctx2)) &&
1465 (ecore_imf_context_input_panel_layout_get(ctx1) == ecore_imf_context_input_panel_layout_get(ctx2)) &&
1466 (ecore_imf_context_input_panel_layout_variation_get(ctx1) == ecore_imf_context_input_panel_layout_variation_get(ctx2)) &&
1467 (ecore_imf_context_input_panel_language_get(ctx1) == ecore_imf_context_input_panel_language_get(ctx2)) &&
1468 (ecore_imf_context_input_panel_return_key_type_get(ctx1) == ecore_imf_context_input_panel_return_key_type_get(ctx2)) &&
1469 (ecore_imf_context_input_panel_return_key_disabled_get(ctx1) == ecore_imf_context_input_panel_return_key_disabled_get(ctx2)) &&
1470 (ecore_imf_context_input_panel_caps_lock_mode_get(ctx1) == ecore_imf_context_input_panel_caps_lock_mode_get(ctx2)))
1477 static void send_get_hide_permission(WaylandIMContext *imcontext)
1479 if (imcontext->text_input) {
1480 ignore_hide = EINA_FALSE;
1481 wl_text_input_get_hide_permission(imcontext->text_input);
1485 static Eina_Bool _client_window_focus_out_cb(void *data, int ev_type, void *ev)
1487 Ecore_Wl2_Event_Focus_Out *e = (Ecore_Wl2_Event_Focus_Out *)ev;
1488 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1489 if (!ctx || !e) return ECORE_CALLBACK_PASS_ON;
1491 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get (ctx);
1492 if (!imcontext || !imcontext->window) return ECORE_CALLBACK_PASS_ON;
1494 unsigned int client_win_id = ecore_wl2_window_id_get (imcontext->window);
1496 LOGD ("ctx : %p, client_window id : %#x, focus-out win : %#x", ctx, client_win_id, e->window);
1498 if (client_win_id > 0) {
1499 if (e->window == client_win_id) {
1500 LOGD ("window focus out");
1502 if (_focused_ctx == ctx) {
1503 wayland_im_context_focus_out (ctx);
1506 if (_show_req_ctx == ctx) {
1507 send_get_hide_permission(imcontext);
1512 send_get_hide_permission(imcontext);
1515 return ECORE_CALLBACK_PASS_ON;
1518 static void send_will_hide_ack(Ecore_IMF_Context *ctx)
1520 Eina_Bool need_temporary_context = EINA_FALSE;
1521 Eina_Bool has_conformant = EINA_FALSE;
1522 WaylandIMContext *imcontext = NULL;
1525 LOGD("ctx is NULL");
1526 need_temporary_context = EINA_TRUE;
1528 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1530 LOGD("imcontext is NULL :%p", ctx);
1531 need_temporary_context = EINA_TRUE;
1533 has_conformant = imcontext->has_conformant;
1537 /* When the RENDER_POST event is emitted, it is possible that our IMF_Context is already deleted,
1538 meaning that there is no connection available for communicating with the window manager.
1539 So we are creating a temporary context for sending WILL_HIDE_ACK message */
1540 if (need_temporary_context) {
1541 LOGD("creating temporary context for sending WILL_HIDE_ACK");
1542 const char *ctx_id = ecore_imf_context_default_id_get();
1543 ctx = ecore_imf_context_add(ctx_id);
1545 imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1549 if (ctx && imcontext) {
1550 if (ecore_imf_context_client_canvas_get(ctx) && has_conformant) {
1551 if (_conformant_reset_done && _received_will_hide_event) {
1552 LOGD("Send will hide ack, _conformant_reset_done = 1, received_will_hide_event = 1");
1553 _send_will_hide_ack(imcontext);
1554 _conformant_reset_done = EINA_FALSE;
1555 _received_will_hide_event = EINA_FALSE;
1557 LOGD ("_conformant_reset_done=%d, received_will_hide_event=%d",
1558 _conformant_reset_done, _received_will_hide_event);
1561 LOGD("Send will hide ack right away, since there is no conformant available : %p %d",
1562 ecore_imf_context_client_canvas_get(ctx), has_conformant);
1563 _send_will_hide_ack (imcontext);
1567 if (need_temporary_context) {
1569 ecore_imf_context_del(ctx);
1574 static void _render_post_cb(void *data, Evas *e, void *event_info)
1576 void *callback = evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1577 _conformant_reset_done = EINA_TRUE;
1578 _conformant_reset_started = EINA_FALSE;
1579 LOGD("[_render_post_cb], _conformant_reset_done = 1 , %p", callback);
1580 send_will_hide_ack(NULL);
1583 static Eina_Bool _conformant_change_cb(void *data, int ev_type, void *ev)
1585 Ecore_Wl2_Event_Conformant_Change *e = (Ecore_Wl2_Event_Conformant_Change *)ev;
1586 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
1587 if (!e || !ctx) return ECORE_CALLBACK_PASS_ON;
1589 LOGD ("CONFORMANT changed!! part type : %d, state : %d, win : %d", e->part_type, e->state, e->win);
1591 if (_active_context_window_id != e->win)
1592 return ECORE_CALLBACK_PASS_ON;
1594 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1595 if (!wl2_display) return ECORE_CALLBACK_PASS_ON;
1597 Ecore_Wl2_Window *window = ecore_wl2_display_window_find(wl2_display, e->win);
1598 if (!window) return ECORE_CALLBACK_PASS_ON;
1601 LOGD("_conformant_reset_done = 0, registering _render_post_cb : %p %p", _active_context_canvas, window);
1602 _conformant_reset_done = EINA_FALSE;
1603 if (_active_context_canvas && ecore_wl2_window_conformant_get(window) && !_custom_conformant_event) {
1604 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1605 evas_event_callback_add(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb, ctx);
1608 _conformant_reset_done = EINA_FALSE;
1609 if (_active_context_canvas) {
1610 evas_event_callback_del(_active_context_canvas, EVAS_CALLBACK_RENDER_POST, _render_post_cb);
1613 Eina_Bool result = EINA_FALSE;
1614 int x = 0, y = 0, w = 0, h = 0;
1617 /* TV IME consists of two or three windows, so ecore_wl2_window_keyboard_geometry_get() may return wrong size. */
1618 x = _keyboard_geometry.x, y = _keyboard_geometry.y, w = _keyboard_geometry.w, h = _keyboard_geometry.h;
1619 if (_keyboard_geometry.w == 0 || _keyboard_geometry.h == 0) {
1620 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1623 /* Since the input_panel_geometry is not delivered right at the moment, we use conformant geometry instead */
1624 x = 0, y = 0, w = 0, h = 0;
1625 result = ecore_wl2_window_keyboard_geometry_get(window, &x, &y, &w, &h);
1629 Evas_Coord scr_w = 0, scr_h = 0;
1631 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
1633 ecore_wl2_display_screen_size_get(wl2_display ,&scr_w, &scr_h);
1634 int rot = ecore_wl2_window_rotation_get(window);
1635 /* Assume we are using keyboard that has the same width to the screen width*/
1638 _keyboard_geometry.h = w;
1639 _keyboard_geometry.w = h;
1640 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1641 _keyboard_geometry.x = 0;
1644 _keyboard_geometry.w = w;
1645 _keyboard_geometry.h = h;
1646 _keyboard_geometry.x = 0;
1647 _keyboard_geometry.y = scr_h - _keyboard_geometry.h;
1650 _keyboard_geometry.h = w;
1651 _keyboard_geometry.w = h;
1652 _keyboard_geometry.y = scr_w - _keyboard_geometry.h;
1653 _keyboard_geometry.x = 0;
1656 _keyboard_geometry.x = x;
1657 _keyboard_geometry.y = y;
1658 _keyboard_geometry.w = w;
1659 _keyboard_geometry.h = h;
1661 LOGD("[KEYPAD]: scr %dx%d, rot %d, orig (%d,%d, %dx%d)", scr_w, scr_h, rot, x, y, w, h);
1662 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
1663 ecore_imf_context_input_panel_event_callback_call(ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
1667 return ECORE_CALLBACK_PASS_ON;
1671 get_purpose(Ecore_IMF_Context *ctx)
1673 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1674 uint32_t new_purpose = 0;
1676 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1680 switch (imcontext->content_purpose) {
1681 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
1682 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED)
1683 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED;
1684 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL)
1685 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL;
1686 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL)
1687 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL;
1689 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
1691 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
1692 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY)
1693 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS;
1695 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
1697 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
1698 if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME)
1699 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME;
1700 else if (layout_variation == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME)
1701 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NAME;
1703 new_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
1706 new_purpose = imcontext->content_purpose;
1713 static void _canvas_focus_in_cb(void *data, Evas *e, void *event_info)
1715 LOGD("ctx : %p %d", _focus_req_ctx, _focus_req_only);
1717 if (_focus_req_ctx) {
1718 set_focus(_focus_req_ctx);
1719 if (ecore_imf_context_input_panel_enabled_get (_focus_req_ctx) || !_focus_req_only)
1720 if (!ecore_imf_context_input_panel_show_on_demand_get (_focus_req_ctx) || !_focus_req_only)
1721 show_input_panel (_focus_req_ctx);
1723 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(_focus_req_ctx);
1724 if (imcontext && imcontext->canvas)
1725 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1726 _focus_req_ctx = NULL;
1727 _focus_req_only = EINA_TRUE;
1732 show_input_panel(Ecore_IMF_Context *ctx)
1734 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
1736 char *surrounding = NULL;
1739 if ((!imcontext) || (!imcontext->text_input))
1742 if (!imcontext->input) {
1744 if (!imcontext->input) {
1745 _focus_req_ctx = ctx;
1746 _focus_req_only = EINA_FALSE;
1747 if (imcontext->canvas) {
1748 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
1749 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
1754 _clear_hide_timer ();
1756 _win_focus_out_handler_del ();
1758 if (!imcontext->input)
1761 ignore_hide = EINA_TRUE;
1763 _win_focus_out_handler = ecore_event_handler_add (ECORE_WL2_EVENT_FOCUS_OUT, _client_window_focus_out_cb, ctx);
1764 _conformant_change_handler_del ();
1765 _conformant_change_handler = ecore_event_handler_add(ECORE_WL2_EVENT_CONFORMANT_CHANGE, _conformant_change_cb, ctx);
1767 // TIZEN_ONLY(20160217): ignore the duplicate show request
1768 if ((_show_req_ctx == ctx) && _compare_context(_show_req_ctx, ctx) && (!will_hide)) {
1769 if (_input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW ||
1770 _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
1771 LOGD("already show. ctx : %p", ctx);
1777 will_hide = EINA_FALSE;
1778 _show_req_ctx = ctx;
1779 _input_panel_ctx = ctx;
1780 _active_context_canvas = ecore_imf_context_client_canvas_get(ctx);
1784 // TIZEN_ONLY(20150715): Support input_panel_state_get
1785 int layout = ecore_imf_context_input_panel_layout_get (ctx);
1786 int layout_variation = ecore_imf_context_input_panel_layout_variation_get (ctx);
1789 if (layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
1790 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
1792 wl_text_input_set_content_type(imcontext->text_input,
1793 imcontext->content_hint,
1796 if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos)) {
1797 SECURE_LOGD ("surrounding text : %s", surrounding);
1801 imcontext->cursor_position = cursor_pos;
1802 wl_text_input_set_cursor_position(imcontext->text_input, cursor_pos);
1804 // TIZEN_ONLY(20150716): Support return key type
1805 wl_text_input_set_return_key_type(imcontext->text_input,
1806 imcontext->return_key_type);
1808 wl_text_input_set_return_key_disabled(imcontext->text_input,
1809 imcontext->return_key_disabled);
1811 if (imcontext->imdata_size > 0)
1812 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
1814 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
1816 set_autocapital (ctx);
1818 if (imcontext->mime_type)
1819 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
1821 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
1822 wl_text_input_set_input_panel_position(imcontext->text_input,
1823 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
1825 LOGD ("ctx : %p, layout : %d, layout variation : %d, language : %d, cursor position : %d",
1826 ctx, layout, layout_variation,
1827 ecore_imf_context_input_panel_language_get (ctx),
1829 LOGD ("input hint : %#x, bidi direction : %d, return key type : %d, return key disabled : %d, autocapital type : %d",
1830 ecore_imf_context_input_hint_get (ctx),
1831 imcontext->bidi_direction,
1832 ecore_imf_context_input_panel_return_key_type_get (ctx),
1833 ecore_imf_context_input_panel_return_key_disabled_get (ctx),
1834 ecore_imf_context_autocapital_type_get (ctx));
1835 LOGD ("client_window : %#lx, password mode : %d, prediction_allow : %d, mime_type : %s, input panel position x : %d, y : %d",
1836 (unsigned long int)ecore_imf_context_client_window_get (ctx),
1837 (imcontext->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) ? 1 : 0,
1838 ecore_imf_context_prediction_allow_get (ctx),
1839 imcontext->mime_type,
1840 imcontext->input_panel_position.x,
1841 imcontext->input_panel_position.y);
1843 if (_active_context_canvas && !evas_focus_state_get (_active_context_canvas)) {
1844 LOGW ("Canvas does not have focus!");
1848 if (hw_keyboard_mode) {
1849 LOGD("hw_keyboard_mode is TRUE, returning");
1853 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
1855 wl_text_input_show_input_panel(imcontext->text_input);
1857 if (imcontext->window) {
1858 _active_context_window_id = ecore_wl2_window_id_get(imcontext->window);
1859 imcontext->has_conformant = ecore_wl2_window_conformant_get(imcontext->window);
1861 imcontext->has_conformant = EINA_FALSE;
1867 static void delete_surrounding_text(WaylandIMContext *imcontext, int index, int length)
1869 Ecore_IMF_Event_Delete_Surrounding ev;
1870 LOGD("delete surrounding text (index: %d, length: %u)",
1874 ev.n_chars = length;
1876 ecore_imf_context_delete_surrounding_event_add(imcontext->ctx, ev.offset, ev.n_chars);
1877 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
1881 text_input_preedit_string(void *data,
1882 struct wl_text_input *text_input EINA_UNUSED,
1887 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1888 Eina_Bool old_preedit = EINA_FALSE;
1889 Eina_Bool preedit_changed = EINA_FALSE;
1891 SECURE_LOGD("ctx : %p, preedit event (text: '%s', current pre-edit: '%s')",
1894 imcontext->preedit_text ? imcontext->preedit_text : "");
1896 if (!check_serial(imcontext, serial))
1900 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
1902 if (imcontext->preedit_text)
1903 preedit_changed = (strcmp(imcontext->preedit_text, text) != 0);
1905 preedit_changed = (strlen(text) != 0);
1907 if (_preedit_cursor_changed) {
1908 preedit_changed = EINA_TRUE;
1909 _preedit_cursor_changed = EINA_FALSE;
1912 if (imcontext->pending_preedit.attrs)
1913 preedit_changed = EINA_TRUE;
1915 clear_preedit(imcontext);
1917 imcontext->preedit_text = strdup(text);
1918 imcontext->preedit_commit = (strlen(text) > 0 ? strdup(commit) : NULL);
1919 imcontext->preedit_cursor =
1920 utf8_offset_to_characters(text, imcontext->pending_preedit.cursor);
1921 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
1923 imcontext->pending_preedit.attrs = NULL;
1925 if (preedit_changed) {
1927 ecore_imf_context_preedit_start_event_add(imcontext->ctx);
1928 ecore_imf_context_event_callback_call(imcontext->ctx,
1929 ECORE_IMF_CALLBACK_PREEDIT_START,
1933 ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
1934 ecore_imf_context_event_callback_call(imcontext->ctx,
1935 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
1938 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
1939 ecore_imf_context_preedit_end_event_add(imcontext->ctx);
1940 ecore_imf_context_event_callback_call(imcontext->ctx,
1941 ECORE_IMF_CALLBACK_PREEDIT_END,
1948 text_input_delete_surrounding_text(void *data,
1949 struct wl_text_input *text_input EINA_UNUSED,
1953 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1954 delete_surrounding_text(imcontext, index, length);
1958 text_input_cursor_position(void *data EINA_UNUSED,
1959 struct wl_text_input *text_input EINA_UNUSED,
1963 LOGD("cursor_position for next commit (index: %d, anchor: %d)",
1968 text_input_preedit_styling(void *data,
1969 struct wl_text_input *text_input EINA_UNUSED,
1974 WaylandIMContext *imcontext = (WaylandIMContext *)data;
1975 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
1980 case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
1981 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1983 case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
1984 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1986 case WL_TEXT_INPUT_PREEDIT_STYLE_REVERSE:
1987 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1989 case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
1990 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
1992 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR1:
1993 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
1995 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR2:
1996 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
1998 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR3:
1999 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
2001 case WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR4:
2002 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
2005 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
2009 attr->start_index = index;
2010 attr->end_index = index + length;
2012 imcontext->pending_preedit.attrs =
2013 eina_list_append(imcontext->pending_preedit.attrs, attr);
2017 text_input_preedit_cursor(void *data,
2018 struct wl_text_input *text_input EINA_UNUSED,
2021 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2023 if (imcontext->pending_preedit.cursor != index) {
2024 imcontext->pending_preedit.cursor = index;
2025 _preedit_cursor_changed = EINA_TRUE;
2029 static xkb_mod_index_t
2030 modifiers_get_index(struct wl_array *modifiers_map, const char *name)
2032 xkb_mod_index_t index = 0;
2033 char *p = modifiers_map->data;
2035 while ((const char *)p < ((const char *)modifiers_map->data + modifiers_map->size))
2037 if (strcmp(p, name) == 0)
2044 return XKB_MOD_INVALID;
2047 static xkb_mod_mask_t
2048 modifiers_get_mask(struct wl_array *modifiers_map,
2051 xkb_mod_index_t index = modifiers_get_index(modifiers_map, name);
2053 if (index == XKB_MOD_INVALID)
2054 return XKB_MOD_INVALID;
2060 text_input_modifiers_map(void *data,
2061 struct wl_text_input *text_input EINA_UNUSED,
2062 struct wl_array *map)
2064 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2065 imcontext->shift_mask = modifiers_get_mask(map, XKB_MOD_NAME_SHIFT);
2066 imcontext->control_mask = modifiers_get_mask(map, XKB_MOD_NAME_CTRL);
2067 imcontext->alt_mask = modifiers_get_mask(map, XKB_MOD_NAME_ALT);
2068 imcontext->caps_mask = modifiers_get_mask(map, XKB_MOD_NAME_CAPS);
2069 imcontext->num_mask = modifiers_get_mask(map, XKB_MOD_NAME_NUM);
2073 _ecore_keyevent_free (void *data EINA_UNUSED, void *ev)
2075 Ecore_Event_Key *e = ev;
2076 if (e->dev) ecore_device_unref(e->dev);
2082 text_input_keysym(void *data,
2083 struct wl_text_input *text_input EINA_UNUSED,
2084 uint32_t serial EINA_UNUSED,
2090 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2091 char string[32], key[32], keyname[32];
2094 memset(key, 0, sizeof(key));
2095 xkb_keysym_get_name(sym, key, sizeof(key));
2097 memset(keyname, 0, sizeof(keyname));
2098 xkb_keysym_get_name(sym, keyname, sizeof(keyname));
2099 if (keyname[0] == '\0')
2100 snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
2102 memset(string, 0, sizeof(string));
2103 xkb_keysym_to_utf8(sym, string, 32);
2105 SECURE_LOGD("key event (key: %s)", keyname);
2107 e = calloc(1, sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) +
2108 strlen(string) + 3);
2111 e->keyname = (char *)(e + 1);
2112 e->key = e->keyname + strlen(keyname) + 1;
2113 e->string = e->key + strlen(key) + 1;
2114 e->compose = e->string;
2116 strncpy((char *)e->keyname, keyname, strlen(keyname));
2117 strncpy((char *)e->key, key, strlen(key));
2118 strncpy((char *)e->string, string, strlen(string));
2120 e->window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2121 e->event_window = (Ecore_Window)ecore_wl2_window_id_get(imcontext->window);
2122 e->dev = ecore_device_ref(_ime_device);
2123 e->timestamp = 0; /* For distinguishing S/W keyboard event */
2126 if (modifiers & imcontext->shift_mask)
2127 e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
2129 if (modifiers & imcontext->control_mask)
2130 e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
2132 if (modifiers & imcontext->alt_mask)
2133 e->modifiers |= ECORE_EVENT_MODIFIER_ALT;
2135 if (modifiers & MOD_Mod5_MASK)
2136 e->modifiers |= MOD_Mod5_MASK;
2138 if (modifiers & imcontext->caps_mask)
2139 e->modifiers |= ECORE_EVENT_LOCK_CAPS;
2141 if (modifiers & imcontext->num_mask)
2142 e->modifiers |= ECORE_EVENT_LOCK_NUM;
2144 //Save "wl_text_input::keysym" keysym to list if list is not empty,
2145 //if not, send keysym to ecore loop as key event.
2146 //This code let key event which will be filtered by IME one by one.
2147 if (eina_list_count(imcontext->keysym_list)) {
2148 e->data = (void *)(unsigned long int)(state ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP);
2149 imcontext->keysym_list = eina_list_prepend(imcontext->keysym_list, e);
2153 ecore_event_add(ECORE_EVENT_KEY_DOWN, e, _ecore_keyevent_free, NULL);
2155 ecore_event_add(ECORE_EVENT_KEY_UP, e, _ecore_keyevent_free, NULL);
2160 text_input_enter(void *data,
2161 struct wl_text_input *text_input EINA_UNUSED,
2162 struct wl_surface *surface EINA_UNUSED)
2164 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2166 update_state(imcontext);
2168 imcontext->reset_serial = imcontext->serial;
2172 text_input_leave(void *data,
2173 struct wl_text_input *text_input EINA_UNUSED)
2175 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2178 commit_preedit(imcontext);
2179 clear_preedit(imcontext);
2183 text_input_input_panel_state(void *data EINA_UNUSED,
2184 struct wl_text_input *text_input EINA_UNUSED,
2185 uint32_t state EINA_UNUSED)
2187 // TIZEN_ONLY(20150708): Support input panel state callback
2188 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2189 LOGD("input panel state: %d", state);
2191 case WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE:
2192 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2193 if (imcontext->ctx == _show_req_ctx)
2194 _show_req_ctx = NULL;
2196 will_hide = EINA_FALSE;
2198 _received_will_hide_event = EINA_TRUE;
2199 LOGD("_received_will_hide_event = 1");
2200 send_will_hide_ack(imcontext->ctx);
2202 case WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW:
2203 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
2204 _received_will_hide_event = EINA_FALSE;
2206 _show_req_ctx = imcontext->ctx;
2207 LOGD("_received_will_hide_event = 0");
2210 _input_panel_state = (Ecore_IMF_Input_Panel_State)state;
2214 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx,
2215 ECORE_IMF_INPUT_PANEL_STATE_EVENT,
2216 _input_panel_state);
2218 if (state == WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE) {
2219 reset_keyboard_geometry();
2220 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2221 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2226 // TIZEN_ONLY(20151221): Support input panel geometry
2228 text_input_input_panel_geometry(void *data EINA_UNUSED,
2229 struct wl_text_input *text_input EINA_UNUSED,
2235 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2237 if (_keyboard_geometry.x != (int)x || _keyboard_geometry.y != (int)y ||
2238 _keyboard_geometry.w != (int)w || _keyboard_geometry.h != (int)h)
2240 _keyboard_geometry.x = x;
2241 _keyboard_geometry.y = y;
2242 _keyboard_geometry.w = w;
2243 _keyboard_geometry.h = h;
2244 LOGD ("IME geometry x : %d, y : %d, w : %d, h : %d", _keyboard_geometry.x, _keyboard_geometry.y, _keyboard_geometry.w, _keyboard_geometry.h);
2245 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2251 text_input_language(void *data,
2252 struct wl_text_input *text_input EINA_UNUSED,
2253 uint32_t serial EINA_UNUSED,
2254 const char *language)
2256 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2257 Eina_Bool changed = EINA_FALSE;
2259 if (!imcontext || !language) return;
2261 if (imcontext->language) {
2262 if (strcmp(imcontext->language, language) != 0) {
2263 changed = EINA_TRUE;
2264 free(imcontext->language);
2268 changed = EINA_TRUE;
2272 imcontext->language = strdup(language);
2275 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, 0);
2280 text_input_text_direction(void *data EINA_UNUSED,
2281 struct wl_text_input *text_input EINA_UNUSED,
2282 uint32_t serial EINA_UNUSED,
2283 uint32_t direction EINA_UNUSED)
2287 // TIZEN_ONLY(20150918): Support to set the selection region
2289 text_input_selection_region(void *data,
2290 struct wl_text_input *text_input EINA_UNUSED,
2291 uint32_t serial EINA_UNUSED,
2295 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2296 if (!imcontext || !imcontext->ctx) return;
2298 Ecore_IMF_Event_Selection ev;
2299 ev.ctx = imcontext->ctx;
2302 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_SELECTION_SET, &ev);
2306 text_input_private_command(void *data,
2307 struct wl_text_input *text_input EINA_UNUSED,
2308 uint32_t serial EINA_UNUSED,
2309 const char *command)
2311 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2312 if (!imcontext || !imcontext->ctx) return;
2314 const char *szConformantReset = "CONFORMANT_RESET";
2315 const char *szConformantRestore = "CONFORMANT_RESTORE";
2316 LOGD("Checking command : %s", command);
2318 if (strncmp(command, szConformantReset, strlen(szConformantReset)) == 0) {
2319 Ecore_Wl2_Window *window = imcontext->window;
2320 if (!window) return;
2322 if (!reset_conformant_area(imcontext->ctx) && !_conformant_reset_started) {
2323 LOGD("Could not reset conformant area, send will_hide_ack right away %d", _conformant_reset_started);
2324 _send_will_hide_ack(imcontext);
2325 } else if (_conformant_reset_done) {
2326 LOGD("Conformant reset has been already finished, send will_hide_ack right away");
2327 _send_will_hide_ack(imcontext);
2329 } else if (strncmp(command, szConformantRestore, strlen(szConformantRestore)) == 0) {
2330 Ecore_Wl2_Window *window = imcontext->window;
2331 if (!window) return;
2333 restore_conformant_area(imcontext->ctx);
2335 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)command);
2340 text_input_commit_content(void *data,
2341 struct wl_text_input *text_input EINA_UNUSED,
2342 uint32_t serial EINA_UNUSED,
2343 const char *content,
2344 const char *description,
2345 const char *mime_types)
2347 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2348 if (!imcontext || !imcontext->ctx) return;
2350 Ecore_IMF_Event_Commit_Content ev;
2351 ev.content_uri = content;
2352 ev.mime_types = mime_types;
2353 ev.description = description;
2355 SECURE_LOGD("commit content : %s, description : %s, mime types : %s", content, description, mime_types);
2357 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT_CONTENT, (void *)&ev);
2361 text_input_input_panel_data(void *data,
2362 struct wl_text_input *text_input EINA_UNUSED,
2363 uint32_t serial EINA_UNUSED,
2364 const char *input_panel_data,
2367 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2368 if (!imcontext || !imcontext->ctx) return;
2370 if (imcontext->input_panel_data)
2371 free (imcontext->input_panel_data);
2373 imcontext->input_panel_data = calloc (1, length);
2374 if (imcontext->input_panel_data)
2375 memcpy (imcontext->input_panel_data, input_panel_data, length);
2377 imcontext->input_panel_data_length = length;
2381 text_input_get_selection_text (void *data,
2382 struct wl_text_input *text_input EINA_UNUSED,
2385 char *selection = NULL;
2387 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2388 if (!imcontext || !imcontext->ctx) {
2389 LOGD ("No context!");
2394 ecore_imf_context_selection_get (imcontext->ctx, &selection);
2395 if (imcontext->text_input) {
2396 SECURE_LOGD ("selection :%s", selection ? selection : "");
2398 char *_selection = selection;
2399 size_t len = strlen (selection);
2401 ssize_t ret = write (fd, _selection, len);
2405 LOGW ("write pipe failed, errno: %d", errno);
2419 text_input_get_surrounding_text (void *data,
2420 struct wl_text_input *text_input EINA_UNUSED,
2421 uint32_t maxlen_before,
2422 uint32_t maxlen_after,
2426 char *surrounding = NULL;
2427 LOGD("fd: %d maxlen_before: %d maxlen_after: %d", fd, maxlen_before, maxlen_after);
2428 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2429 if (!imcontext || !imcontext->ctx) {
2430 LOGD ("No context!");
2435 /* cursor_pos is a byte index */
2436 if (ecore_imf_context_surrounding_get (imcontext->ctx, &surrounding, &cursor_pos)) {
2437 SECURE_LOGD ("surrounding : '%s', cursor: %d", surrounding ? surrounding : "", cursor_pos);
2438 if (imcontext->text_input) {
2439 Eina_Unicode *wide_surrounding = eina_unicode_utf8_to_unicode (surrounding, NULL);
2440 size_t wlen = eina_unicode_strlen (wide_surrounding);
2442 if (cursor_pos > (int)wlen || cursor_pos < 0)
2445 if (maxlen_before > cursor_pos)
2448 maxlen_before = cursor_pos - maxlen_before;
2450 if (maxlen_after > wlen - cursor_pos)
2451 maxlen_after = (uint32_t)wlen;
2453 maxlen_after = cursor_pos + maxlen_after;
2455 char *req_surrounding = eina_unicode_unicode_to_utf8_range (wide_surrounding + maxlen_before, maxlen_after - maxlen_before, NULL);
2457 ssize_t ret = write(fd, &cursor_pos, sizeof(cursor_pos));
2459 LOGW ("write pipe failed, errno: %d", errno);
2460 } else if (req_surrounding) {
2461 char *_surrounding = req_surrounding;
2462 size_t len = strlen(req_surrounding);
2464 ssize_t ret = write(fd, _surrounding, len);
2468 LOGW ("write pipe failed, errno: %d", errno);
2471 _surrounding += ret;
2476 if (req_surrounding)
2477 free (req_surrounding);
2479 if (wide_surrounding)
2480 free (wide_surrounding);
2490 text_input_filter_key_event_done(void *data,
2491 struct wl_text_input *text_input EINA_UNUSED,
2495 LOGD("serial: %d, state: %d", serial, state);
2496 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2497 if (!imcontext) return;
2499 imcontext->last_key_event_filter.serial = serial;
2500 imcontext->last_key_event_filter.state = state;
2504 text_input_hide_permission(void *data,
2505 struct wl_text_input *text_input EINA_UNUSED,
2506 uint32_t permission)
2508 LOGD("permission : %d", permission);
2509 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2510 if (!imcontext || !imcontext->ctx || ignore_hide)
2514 ecore_imf_context_input_panel_hide(imcontext->ctx);
2518 text_input_recapture_string(void *data,
2519 struct wl_text_input *text_input EINA_UNUSED,
2523 const char *preedit,
2524 const char *preedit_commit,
2527 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2528 Eina_Bool old_preedit = EINA_FALSE;
2529 Eina_Bool preedit_changed = EINA_FALSE;
2531 SECURE_LOGD("ctx : %p, index : %d, length : %d, preedit event (preedit: '%s', current pre-edit: '%s')",
2536 imcontext->preedit_text ? imcontext->preedit_text : "");
2538 if (!check_serial(imcontext, serial))
2542 imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
2544 if (imcontext->preedit_text)
2545 preedit_changed = (strcmp(imcontext->preedit_text, preedit) != 0);
2547 preedit_changed = (strlen(preedit) != 0);
2549 // send transaction start
2550 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_START");
2551 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_START, NULL);
2553 commit_preedit(imcontext);
2554 clear_preedit(imcontext);
2556 // delete surrounding text
2557 delete_surrounding_text(imcontext, index, length);
2559 // update preedit string
2560 imcontext->preedit_text = strdup(preedit);
2561 imcontext->preedit_commit = (strlen(preedit) > 0 ? strdup(preedit_commit) : NULL);
2562 imcontext->preedit_cursor =
2563 utf8_offset_to_characters(preedit, imcontext->pending_preedit.cursor);
2564 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
2566 imcontext->pending_preedit.attrs = NULL;
2568 if (preedit_changed) {
2570 ecore_imf_context_preedit_start_event_add(imcontext->ctx);
2571 ecore_imf_context_event_callback_call(imcontext->ctx,
2572 ECORE_IMF_CALLBACK_PREEDIT_START,
2576 ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
2577 ecore_imf_context_event_callback_call(imcontext->ctx,
2578 ECORE_IMF_CALLBACK_PREEDIT_CHANGED,
2581 if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) {
2582 ecore_imf_context_preedit_end_event_add(imcontext->ctx);
2583 ecore_imf_context_event_callback_call(imcontext->ctx,
2584 ECORE_IMF_CALLBACK_PREEDIT_END,
2590 if (commit && strlen(commit) != 0) {
2591 ecore_imf_context_commit_event_add(imcontext->ctx, commit);
2592 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)commit);
2595 // send transaction end
2596 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, (void *)"TRANSACTION_END");
2597 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_TRANSACTION_END, NULL);
2601 text_input_input_panel_event(void *data,
2602 struct wl_text_input *text_input EINA_UNUSED,
2603 uint32_t serial EINA_UNUSED,
2604 uint32_t event_type,
2607 WaylandIMContext *imcontext = (WaylandIMContext *)data;
2608 if (!imcontext || !imcontext->ctx) return;
2610 LOGD("event type : %d, value : %d", event_type, value);
2612 ecore_imf_context_input_panel_event_callback_call(imcontext->ctx, event_type, value);
2616 static const struct wl_text_input_listener text_input_listener =
2620 text_input_modifiers_map,
2621 text_input_input_panel_state,
2622 text_input_preedit_string,
2623 text_input_preedit_styling,
2624 text_input_preedit_cursor,
2625 text_input_commit_string,
2626 text_input_cursor_position,
2627 text_input_delete_surrounding_text,
2629 text_input_language,
2630 text_input_text_direction,
2631 // TIZEN_ONLY(20150918): Support to set the selection region
2632 text_input_selection_region,
2633 text_input_private_command,
2634 text_input_input_panel_geometry,
2635 text_input_input_panel_data,
2636 text_input_get_selection_text,
2637 text_input_get_surrounding_text,
2638 text_input_filter_key_event_done,
2639 text_input_hide_permission,
2640 text_input_recapture_string,
2641 text_input_input_panel_event,
2642 text_input_commit_content
2648 keyboard_mode_changed_cb (keynode_t *key, void* data)
2650 hw_keyboard_mode = vconf_keynode_get_bool (key);
2651 Ecore_IMF_Context *active_ctx = get_using_ctx ();
2653 LOGD ("ctx : %p, input detect : %d", active_ctx, hw_keyboard_mode);
2655 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;
2656 ecore_imf_context_input_panel_event_callback_call (active_ctx, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, input_mode);
2658 if (input_mode == ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE && _input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW)
2659 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2661 if ((input_mode == ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE) && _focused_ctx && (active_ctx == _focused_ctx)) {
2662 if (ecore_imf_context_input_panel_enabled_get (active_ctx)) {
2663 ecore_imf_context_input_panel_show (active_ctx);
2670 #ifdef SOCKET_ACTIVATION
2671 static int activate_socket () {
2673 struct sockaddr_un svr;
2679 LOGD("socket_activate start");
2680 s = socket(AF_UNIX, SOCK_STREAM, 0);
2682 LOGW("socket error");
2686 flag = fcntl(s, F_GETFL, NULL);
2688 fcntl(s, F_SETFL, flag);
2690 svr.sun_family = AF_UNIX;
2691 strcpy(svr.sun_path, SOCK_PATH);
2694 r = connect(s, (struct sockaddr *)&svr, len);
2696 LOGD("connect error");
2704 gettimeofday(&s1, NULL);
2705 LOGD("%d %06d\n", (int)s1.tv_sec, (int)s1.tv_usec);
2707 r = send(s, (const void *)&s1, sizeof(s1), 0);
2720 void wayland_im_initialize ()
2722 register_key_handler ();
2724 /* get input language vconf value */
2725 char *input_lang_str = vconf_get_str (VCONFKEY_ISF_INPUT_LANGUAGE);
2726 if (input_lang_str) {
2727 set_input_language (input_lang_str);
2728 free (input_lang_str);
2732 /* get autoperiod allow vconf value */
2734 if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
2735 if (val == EINA_TRUE)
2736 autoperiod_allow = EINA_TRUE;
2739 /* get autocapital allow vconf value */
2740 if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
2741 if (val == EINA_TRUE)
2742 autocap_allow = EINA_TRUE;
2745 /* get hardware keyboard input detected vconf value */
2746 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
2747 if (val == EINA_TRUE)
2748 hw_keyboard_mode = EINA_TRUE;
2751 vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL);
2752 vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL);
2753 vconf_notify_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb, NULL);
2754 vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
2757 _ime_device = ecore_device_add();
2759 ecore_device_name_set (_ime_device, IME_DEVICE_NAME);
2760 ecore_device_description_set (_ime_device, IME_DEVICE_NAME);
2761 ecore_device_identifier_set (_ime_device, IME_DEVICE_NAME);
2762 ecore_device_class_set (_ime_device, ECORE_DEVICE_CLASS_KEYBOARD);
2763 ecore_device_subclass_set (_ime_device, ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD);
2767 void wayland_im_uninitialize ()
2769 _ecore_imf_wayland_imcontext_pair_destroy ();
2771 unregister_key_handler ();
2773 _win_focus_out_handler_del ();
2774 _conformant_change_handler_del ();
2777 vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
2778 vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
2779 vconf_ignore_key_changed (VCONFKEY_ISF_INPUT_LANGUAGE, input_language_changed_cb);
2780 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
2784 ecore_device_del (_ime_device);
2788 ecore_event_type_flush(ECORE_EVENT_DEVICE_ADD, ECORE_EVENT_DEVICE_DEL);
2792 wayland_im_context_add(Ecore_IMF_Context *ctx)
2794 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2797 LOGD("ctx : %p", ctx);
2799 if (!imcontext) return;
2801 imcontext->ctx = ctx;
2802 imcontext->input_panel_layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2803 imcontext->keysym_list = NULL;
2805 imcontext->shift_mask = MOD_SHIFT_MASK;
2806 imcontext->control_mask = MOD_CONTROL_MASK;
2807 imcontext->alt_mask = MOD_ALT_MASK;
2808 imcontext->caps_mask = MOD_CAPS_MASK;
2809 imcontext->num_mask = MOD_NUM_MASK;
2811 imcontext->input_panel_position.x = -1;
2812 imcontext->input_panel_position.y = -1;
2814 imcontext->text_input =
2815 wl_text_input_manager_create_text_input(imcontext->text_input_manager);
2817 if (imcontext->text_input)
2818 wl_text_input_add_listener(imcontext->text_input,
2819 &text_input_listener, imcontext);
2822 LOGD("app id : %s\n", appid);
2824 ecore_imf_context_prediction_hint_hash_set(ctx, "appid", appid ? appid : "");
2831 wayland_im_context_del (Ecore_IMF_Context *ctx)
2833 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2835 Eina_Bool valid = EINA_FALSE;
2836 Ecore_Imf_Wayland_Imcontext_Pair *pair = _ecore_imf_wayland_imcontext_pair_find(ctx);
2837 if (pair && pair->imcontext == imcontext) {
2838 _ecore_imf_wayland_imcontext_pair_del(ctx);
2842 LOGE("The Ecore_Imf %p and WaylandIMContext %p pair not found!! pair : %p, pair->imcontext %p",
2843 ctx, imcontext, pair, pair ? pair->imcontext : NULL);
2844 _ecore_imf_wayland_imcontext_pair_log();
2847 Ecore_Event_Key *ev;
2848 LOGD ("ctx : %p [%d], focused_ctx : %p, show_req_ctx : %p", ctx, valid, _focused_ctx, _show_req_ctx);
2850 if (!imcontext) return;
2852 // TIZEN_ONLY(20150708): Support back key
2853 if (_input_panel_ctx == ctx) {
2854 _clear_hide_timer();
2855 _input_panel_hide(ctx, EINA_TRUE);
2856 _input_panel_state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
2857 _input_panel_ctx = NULL;
2860 if (_focused_ctx == ctx)
2861 _focused_ctx = NULL;
2863 if (_show_req_ctx == ctx)
2864 _show_req_ctx = NULL;
2866 if (_focus_req_ctx == ctx) {
2867 if (imcontext->canvas)
2868 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
2870 _focus_req_ctx = NULL;
2871 _focus_req_only = EINA_TRUE;
2875 if (imcontext->language) {
2876 free (imcontext->language);
2877 imcontext->language = NULL;
2880 // TIZEN_ONLY(20150922): Support to set input panel data
2881 if (imcontext->imdata) {
2882 free (imcontext->imdata);
2883 imcontext->imdata = NULL;
2884 imcontext->imdata_size = 0;
2887 if (imcontext->input_panel_data) {
2888 free (imcontext->input_panel_data);
2889 imcontext->input_panel_data = NULL;
2890 imcontext->input_panel_data_length = 0;
2894 if (imcontext->prediction_hint) {
2895 free (imcontext->prediction_hint);
2896 imcontext->prediction_hint = NULL;
2899 if (imcontext->mime_type) {
2900 free (imcontext->mime_type);
2901 imcontext->mime_type = NULL;
2904 if (imcontext->text_input)
2905 wl_text_input_destroy (imcontext->text_input);
2907 clear_preedit (imcontext);
2909 EINA_LIST_FREE(imcontext->keysym_list, ev) {
2917 wayland_im_context_reset(Ecore_IMF_Context *ctx)
2919 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2921 LOGD("ctx : %p", ctx);
2923 if (!imcontext) return;
2925 commit_preedit (imcontext);
2927 if (!imcontext->input) return;
2929 if (imcontext->text_input) {
2930 wl_text_input_reset(imcontext->text_input);
2932 update_state(imcontext);
2934 imcontext->reset_serial = imcontext->serial;
2938 _prediction_hint_data_foreach_cb(const Eina_Hash *hash, const void *key,
2939 void *data, void *fdata)
2941 const char *key_str = key;
2942 const char *value = data;
2943 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)fdata;
2944 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2946 SECURE_LOGD("key : %s, value : %s\n", key_str, value);
2948 if (imcontext && imcontext->text_input)
2949 wl_text_input_prediction_hint_data(imcontext->text_input, key_str, value);
2955 wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
2957 LOGD ("ctx : %p. enable : %d, on demand : %d", ctx,
2958 ecore_imf_context_input_panel_enabled_get(ctx),
2959 ecore_imf_context_input_panel_show_on_demand_get (ctx));
2961 #ifdef SOCKET_ACTIVATION
2965 if (!set_focus(ctx)) {
2966 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2967 if (imcontext && !imcontext->input) {
2968 if (_focus_req_ctx != ctx)
2969 _focus_req_only = EINA_TRUE;
2970 _focus_req_ctx = ctx;
2971 if (imcontext->canvas) {
2972 evas_event_callback_del(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb);
2973 evas_event_callback_add(imcontext->canvas, EVAS_CALLBACK_CANVAS_FOCUS_IN, _canvas_focus_in_cb, NULL);
2976 LOGW("ctx : %p. Fail to set focus!", ctx);
2980 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
2981 if (imcontext && imcontext->input && imcontext->text_input) {
2982 wl_text_input_set_return_key_disabled(imcontext->text_input,
2983 imcontext->return_key_disabled);
2985 if (imcontext->prediction_hint)
2986 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
2988 if (imcontext->mime_type)
2989 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
2991 if (imcontext->input_panel_position.x >= 0 && imcontext->input_panel_position.y >= 0)
2992 wl_text_input_set_input_panel_position(imcontext->text_input,
2993 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
2995 const Eina_Hash *hash = ecore_imf_context_prediction_hint_hash_get(ctx);
2997 eina_hash_foreach(hash, _prediction_hint_data_foreach_cb, ctx);
2999 wl_text_input_set_content_type(imcontext->text_input, imcontext->content_hint, get_purpose(ctx));
3002 if (ecore_imf_context_input_panel_enabled_get(ctx))
3003 if (!ecore_imf_context_input_panel_show_on_demand_get (ctx))
3004 show_input_panel(ctx);
3006 LOGD ("ctx : %p input panel on demand mode : TRUE", ctx);
3008 LOGD ("ctx : %p input panel enable : FALSE", ctx);
3012 wayland_im_context_focus_out(Ecore_IMF_Context *ctx)
3014 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3016 LOGD("ctx : %p", ctx);
3018 if (_focus_req_ctx == ctx) {
3019 _focus_req_ctx = NULL;
3020 _focus_req_only = EINA_TRUE;
3023 if (!imcontext || !imcontext->input) return;
3026 if (hw_keyboard_mode == EINA_TRUE) {
3027 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3028 hw_keyboard_mode = EINA_FALSE;
3032 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3033 ecore_imf_context_input_panel_hide(ctx);
3040 wayland_im_context_preedit_string_get(Ecore_IMF_Context *ctx,
3044 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3045 if (!imcontext) return;
3047 SECURE_LOGD("pre-edit string requested (preedit: '%s')",
3048 imcontext->preedit_text ? imcontext->preedit_text : "");
3051 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3054 *cursor_pos = imcontext->preedit_cursor;
3058 wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
3063 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3064 if (!imcontext) return;
3066 SECURE_LOGD("pre-edit string with attributes requested (preedit: '%s')",
3067 imcontext->preedit_text ? imcontext->preedit_text : "");
3070 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
3074 Ecore_IMF_Preedit_Attr *a, *attr;
3076 if (imcontext->preedit_attrs) {
3077 EINA_LIST_FOREACH(imcontext->preedit_attrs, l, a) {
3078 attr = malloc(sizeof(*attr));
3080 attr = memcpy(attr, a, sizeof(*attr));
3081 *attrs = eina_list_append(*attrs, attr);
3086 if (imcontext->preedit_text) {
3087 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
3089 // use REVERSE style as default
3090 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
3091 attr->start_index = 0;
3092 attr->end_index = strlen(imcontext->preedit_text);
3093 *attrs = eina_list_append(*attrs, attr);
3100 *cursor_pos = imcontext->preedit_cursor;
3104 wayland_im_context_cursor_position_set (Ecore_IMF_Context *ctx,
3107 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3108 if (!imcontext) return;
3110 if (imcontext->cursor_position != cursor_pos) {
3111 imcontext->cursor_position = cursor_pos;
3113 if (imcontext->input && imcontext->text_input) {
3114 LOGD ("ctx : %p, cursor pos : %d", ctx, cursor_pos);
3116 set_autocapital (ctx);
3118 if (!imcontext->preedit_text || strlen(imcontext->preedit_text) == 0)
3119 wl_text_input_set_cursor_position (imcontext->text_input, cursor_pos);
3125 wayland_im_context_use_preedit_set(Ecore_IMF_Context *ctx EINA_UNUSED,
3126 Eina_Bool use_preedit EINA_UNUSED)
3131 wayland_im_context_client_window_set(Ecore_IMF_Context *ctx,
3134 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3136 LOGD("client window set (window: %p)", window);
3138 if (imcontext && window) {
3139 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3142 imcontext->window = ecore_wl2_display_window_find(wl2_display, (Ecore_Window)window);
3144 if (_ime_device && imcontext->window)
3145 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3150 wayland_im_context_client_canvas_set(Ecore_IMF_Context *ctx,
3153 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3155 LOGD("client canvas set (canvas: %p)", canvas);
3157 if (imcontext && canvas) {
3158 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3159 imcontext->canvas = canvas;
3161 if (wl2_display && !imcontext->window)
3162 imcontext->window = ecore_wl2_display_window_find(wl2_display, ecore_evas_window_get(ecore_evas_ecore_evas_get(canvas)));
3164 if (_ime_device && imcontext->window)
3165 _device_info_send (ecore_wl2_window_id_get (imcontext->window), EINA_TRUE);
3170 wayland_im_context_show(Ecore_IMF_Context *ctx)
3172 LOGD("ctx : %p", ctx);
3174 show_input_panel(ctx);
3178 wayland_im_context_hide(Ecore_IMF_Context *ctx)
3180 LOGD("ctx : %p", ctx);
3182 if (!get_using_ctx()) {
3183 LOGW("Can't hide input_panel because there is no using context!!");
3187 _input_panel_hide(ctx, EINA_FALSE);
3190 #if !(ENABLE_GRAB_KEYBOARD)
3192 _ecore_imf_lock_to_ecore_key_modifier(unsigned int locks)
3194 unsigned int mask = 0;
3196 if (locks & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
3197 mask |= ECORE_EVENT_LOCK_SCROLL;
3199 if (locks & ECORE_IMF_KEYBOARD_LOCK_CAPS)
3200 mask |= ECORE_EVENT_LOCK_CAPS;
3202 if (locks & ECORE_IMF_KEYBOARD_LOCK_NUM)
3203 mask |= ECORE_EVENT_LOCK_NUM;
3209 _ecore_imf_modifier_to_ecore_key_modifier(Ecore_IMF_Keyboard_Modifiers modifiers)
3211 unsigned int mask = 0;
3213 /**< "Control" is pressed */
3214 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
3215 mask |= ECORE_EVENT_MODIFIER_CTRL;
3217 /**< "Alt" is pressed */
3218 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
3219 mask |= ECORE_EVENT_MODIFIER_ALT;
3221 /**< "Shift" is pressed */
3222 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
3223 mask |= ECORE_EVENT_MODIFIER_SHIFT;
3225 /**< "Win" (between "Ctrl" and "Alt") is pressed */
3226 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
3227 mask |= ECORE_EVENT_MODIFIER_WIN;
3229 /**< "AltGr" is pressed */
3230 if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
3231 mask |= ECORE_EVENT_MODIFIER_ALTGR;
3238 wayland_im_context_filter_event(Ecore_IMF_Context *ctx,
3239 Ecore_IMF_Event_Type type,
3240 Ecore_IMF_Event *imf_event)
3243 #if !(ENABLE_GRAB_KEYBOARD)
3244 Eina_Bool ret = EINA_FALSE;
3245 Ecore_Event_Key ecore_key_ev;
3246 char *key_dev_name = NULL;
3247 uint32_t key_dev_class = 0;
3248 uint32_t key_dev_subclass = 0;
3250 if (type == ECORE_IMF_EVENT_MOUSE_UP) {
3251 if (ecore_imf_context_input_panel_enabled_get(ctx)) {
3252 LOGD ("[Mouse-up event] ctx : %p", ctx);
3253 if (ctx == _focused_ctx) {
3254 ecore_imf_context_input_panel_show(ctx);
3257 LOGE ("Can't show IME because there is no focus. ctx : %p", ctx);
3260 #if !(ENABLE_GRAB_KEYBOARD)
3261 else if (type == ECORE_IMF_EVENT_KEY_UP) {
3262 Ecore_IMF_Event_Key_Up *key_ev = (Ecore_IMF_Event_Key_Up *)imf_event;
3263 ecore_key_ev.keyname = key_ev->keyname;
3264 ecore_key_ev.key = key_ev->key;
3265 ecore_key_ev.string = key_ev->string;
3266 ecore_key_ev.compose = key_ev->compose;
3267 ecore_key_ev.timestamp = key_ev->timestamp;
3268 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3269 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3270 key_dev_name = (char *)key_ev->dev_name;
3271 key_dev_class = key_ev->dev_class;
3272 key_dev_subclass = key_ev->dev_subclass;
3274 else if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3275 Ecore_IMF_Event_Key_Down *key_ev = (Ecore_IMF_Event_Key_Down *)imf_event;
3276 ecore_key_ev.keyname = key_ev->keyname;
3277 ecore_key_ev.key = key_ev->key;
3278 ecore_key_ev.string = key_ev->string;
3279 ecore_key_ev.compose = key_ev->compose;
3280 ecore_key_ev.timestamp = key_ev->timestamp;
3281 ecore_key_ev.modifiers = _ecore_imf_modifier_to_ecore_key_modifier(key_ev->modifiers);
3282 ecore_key_ev.modifiers |= _ecore_imf_lock_to_ecore_key_modifier(key_ev->locks);
3283 key_dev_name = (char *)key_ev->dev_name;
3284 key_dev_class = key_ev->dev_class;
3285 key_dev_subclass = key_ev->dev_subclass;
3288 if (type == ECORE_IMF_EVENT_KEY_UP || type == ECORE_IMF_EVENT_KEY_DOWN) {
3289 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3290 if (!imcontext || !imcontext->input || !imcontext->text_input)
3293 if (!_focused_ctx) {
3298 if (_focused_ctx != ctx) {
3299 LOGW ("focused context is different from the context used in ecore_imf_context_filter_event.");
3300 LOGW ("focus context : %p, context : %p", _focused_ctx, ctx);
3305 if (!ecore_key_ev.timestamp && (ecore_key_ev.modifiers & MOD_Mod5_MASK)
3306 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD) {
3307 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3308 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3309 strcmp (ecore_key_ev.key, "KP_Space") == 0 ) {
3310 autoperiod_insert (ctx);
3314 LOGD("Return! This is SW keyboard fake event!");
3318 int serial = imcontext->serial++;
3319 double start_time = ecore_time_get();
3322 uint32_t modifiers = 0;
3323 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_SHIFT)
3324 modifiers |= imcontext->shift_mask;
3325 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_CTRL)
3326 modifiers |= imcontext->control_mask;
3327 if (ecore_key_ev.modifiers & ECORE_EVENT_MODIFIER_ALT)
3328 modifiers |= imcontext->alt_mask;
3329 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_CAPS)
3330 modifiers |= imcontext->caps_mask;
3331 if (ecore_key_ev.modifiers & ECORE_EVENT_LOCK_NUM)
3332 modifiers |= imcontext->num_mask;
3334 SECURE_LOGD ("ev:modifiers=0x%x, modifiers=0x%x, shift_mask=0x%x, control_mask=0x%0x, alt_mask=0x%x, caps_mask=0x%x, num_mask=0x%x", ecore_key_ev.modifiers, modifiers, imcontext->shift_mask, imcontext->control_mask, imcontext->alt_mask, imcontext->caps_mask, imcontext->num_mask);
3335 //Send key event to IME.
3336 wl_text_input_filter_key_event(imcontext->text_input, serial, ecore_key_ev.timestamp, ecore_key_ev.key,
3337 type == ECORE_IMF_EVENT_KEY_UP? WL_KEYBOARD_KEY_STATE_RELEASED : WL_KEYBOARD_KEY_STATE_PRESSED,
3338 modifiers, (key_dev_name ? key_dev_name : ""), key_dev_class, key_dev_subclass);
3339 //Waiting for filter_key_event_done from IME.
3340 //This function should return IME filtering result with boolean type.
3341 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3342 struct wl_display *display = NULL;
3344 display = ecore_wl2_display_get(wl2_display);
3345 struct wl_event_queue *queue = wl_display_create_queue(display);
3347 if (display && queue) {
3348 while (ecore_time_get() - start_time < WAIT_FOR_FILTER_DONE_SECOND && _focused_ctx == ctx && wl_display_roundtrip_queue(display, queue) != -1) {
3349 wl_display_dispatch_pending(display);
3350 if (imcontext->last_key_event_filter.serial == serial) {
3351 ret = imcontext->last_key_event_filter.state;
3353 } else if (imcontext->last_key_event_filter.serial > serial)
3359 wl_event_queue_destroy(queue);
3360 LOGD ("elapsed : %.3f ms, serial (last, require) : (%d, %d)", (ecore_time_get() - start_time)*1000, imcontext->last_key_event_filter.serial, serial);
3363 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
3364 if (ret == EINA_FALSE) {
3366 if (strcmp (ecore_key_ev.keyname, "Return") == 0 && key_dev_subclass == ECORE_DEVICE_SUBCLASS_REMOCON) {
3368 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0) {
3370 LOGD ("Changed keyboard mode from H/W to S/W ");
3371 hw_keyboard_mode = EINA_FALSE;
3372 vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
3373 if (ecore_imf_context_input_panel_enabled_get (ctx)) {
3374 ecore_imf_context_input_panel_show (ctx);
3381 if (strcmp (ecore_key_ev.key, "space") == 0 ||
3382 strcmp (ecore_key_ev.key, "KP_Space") == 0) {
3383 autoperiod_insert (ctx);
3388 //Deal with the next key event in list.
3389 Ecore_Event_Key *ev = NULL;
3390 if (eina_list_count (imcontext->keysym_list)) {
3391 Eina_List *n = eina_list_last(imcontext->keysym_list);
3392 ev = (Ecore_Event_Key *)eina_list_data_get(n);
3393 int event_type = (unsigned long int)ev->data;
3396 ecore_event_add(event_type, ev, _ecore_keyevent_free, NULL);
3397 imcontext->keysym_list = eina_list_remove_list(imcontext->keysym_list, n);
3408 wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int width, int height)
3410 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3411 if (!imcontext) return;
3413 if ((imcontext->cursor_location.x != x) ||
3414 (imcontext->cursor_location.y != y) ||
3415 (imcontext->cursor_location.width != width) ||
3416 (imcontext->cursor_location.height != height)) {
3417 imcontext->cursor_location.x = x;
3418 imcontext->cursor_location.y = y;
3419 imcontext->cursor_location.width = width;
3420 imcontext->cursor_location.height = height;
3422 if (_focused_ctx == ctx)
3423 send_cursor_location (imcontext);
3427 void wayland_im_context_autocapital_type_set(Ecore_IMF_Context *ctx,
3428 Ecore_IMF_Autocapital_Type autocapital_type)
3430 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3431 if (!imcontext) return;
3433 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
3434 // TIZEN_ONLY(20160201): Add autocapitalization word
3435 WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION |
3437 WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
3438 WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE);
3440 if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE)
3441 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION;
3442 // TIZEN_ONLY(20160201): Add autocapitalization word
3443 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD)
3444 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
3446 else if (autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER)
3447 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE;
3449 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE;
3451 if (imcontext->input && imcontext->text_input) {
3452 LOGD ("ctx : %p. set autocapital type : %d", ctx, autocapital_type);
3453 wl_text_input_set_content_type(imcontext->text_input,
3454 imcontext->content_hint,
3460 wayland_im_context_input_panel_layout_set(Ecore_IMF_Context *ctx,
3461 Ecore_IMF_Input_Panel_Layout layout)
3463 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3464 if (!imcontext) return;
3466 imcontext->input_panel_layout = layout;
3469 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER:
3470 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER;
3472 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL:
3473 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL;
3475 case ECORE_IMF_INPUT_PANEL_LAYOUT_URL:
3476 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_URL;
3478 case ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER:
3479 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE;
3481 case ECORE_IMF_INPUT_PANEL_LAYOUT_IP:
3482 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3483 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_IP;
3486 case ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH:
3487 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATE;
3489 case ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY:
3490 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS;
3492 case ECORE_IMF_INPUT_PANEL_LAYOUT_HEX:
3493 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_HEX;
3495 case ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL:
3496 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL;
3498 case ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD:
3499 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD;
3500 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3502 case ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME:
3503 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME;
3505 // TIZEN_ONLY(20150710): Support IP and emoticon layout
3506 case ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON:
3507 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON;
3510 case ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE:
3511 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE;
3514 imcontext->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
3518 if (imcontext->input && imcontext->text_input) {
3519 LOGD ("ctx : %p, layout type : %d", ctx, layout);
3520 wl_text_input_set_content_type(imcontext->text_input,
3521 imcontext->content_hint,
3526 Ecore_IMF_Input_Panel_Layout
3527 wayland_im_context_input_panel_layout_get(Ecore_IMF_Context *ctx)
3529 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3530 if (!imcontext) return ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
3532 return imcontext->input_panel_layout;
3536 wayland_im_context_input_mode_set(Ecore_IMF_Context *ctx,
3537 Ecore_IMF_Input_Mode input_mode)
3539 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3540 if (!imcontext) return;
3542 if (input_mode & ECORE_IMF_INPUT_MODE_INVISIBLE)
3543 imcontext->content_hint |= (WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3545 imcontext->content_hint &= ~(WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA | WL_TEXT_INPUT_CONTENT_HINT_PASSWORD);
3547 if (imcontext->input && imcontext->text_input) {
3548 LOGD ("ctx : %p, input mode : %d", ctx, input_mode);
3549 wl_text_input_set_content_type(imcontext->text_input,
3550 imcontext->content_hint,
3556 wayland_im_context_input_hint_set(Ecore_IMF_Context *ctx,
3557 Ecore_IMF_Input_Hints input_hints)
3559 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3560 if (!imcontext) return;
3562 if (input_hints & ECORE_IMF_INPUT_HINT_AUTO_COMPLETE)
3563 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3565 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3567 if (input_hints & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA)
3568 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3570 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA;
3572 if (input_hints & ECORE_IMF_INPUT_HINT_MULTILINE)
3573 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3575 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_MULTILINE;
3578 LOGD("autofill hint : %x\n", input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK);
3580 switch(input_hints & ECORE_IMF_INPUT_HINT_AUTOFILL_MASK)
3582 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE:
3583 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE;
3585 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY:
3586 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY;
3588 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH:
3589 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH;
3591 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR:
3592 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR;
3594 case ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_NUMBER:
3595 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_NUMBER;
3597 case ECORE_IMF_INPUT_HINT_AUTOFILL_EMAIL_ADDRESS:
3598 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_EMAIL_ADDRESS;
3600 case ECORE_IMF_INPUT_HINT_AUTOFILL_PHONE:
3601 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_PHONE;
3603 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_ADDRESS:
3604 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_ADDRESS;
3606 case ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_CODE:
3607 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_CODE;
3609 case ECORE_IMF_INPUT_HINT_AUTOFILL_ID:
3610 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_ID;
3612 case ECORE_IMF_INPUT_HINT_AUTOFILL_NAME:
3613 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_NAME;
3617 if (imcontext->input && imcontext->text_input) {
3618 LOGD("ctx : %p, input hint : %#x", ctx, input_hints);
3619 wl_text_input_set_content_type(imcontext->text_input,
3620 imcontext->content_hint,
3626 wayland_im_context_input_panel_language_set(Ecore_IMF_Context *ctx,
3627 Ecore_IMF_Input_Panel_Lang lang)
3629 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3630 if (!imcontext) return;
3632 if (lang == ECORE_IMF_INPUT_PANEL_LANG_ALPHABET)
3633 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3635 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_LATIN;
3637 if (imcontext->input && imcontext->text_input)
3638 wl_text_input_set_content_type(imcontext->text_input,
3639 imcontext->content_hint,
3643 // TIZEN_ONLY(20150708): Support input_panel_state_get
3644 Ecore_IMF_Input_Panel_State
3645 wayland_im_context_input_panel_state_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3647 return _input_panel_state;
3651 wayland_im_context_input_panel_return_key_type_set(Ecore_IMF_Context *ctx,
3652 Ecore_IMF_Input_Panel_Return_Key_Type return_key_type)
3654 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3655 if (!imcontext) return;
3657 imcontext->return_key_type = return_key_type;
3659 if (imcontext->input && imcontext->text_input)
3660 wl_text_input_set_return_key_type(imcontext->text_input,
3661 imcontext->return_key_type);
3665 wayland_im_context_input_panel_return_key_disabled_set(Ecore_IMF_Context *ctx,
3668 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3669 if (!imcontext) return;
3671 imcontext->return_key_disabled = disabled;
3673 if (imcontext->input && imcontext->text_input)
3674 wl_text_input_set_return_key_disabled(imcontext->text_input,
3675 imcontext->return_key_disabled);
3680 wayland_im_context_input_panel_language_locale_get(Ecore_IMF_Context *ctx,
3683 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3684 if (!imcontext) return;
3687 *locale = strdup(imcontext->language ? imcontext->language : "");
3691 wayland_im_context_prediction_allow_set(Ecore_IMF_Context *ctx,
3692 Eina_Bool prediction)
3694 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3695 if (!imcontext) return;
3698 imcontext->content_hint |= WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3700 imcontext->content_hint &= ~WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
3702 if (imcontext->input && imcontext->text_input)
3703 wl_text_input_set_content_type(imcontext->text_input,
3704 imcontext->content_hint,
3708 // TIZEN_ONLY(20151221): Support input panel geometry
3710 wayland_im_context_input_panel_geometry_get(Ecore_IMF_Context *ctx EINA_UNUSED,
3711 int *x, int *y, int *w, int *h)
3714 *x = _keyboard_geometry.x;
3716 *y = _keyboard_geometry.y;
3718 *w = _keyboard_geometry.w;
3720 *h = _keyboard_geometry.h;
3724 wayland_im_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *data, int length)
3726 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3727 if (!imcontext) return;
3729 if (data && length > 0) {
3730 const char *custom_conformant_enabled = "conformant:custom,enabled";
3731 const char *custom_conformant_disabled = "conformant:custom,disabled";
3732 const char *custom_conformant_finished = "conformant:custom,finished";
3734 if (strncmp(data, custom_conformant_enabled, strlen(custom_conformant_enabled)) == 0) {
3735 _custom_conformant_event = EINA_TRUE;
3738 if (strncmp(data, custom_conformant_disabled, strlen(custom_conformant_disabled)) == 0) {
3739 _custom_conformant_event = EINA_FALSE;
3742 if (strncmp(data, custom_conformant_finished, strlen(custom_conformant_finished)) == 0) {
3743 if (_custom_conformant_event) {
3744 _conformant_reset_done = EINA_TRUE;
3745 LOGD("[conformant:custom,finished], _conformant_reset_done = 1");
3746 send_will_hide_ack(NULL);
3752 if (imcontext->imdata)
3753 free(imcontext->imdata);
3755 imcontext->imdata = calloc(1, length);
3756 if (imcontext->imdata && data)
3757 memcpy(imcontext->imdata, data, length);
3759 imcontext->imdata_size = length;
3761 if (imcontext->input && imcontext->text_input && (imcontext->imdata_size > 0))
3762 wl_text_input_set_input_panel_data(imcontext->text_input, (const char *)imcontext->imdata, imcontext->imdata_size);
3766 wayland_im_context_input_panel_imdata_get(Ecore_IMF_Context *ctx, void *data, int *length)
3769 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3771 if (imcontext && imcontext->input_panel_data && (imcontext->input_panel_data_length > 0)) {
3773 memcpy(data, imcontext->input_panel_data, imcontext->input_panel_data_length);
3776 *length = imcontext->input_panel_data_length;
3784 // TIZEN_ONLY(20160218): Support BiDi direction
3786 wayland_im_context_bidi_direction_set(Ecore_IMF_Context *ctx, Ecore_IMF_BiDi_Direction bidi_direction)
3788 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3789 if (!imcontext) return;
3791 imcontext->bidi_direction = bidi_direction;
3793 if (imcontext->input && imcontext->text_input) {
3794 LOGD ("ctx : %p, bidi direction : %#x", ctx, bidi_direction);
3795 wl_text_input_bidi_direction(imcontext->text_input, imcontext->bidi_direction);
3800 Ecore_IMF_Input_Panel_Keyboard_Mode
3801 wayland_im_context_input_panel_keyboard_mode_get(Ecore_IMF_Context *ctx EINA_UNUSED)
3803 return hw_keyboard_mode ? ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE : ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE;
3807 wayland_im_context_prediction_hint_set (Ecore_IMF_Context *ctx, const char *prediction_hint)
3809 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3810 if (!imcontext) return;
3812 imcontext->prediction_hint = strdup(prediction_hint ? prediction_hint : "");
3814 if (imcontext->input && imcontext->text_input) {
3815 SECURE_LOGD ("ctx : %p, prediction_hint : %s", ctx, imcontext->prediction_hint);
3816 wl_text_input_prediction_hint(imcontext->text_input, imcontext->prediction_hint);
3821 wayland_im_context_mime_type_accept_set (Ecore_IMF_Context *ctx, const char *mime_type)
3823 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3824 if (!imcontext) return;
3826 imcontext->mime_type = strdup(mime_type);
3828 if (imcontext->input && imcontext->text_input && (strlen(mime_type) > 0)) {
3829 LOGD ("ctx : %p, mime_type : %s", ctx, imcontext->mime_type);
3830 wl_text_input_set_mime_type(imcontext->text_input, imcontext->mime_type);
3835 wayland_im_context_input_panel_position_set (Ecore_IMF_Context *ctx, int x, int y)
3837 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
3838 if (!imcontext) return;
3840 if ((imcontext->input_panel_position.x != x) || (imcontext->input_panel_position.y != y)) {
3841 imcontext->input_panel_position.x = x;
3842 imcontext->input_panel_position.y = y;
3845 if (imcontext->input && imcontext->text_input) {
3846 LOGD ("ctx : %p, x = %d, y = %d", ctx, x, y);
3847 wl_text_input_set_input_panel_position(imcontext->text_input,
3848 imcontext->input_panel_position.x, imcontext->input_panel_position.y);
3852 WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager)
3854 WaylandIMContext *context = calloc(1, sizeof(WaylandIMContext));
3856 LOGD("new context created");
3857 context->text_input_manager = text_input_manager;
3863 void wayland_im_context_pair_set (Ecore_IMF_Context *ctx, WaylandIMContext *imcontext)
3865 _ecore_imf_wayland_imcontext_pair_add (ctx, imcontext);