3 #include "e_mod_main.h"
4 #include <text-server-protocol.h>
5 #include <input-method-server-protocol.h>
7 #include <vconf-keys.h>
9 #include <Ecore_Wayland.h>
12 #include <system_info.h>
17 #define LOG_TAG "WL_TEXTINPUT"
19 #define WTI_WARNING(resource, code, msg) (_e_text_input_log_show((resource), (code), (msg), __func__))
21 tizen_profile_t _get_tizen_profile()
23 static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
24 if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
28 system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
33 profile = TIZEN_PROFILE_MOBILE;
37 profile = TIZEN_PROFILE_WEARABLE;
41 profile = TIZEN_PROFILE_TV;
45 profile = TIZEN_PROFILE_IVI;
47 default: // common or unknown ==> ALL ARE COMMON.
48 profile = TIZEN_PROFILE_COMMON;
55 static Eina_Bool _e_text_input_method_context_cb_client_resize(void *data EINA_UNUSED, int type, void *event);
56 static void set_soft_keyboard_mode();
58 typedef struct _E_Text_Input E_Text_Input;
59 typedef struct _E_Text_Input_Mgr E_Text_Input_Mgr;
60 typedef struct _E_Input_Method E_Input_Method;
61 typedef struct _E_Input_Method_Context E_Input_Method_Context;
62 typedef struct _E_Mod_Text_Input_Shutdown_Cb E_Mod_Text_Input_Shutdown_Cb;
66 struct wl_resource *resource;
68 Eina_List *input_methods;
69 Eina_Bool input_panel_visibile;
73 struct _E_Text_Input_Mgr
75 struct wl_global *global;
76 struct wl_resource *resource;
78 Eina_List *text_input_list;
81 struct _E_Input_Method
83 struct wl_global *global;
84 struct wl_resource *resource;
87 E_Input_Method_Context *context;
90 struct _E_Input_Method_Context
92 struct wl_resource *resource;
95 E_Input_Method *input_method;
97 #if ENABLE_GRAB_KEYBOARD
100 struct wl_resource *resource;
103 struct xkb_keymap *keymap;
104 struct xkb_state *state;
105 xkb_mod_mask_t mod_depressed, mod_latched, mod_locked;
106 xkb_layout_index_t mod_group;
112 struct _E_Mod_Text_Input_Shutdown_Cb
114 void (*func)(void *data);
118 struct _E_Input_Method_Keymap_Info
120 const char *language;
126 enum _E_Input_Panel_State
128 E_INPUT_PANEL_STATE_DID_HIDE,
129 E_INPUT_PANEL_STATE_WILL_HIDE,
130 E_INPUT_PANEL_STATE_DID_SHOW,
131 E_INPUT_PANEL_STATE_WILL_SHOW,
134 static E_Input_Method *g_input_method = NULL;
135 static E_Text_Input *g_text_input = NULL;
136 static struct wl_client *g_client = NULL;
137 static Eina_List *shutdown_list = NULL;
138 static Eina_Bool g_disable_show_panel = EINA_FALSE;
139 static Eeze_Udev_Watch *eeze_udev_watch_hander = NULL;
140 static Ecore_Event_Handler *ecore_key_down_handler = NULL;
141 static Eina_List *handlers = NULL;
142 static uint32_t g_text_input_count = 1;
143 static uint32_t g_keymap_index = 0;
144 static Eina_Bool g_keyboard_mode_engligh = EINA_TRUE;
145 static Ecore_Timer *g_timer_will_hide = NULL;
146 static enum _E_Input_Panel_State g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
147 static E_Client *client_surface_ec = NULL;
148 static E_Text_Input *g_show_text_input = NULL;
149 static struct wl_client *g_show_client = NULL;
151 static Eina_List *hooks_ec = NULL;
153 const int WILL_HIDE_TIMER_INTERVAL = 1.0f;
155 #undef E_CLIENT_HOOK_APPEND
156 #define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
160 _h = e_client_hook_add(t, cb, d); \
162 l = eina_list_append(l, _h); \
166 static struct _E_Input_Method_Keymap_Info g_keymap_info[] = {
167 {"en_US", "evdev", "pc105", "us"},
168 {"ru_RU", "evdev", "pc105", "ru"},
171 static void _e_text_input_deactivate(E_Text_Input *text_input, E_Input_Method *input_method, Eina_Bool need_focus_in);
172 static Eina_Bool _e_text_input_method_create_context(struct wl_client *client, E_Input_Method *input_method, E_Text_Input *text_input, Eina_Bool need_focus_out);
175 _e_text_input_log_show(struct wl_resource *resource, uint32_t code, const char *msg, const char *warning_msg)
177 LOGE("%s() is failed. msg : %s\n", warning_msg, msg);
181 _e_text_input_send_input_panel_geometry(struct wl_resource *resource, int x, int y, int w, int h)
186 if (client_surface_ec)
188 angle = client_surface_ec->e.state.rot.ang.next < 0 ?
189 client_surface_ec->e.state.rot.ang.curr :
190 client_surface_ec->e.state.rot.ang.next;
192 LOGD("curr : %d, next : %d, angle : %d\n", client_surface_ec->e.state.rot.ang.curr,
193 client_surface_ec->e.state.rot.ang.next, angle);
196 snprintf(geometry, sizeof(geometry), "%d,%d,%d,%d", x, y, w, h);
202 vconf_set_str(VCONFKEY_ISF_IME_RECENT_LAND_GEOMETRY, geometry);
205 vconf_set_str(VCONFKEY_ISF_IME_RECENT_PORT_GEOMETRY, geometry);
209 LOGD("angle : %d, x : %d, y : %d, w : %d, h : %d\n", angle, x, y, w, h);
211 wl_text_input_send_input_panel_geometry(resource, x, y, w, h);
215 _will_hide_timer_handler(void *data)
217 INF("TIMED OUT while waiting for WILL_HIDE_ACK : %d", g_input_panel_state);
218 if (g_input_panel_state == E_INPUT_PANEL_STATE_WILL_HIDE)
220 e_input_panel_visibility_change(EINA_FALSE);
221 e_input_panel_transient_for_set(NULL);
222 g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
225 if (g_timer_will_hide)
227 ecore_timer_del(g_timer_will_hide);
228 g_timer_will_hide = NULL;
231 return ECORE_CALLBACK_CANCEL;
235 _input_panel_hide(struct wl_client *client, struct wl_resource *resource, Eina_Bool force_hide)
237 E_Text_Input *text_input = wl_resource_get_user_data(resource);
238 E_Input_Method *input_method = NULL;
239 Eina_Bool _context_created = EINA_FALSE;
243 WTI_WARNING(resource,
244 WL_DISPLAY_ERROR_INVALID_OBJECT,
245 "No Text Input For Resource");
249 text_input->input_panel_visibile = EINA_FALSE;
251 if (text_input->resource)
253 wl_text_input_send_input_panel_geometry(text_input->resource, 0, 0, 0, 0);
254 wl_text_input_send_input_panel_state(text_input->resource, WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE);
259 e_input_panel_visibility_change(EINA_FALSE);
260 e_input_panel_transient_for_set(NULL);
261 g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
265 g_input_panel_state = E_INPUT_PANEL_STATE_WILL_HIDE;
266 /* Temporarily sending private command, will need for a new wayland protocol */
267 if (text_input->resource)
268 wl_text_input_send_private_command(text_input->resource, 0, "CONFORMANT_RESET");
270 if (g_timer_will_hide)
272 ecore_timer_del(g_timer_will_hide);
273 g_timer_will_hide = NULL;
275 g_timer_will_hide = ecore_timer_add(WILL_HIDE_TIMER_INTERVAL, _will_hide_timer_handler, NULL);
278 if (g_input_method && g_input_method->resource)
279 input_method = wl_resource_get_user_data(g_input_method->resource);
282 If input_method->context is already deleted, create context struct again to send input_panel_hide event to Input Method(IME) correctly.
283 Because input_panel_hide event can be called after focus_out(deactivate) by application.
284 And Input Method(IME) should know the state of their own input_panel to manage their resource when the input_panel is hidden.
287 ((!input_method->context) || (!input_method->context->resource)))
288 _context_created = _e_text_input_method_create_context(client, input_method, text_input, EINA_FALSE);
290 if (input_method && input_method->resource && input_method->context && input_method->context->resource)
291 wl_input_method_send_hide_input_panel(input_method->resource, input_method->context->resource);
293 if (_context_created)
294 _e_text_input_deactivate(text_input, input_method, EINA_FALSE);
296 e_input_panel_wait_update_set(EINA_FALSE);
300 _keyboard_mode_changed_cb(keynode_t *key, void* data)
303 if (vconf_get_bool(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0)
307 g_disable_show_panel = EINA_FALSE;
311 if (g_text_input && g_text_input->resource && g_client)
312 _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
313 g_disable_show_panel = EINA_TRUE;
319 _display_language_changed_cb(keynode_t *key, void* data)
322 char *language = vconf_get_str(VCONFKEY_LANGSET);
324 /* Just in case we did not find any matching language string */
328 for (loop = 0; loop < sizeof(g_keymap_info) / sizeof(struct _E_Input_Method_Keymap_Info); loop++)
330 if (strncmp(language, g_keymap_info[loop].language, strlen(g_keymap_info[loop].language)) == 0)
332 g_keymap_index = loop;
337 /* We do not want to change the current keymap related behavior in TV profile for now */
340 /* Resetting the H/W keyboard language mode to English, would be more appropriate when the
341 * display language gets changed, such as the cases like changing from French to Russian, for example */
342 e_comp_wl_input_keymap_set(g_keymap_info[0].rules, g_keymap_info[0].models, g_keymap_info[0].layout, NULL, NULL, NULL, NULL);
344 g_keyboard_mode_engligh = EINA_TRUE;
347 #if ENABLE_GRAB_KEYBOARD
349 _e_text_input_method_context_keyboard_grab_keyboard_state_update(E_Input_Method_Context *context, uint32_t keycode, Eina_Bool pressed)
351 enum xkb_key_direction dir;
353 if (!context->kbd.state) return;
355 if (pressed) dir = XKB_KEY_DOWN;
356 else dir = XKB_KEY_UP;
358 context->kbd.mod_changed =
359 xkb_state_update_key(context->kbd.state, keycode + 8, dir);
363 _e_text_input_method_context_keyboard_grab_keyboard_modifiers_update(E_Input_Method_Context *context, struct wl_resource *keyboard)
367 if (!context->input) return;
368 if (!context->kbd.state) return;
370 context->kbd.mod_depressed =
371 xkb_state_serialize_mods(context->kbd.state, XKB_STATE_DEPRESSED);
372 context->kbd.mod_latched =
373 xkb_state_serialize_mods(context->kbd.state, XKB_STATE_MODS_LATCHED);
374 context->kbd.mod_locked =
375 xkb_state_serialize_mods(context->kbd.state, XKB_STATE_MODS_LOCKED);
376 context->kbd.mod_group =
377 xkb_state_serialize_layout(context->kbd.state, XKB_STATE_LAYOUT_EFFECTIVE);
379 serial = wl_display_next_serial(e_comp_wl->wl.disp);
380 wl_keyboard_send_modifiers(keyboard, serial,
381 context->kbd.mod_depressed,
382 context->kbd.mod_latched,
383 context->kbd.mod_locked,
384 context->kbd.mod_group);
388 _e_text_input_method_context_key_send(E_Input_Method_Context *context, unsigned int keycode, unsigned int timestamp, enum wl_keyboard_key_state state)
392 if (!context->input) return;
395 /* update modifier state */
396 _e_text_input_method_context_keyboard_grab_keyboard_state_update(context, nk, state == WL_KEYBOARD_KEY_STATE_PRESSED);
398 serial = wl_display_next_serial(e_comp_wl->wl.disp);
400 wl_keyboard_send_key(context->kbd.resource, serial, timestamp, nk, state);
401 if (context->kbd.mod_changed)
403 _e_text_input_method_context_keyboard_grab_keyboard_modifiers_update(context, context->kbd.resource);
404 context->kbd.mod_changed = 0;
409 _e_text_input_method_context_filter_hotkeys(E_Input_Method_Context *context, Ecore_Event_Key *ev)
411 if (!ev) return EINA_FALSE;
412 if (!context) return EINA_FALSE;
414 /* We do not want to change the current keymap related behavior in TV profile for now */
417 const char *keyname_space = "space";
418 if ((strncmp(ev->keyname, keyname_space, strlen(keyname_space)) == 0) && (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT))
421 keymap_index = g_keyboard_mode_engligh ? g_keymap_index : 0;
422 e_comp_wl_input_keymap_set(g_keymap_info[keymap_index].rules, g_keymap_info[keymap_index].models, g_keymap_info[keymap_index].layout, NULL, NULL, NULL, NULL);
423 wl_keyboard_send_keymap(context->kbd.resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
424 e_comp_wl->xkb.fd, e_comp_wl->xkb.size);
425 g_keyboard_mode_engligh = !g_keyboard_mode_engligh;
434 _e_text_input_method_context_ecore_cb_key_down(void *data, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
436 E_Input_Method_Context *context = data;
438 if (!_e_text_input_method_context_filter_hotkeys(context, ev))
440 _e_text_input_method_context_key_send(context, ev->keycode, ev->timestamp,
441 WL_KEYBOARD_KEY_STATE_PRESSED);
444 return ECORE_CALLBACK_RENEW;
448 _e_text_input_method_context_ecore_cb_key_up(void *data, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
450 E_Input_Method_Context *context = data;
452 _e_text_input_method_context_key_send(context, ev->keycode, ev->timestamp,
453 WL_KEYBOARD_KEY_STATE_RELEASED);
455 return ECORE_CALLBACK_RENEW;
459 _e_text_input_method_context_grab_set(E_Input_Method_Context *context, Eina_Bool set)
461 if (set == context->kbd.grabbed)
467 context->kbd.grabbed = set;
471 if (context->kbd.keymap) xkb_map_unref(context->kbd.keymap);
472 if (context->kbd.state) xkb_state_unref(context->kbd.state);
473 context->kbd.keymap = xkb_map_ref(e_comp_wl->xkb.keymap);
474 context->kbd.state = xkb_state_new(e_comp_wl->xkb.keymap);
475 E_LIST_HANDLER_APPEND(context->kbd.handlers, ECORE_EVENT_KEY_DOWN,
476 _e_text_input_method_context_ecore_cb_key_down,
478 E_LIST_HANDLER_APPEND(context->kbd.handlers, ECORE_EVENT_KEY_UP,
479 _e_text_input_method_context_ecore_cb_key_up,
482 e_comp_grab_input(0, 1);
486 E_FREE_LIST(context->kbd.handlers, ecore_event_handler_del);
488 e_comp_ungrab_input(0, 1);
490 if (context->kbd.keymap)
492 xkb_map_unref(context->kbd.keymap);
493 context->kbd.keymap = NULL;
496 if (context->kbd.state)
498 xkb_state_unref(context->kbd.state);
499 context->kbd.state = NULL;
506 _e_mod_text_input_shutdown_cb_add(void (*func)(void *data), void *data)
508 E_Mod_Text_Input_Shutdown_Cb *cb;
510 if (!(cb = E_NEW(E_Mod_Text_Input_Shutdown_Cb, 1)))
512 ERR("Could not allocate space for Text Input Shutdown Callback");
519 shutdown_list = eina_list_append(shutdown_list, cb);
523 _e_text_input_method_context_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
525 wl_resource_destroy(resource);
529 _e_text_input_method_context_cb_string_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *text)
531 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
535 WTI_WARNING(resource,
536 WL_DISPLAY_ERROR_INVALID_OBJECT,
537 "No Input Method Context For Resource");
541 if ((context->input) && (context->input->resource))
542 wl_text_input_send_commit_string(context->input->resource,
547 _e_text_input_method_context_cb_preedit_string(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *text, const char *commit)
549 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
553 WTI_WARNING(resource,
554 WL_DISPLAY_ERROR_INVALID_OBJECT,
555 "No Input Method Context For Resource");
559 if ((context->input) && (context->input->resource))
560 wl_text_input_send_preedit_string(context->input->resource,
561 serial, text, commit);
565 _e_text_input_method_context_cb_recapture_string(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, int32_t index, uint32_t length, const char *preedit, const char *preedit_commit, const char *commit)
567 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
571 WTI_WARNING(resource,
572 WL_DISPLAY_ERROR_INVALID_OBJECT,
573 "No Input Method Context For Resource");
577 if ((context->input) && (context->input->resource))
578 wl_text_input_send_recapture_string(context->input->resource,
579 serial, index, length, preedit, preedit_commit, commit);
583 _e_text_input_method_context_cb_preedit_styling(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t index, uint32_t length, uint32_t style)
585 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
589 WTI_WARNING(resource,
590 WL_DISPLAY_ERROR_INVALID_OBJECT,
591 "No Input Method Context For Resource");
595 if ((context->input) && (context->input->resource))
596 wl_text_input_send_preedit_styling(context->input->resource,
597 index, length, style);
601 _e_text_input_method_context_cb_preedit_cursor(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t cursor)
603 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
607 WTI_WARNING(resource,
608 WL_DISPLAY_ERROR_INVALID_OBJECT,
609 "No Input Method Context For Resource");
613 if ((context->input) && (context->input->resource))
614 wl_text_input_send_preedit_cursor(context->input->resource,
619 _e_text_input_method_context_cb_surrounding_text_delete(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t index, uint32_t length)
621 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
625 WTI_WARNING(resource,
626 WL_DISPLAY_ERROR_INVALID_OBJECT,
627 "No Input Method Context For Resource");
631 if ((context->input) && (context->input->resource))
632 wl_text_input_send_delete_surrounding_text(context->input->resource,
637 _e_text_input_method_context_cb_cursor_position(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t index, int32_t anchor)
639 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
643 WTI_WARNING(resource,
644 WL_DISPLAY_ERROR_INVALID_OBJECT,
645 "No Input Method Context For Resource");
649 if ((context->input) && (context->input->resource))
650 wl_text_input_send_cursor_position(context->input->resource,
655 _e_text_input_method_context_cb_modifiers_map(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_array *map)
657 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
661 WTI_WARNING(resource,
662 WL_DISPLAY_ERROR_INVALID_OBJECT,
663 "No Input Method Context For Resource");
667 if ((context->input) && (context->input->resource))
668 wl_text_input_send_modifiers_map(context->input->resource, map);
672 _e_keyevent_free(void *data EINA_UNUSED, void *ev)
674 Ecore_Event_Key *e = ev;
677 eina_stringshare_del(e->keyname);
680 eina_stringshare_del(e->key);
683 eina_stringshare_del(e->compose);
686 eina_stringshare_del(e->string);
692 feed_key_event(const char *keyname, const char *key, const char *string, int keycode, int state)
694 Ecore_Event_Key *e = E_NEW(Ecore_Event_Key, 1);
697 e->keyname = (char *)eina_stringshare_add(keyname);
698 e->key = (char *)eina_stringshare_add(key);
699 e->string = (char *)eina_stringshare_add(string);
700 e->compose = (char *)eina_stringshare_add(e->string);
702 e->timestamp = 0; /* For distinguishing S/W keyboard event */
704 e->keycode = keycode;
706 ecore_event_add(state ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP, e, _e_keyevent_free, NULL);
710 _e_text_input_method_context_cb_keysym(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers)
712 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
716 WTI_WARNING(resource,
717 WL_DISPLAY_ERROR_INVALID_OBJECT,
718 "No Input Method Context For Resource");
722 if ((context->input) && (context->input->resource))
724 wl_text_input_send_keysym(context->input->resource,
725 serial, time, sym, state, modifiers);
729 char string[32], key[32], keyname[32];
731 memset(keyname, 0, sizeof(keyname));
732 xkb_keysym_get_name(sym, keyname, sizeof(keyname));
733 if (keyname[0] == '\0')
734 snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
736 if (strcmp(keyname, "BackSpace") == 0)
738 /* backspace key should be supported in the multibutton entry of elementary
739 even though it losts focus */
740 memset(key, 0, sizeof(key));
741 xkb_keysym_get_name(sym, key, sizeof(key));
743 memset(string, 0, sizeof(string));
744 xkb_keysym_to_utf8(sym, string, 32);
748 /* Backspace keycode (22) */
749 feed_key_event(keyname, key, string, 22, 1); /* key down */
750 feed_key_event(keyname, key, string, 22, 0); /* key up */
756 #if ENABLE_GRAB_KEYBOARD
758 _e_text_input_method_context_keyboard_grab_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
760 wl_resource_destroy(resource);
763 static const struct wl_keyboard_interface _e_keyboard_grab_interface =
765 _e_text_input_method_context_keyboard_grab_cb_resource_destroy
769 _e_text_input_method_context_keyboard_grab_cb_keyboard_unbind(struct wl_resource *resource)
771 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
775 WTI_WARNING(resource,
776 WL_DISPLAY_ERROR_INVALID_OBJECT,
777 "No Input Method Context For Resource");
781 _e_text_input_method_context_grab_set(context, EINA_FALSE);
783 context->kbd.resource = NULL;
788 _e_text_input_method_context_cb_keyboard_grab(struct wl_client *client, struct wl_resource *resource, uint32_t id)
790 DBG("Input Method Context - grab keyboard %d", wl_resource_get_id(resource));
791 #if ENABLE_GRAB_KEYBOARD
792 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
793 struct wl_resource *keyboard = NULL;
797 WTI_WARNING(resource,
798 WL_DISPLAY_ERROR_INVALID_OBJECT,
799 "No Input Method Context For Resource");
803 keyboard = wl_resource_create(client, &wl_keyboard_interface, 1, id);
806 wl_client_post_no_memory(client);
810 wl_resource_set_implementation(keyboard, &_e_keyboard_grab_interface, context, _e_text_input_method_context_keyboard_grab_cb_keyboard_unbind);
812 /* send current keymap */
813 wl_keyboard_send_keymap(keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
814 e_comp_wl->xkb.fd, e_comp_wl->xkb.size);
816 context->kbd.resource = keyboard;
818 _e_text_input_method_context_grab_set(context, EINA_TRUE);
823 _e_text_input_method_context_cb_key(struct wl_client *client, struct wl_resource *resource, uint32_t serial, uint32_t time, uint32_t key, uint32_t state_w)
825 DBG("Input Method Context - key %d", wl_resource_get_id(resource));
836 _e_text_input_method_context_cb_modifiers(struct wl_client *client, struct wl_resource *resource, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
838 DBG("Input Method Context - modifiers %d", wl_resource_get_id(resource));
843 (void)mods_depressed;
850 _e_text_input_method_context_cb_language(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *language)
852 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
856 WTI_WARNING(resource,
857 WL_DISPLAY_ERROR_INVALID_OBJECT,
858 "No Input Method Context For Resource");
862 if ((context->input) && (context->input->resource))
863 wl_text_input_send_language(context->input->resource,
868 _e_text_input_method_context_cb_text_direction(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, uint32_t direction)
870 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
874 WTI_WARNING(resource,
875 WL_DISPLAY_ERROR_INVALID_OBJECT,
876 "No Input Method Context For Resource");
880 if ((context->input) && (context->input->resource))
881 wl_text_input_send_text_direction(context->input->resource,
886 _e_text_input_method_context_cb_selection_region(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, int32_t start, int32_t end)
888 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
892 WTI_WARNING(resource,
893 WL_DISPLAY_ERROR_INVALID_OBJECT,
894 "No Input Method Context For Resource");
898 if ((context->input) && (context->input->resource))
899 wl_text_input_send_selection_region(context->input->resource,
904 _e_text_input_method_context_cb_private_command(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *command)
906 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
910 WTI_WARNING(resource,
911 WL_DISPLAY_ERROR_INVALID_OBJECT,
912 "No Input Method Context For Resource");
916 if ((context->input) && (context->input->resource))
917 wl_text_input_send_private_command(context->input->resource,
922 _e_text_input_method_context_cb_input_panel_data_update(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *data, uint32_t length)
924 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
928 WTI_WARNING(resource,
929 WL_DISPLAY_ERROR_INVALID_OBJECT,
930 "No Input Method Context For Resource");
934 if ((context->input) && (context->input->resource))
935 wl_text_input_send_input_panel_data(context->input->resource,
936 serial, data, length);
940 _e_text_input_method_context_cb_hide_input_panel(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial)
942 E_Text_Input *text_input = g_text_input;
943 E_Input_Method *input_method = NULL;
947 WTI_WARNING(resource,
948 WL_DISPLAY_ERROR_INVALID_OBJECT,
949 "No Text Input For Resource");
953 text_input->input_panel_visibile = EINA_FALSE;
955 if (g_text_input && g_text_input->resource && g_client)
956 _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
958 if (g_input_method && g_input_method->resource)
959 input_method = wl_resource_get_user_data(g_input_method->resource);
961 if (input_method && input_method->resource && input_method->context && input_method->context->resource)
962 wl_input_method_send_hide_input_panel(input_method->resource, input_method->context->resource);
966 _e_text_input_method_context_cb_get_selection_text(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t fd)
968 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
972 WTI_WARNING(resource,
973 WL_DISPLAY_ERROR_INVALID_OBJECT,
974 "No Input Method Context For Resource");
979 if ((context->input) && (context->input->resource))
980 wl_text_input_send_get_selection_text(context->input->resource, fd);
986 _e_text_input_method_context_cb_get_surrounding_text(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,
987 uint32_t maxlen_before, uint32_t maxlen_after, int32_t fd)
989 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
993 WTI_WARNING(resource,
994 WL_DISPLAY_ERROR_INVALID_OBJECT,
995 "No Input Method Context For Resource");
1000 if ((context->input) && (context->input->resource))
1001 wl_text_input_send_get_surrounding_text(context->input->resource, maxlen_before, maxlen_after, fd);
1007 _e_text_input_method_context_cb_filter_key_event_done(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,
1008 uint32_t serial, uint32_t state)
1010 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1014 WTI_WARNING(resource,
1015 WL_DISPLAY_ERROR_INVALID_OBJECT,
1016 "No Input Method Context For Resource");
1020 if ((context->input) && (context->input->resource))
1021 wl_text_input_send_filter_key_event_done(context->input->resource,
1026 _e_text_input_method_context_cb_update_ise_geometry(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,
1027 uint32_t serial, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
1029 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1033 WTI_WARNING(resource,
1034 WL_DISPLAY_ERROR_INVALID_OBJECT,
1035 "No Input Method Context For Resource");
1039 if ((context->input) && (context->input->resource))
1040 _e_text_input_send_input_panel_geometry(context->input->resource, x, y, width, height);
1043 static const struct wl_input_method_context_interface _e_text_input_method_context_implementation = {
1044 _e_text_input_method_context_cb_destroy,
1045 _e_text_input_method_context_cb_string_commit,
1046 _e_text_input_method_context_cb_preedit_string,
1047 _e_text_input_method_context_cb_preedit_styling,
1048 _e_text_input_method_context_cb_preedit_cursor,
1049 _e_text_input_method_context_cb_surrounding_text_delete,
1050 _e_text_input_method_context_cb_cursor_position,
1051 _e_text_input_method_context_cb_modifiers_map,
1052 _e_text_input_method_context_cb_keysym,
1053 _e_text_input_method_context_cb_keyboard_grab,
1054 _e_text_input_method_context_cb_key,
1055 _e_text_input_method_context_cb_modifiers,
1056 _e_text_input_method_context_cb_language,
1057 _e_text_input_method_context_cb_text_direction,
1058 _e_text_input_method_context_cb_selection_region,
1059 _e_text_input_method_context_cb_private_command,
1060 _e_text_input_method_context_cb_input_panel_data_update,
1061 _e_text_input_method_context_cb_hide_input_panel,
1062 _e_text_input_method_context_cb_get_selection_text,
1063 _e_text_input_method_context_cb_get_surrounding_text,
1064 _e_text_input_method_context_cb_filter_key_event_done,
1065 _e_text_input_method_context_cb_update_ise_geometry,
1066 _e_text_input_method_context_cb_recapture_string
1070 _e_text_input_method_context_cb_resource_destroy(struct wl_resource *resource)
1072 E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1076 WTI_WARNING(resource,
1077 WL_DISPLAY_ERROR_INVALID_OBJECT,
1078 "No Input Method Context For Resource");
1082 #if ENABLE_GRAB_KEYBOARD
1083 if (context->kbd.resource)
1084 wl_resource_destroy(context->kbd.resource);
1087 if ((context->input_method) &&
1088 (context->input_method->context == context))
1089 context->input_method->context = NULL;
1094 static Eina_Bool is_number_key(const char *str)
1096 if (!str) return EINA_FALSE;
1098 int result = atoi(str);
1102 if (!strcmp(str, "0"))
1112 _e_mod_ecore_key_down_cb(void *data, int type, void *event)
1114 Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
1116 if (g_disable_show_panel == EINA_TRUE)
1117 return ECORE_CALLBACK_PASS_ON;
1119 /* process remote controller key exceptionally */
1120 if (((!strcmp(ev->key, "Down") ||
1121 !strcmp(ev->key, "KP_Down") ||
1122 !strcmp(ev->key, "Up") ||
1123 !strcmp(ev->key, "KP_Up") ||
1124 !strcmp(ev->key, "Right") ||
1125 !strcmp(ev->key, "KP_Right") ||
1126 !strcmp(ev->key, "Left") ||
1127 !strcmp(ev->key, "KP_Left")) && !ev->string) ||
1128 !strcmp(ev->key, "Return") ||
1129 !strcmp(ev->key, "Pause") ||
1130 !strcmp(ev->key, "NoSymbol") ||
1131 !strncmp(ev->key, "XF86", 4) ||
1132 is_number_key(ev->string))
1133 return ECORE_CALLBACK_PASS_ON;
1135 if (g_text_input && g_text_input->resource && g_client)
1136 _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
1138 g_disable_show_panel = EINA_TRUE;
1140 return ECORE_CALLBACK_PASS_ON;
1144 _e_text_input_deactivate(E_Text_Input *text_input, E_Input_Method *input_method, Eina_Bool need_focus_in)
1146 LOGD("text_input : %p\n", text_input);
1148 if (text_input == g_text_input)
1150 g_text_input = NULL;
1154 if (input_method->input == text_input)
1156 if ((input_method->context) && (input_method->resource))
1158 #if ENABLE_GRAB_KEYBOARD
1159 _e_text_input_method_context_grab_set(input_method->context,
1162 /* TODO: finish the grab of keyboard. */
1163 wl_input_method_send_deactivate(input_method->resource,
1164 input_method->context->resource,
1168 if (ecore_key_down_handler)
1170 ecore_event_handler_del(ecore_key_down_handler);
1171 ecore_key_down_handler = NULL;
1174 LOGD("Resetting input_method->input : %p", input_method->input);
1175 input_method->input = NULL;
1176 if (input_method->context) input_method->context->input = NULL;
1177 input_method->context = NULL;
1179 text_input->input_methods = eina_list_remove(text_input->input_methods, input_method);
1181 if (text_input->resource)
1182 wl_text_input_send_leave(text_input->resource);
1185 g_disable_show_panel = EINA_FALSE;
1190 _e_text_input_cb_activate(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, struct wl_resource *surface)
1192 E_Text_Input *text_input = NULL;
1193 E_Input_Method *input_method = NULL;
1194 E_Text_Input *old = NULL;
1195 E_Input_Method_Context *context = NULL;
1197 EINA_SAFETY_ON_NULL_GOTO(resource, err);
1198 EINA_SAFETY_ON_NULL_GOTO(seat, err);
1199 EINA_SAFETY_ON_NULL_GOTO(g_input_method, err);
1200 EINA_SAFETY_ON_NULL_GOTO(g_input_method->resource, err);
1202 /* Store application window's E_Client* value for setting transient_for information later */
1203 E_Client *ec = wl_resource_get_user_data(surface);
1204 EINA_SAFETY_ON_NULL_GOTO(ec, err);
1205 EINA_SAFETY_ON_TRUE_GOTO(e_object_is_del(E_OBJECT(ec)), err);
1206 client_surface_ec = ec;
1208 text_input = wl_resource_get_user_data(resource);
1209 g_text_input = text_input;
1212 /* FIXME: should get input_method object from seat. */
1213 input_method = wl_resource_get_user_data(g_input_method->resource);
1214 EINA_SAFETY_ON_NULL_GOTO(input_method, err);
1216 LOGD("text_input : %p\n", text_input);
1218 old = input_method->input;
1220 LOGD("old : %p, text_input : %p , %d", old, text_input, g_input_panel_state);
1221 if (old == text_input)
1225 _e_text_input_deactivate(old, input_method, EINA_TRUE);
1227 input_method->input = text_input;
1228 text_input->input_methods = eina_list_append(text_input->input_methods, input_method);
1230 if (input_method->resource)
1232 if (!(context = E_NEW(E_Input_Method_Context, 1)))
1234 wl_client_post_no_memory(client);
1235 ERR("Could not allocate space for Input_Method_Context");
1239 if (!ecore_key_down_handler)
1240 ecore_key_down_handler = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
1241 _e_mod_ecore_key_down_cb,
1245 wl_resource_create(wl_resource_get_client(input_method->resource),
1246 &wl_input_method_context_interface, 1, 0);
1248 if (context->resource)
1249 wl_resource_set_implementation(context->resource,
1250 &_e_text_input_method_context_implementation,
1251 context, _e_text_input_method_context_cb_resource_destroy);
1253 context->input = text_input;
1254 context->input_method = input_method;
1255 input_method->context = context;
1257 if (context->resource)
1258 wl_input_method_send_activate(input_method->resource, context->resource, text_input->id, EINA_TRUE);
1262 set_soft_keyboard_mode();
1264 if (text_input->resource)
1265 wl_text_input_send_enter(text_input->resource, surface);
1271 WTI_WARNING(resource,
1272 WL_DISPLAY_ERROR_INVALID_OBJECT,
1273 "No Text Input For Resource");
1277 WL_DISPLAY_ERROR_INVALID_OBJECT,
1278 "No Comp Data For Seat");
1282 _e_text_input_cb_deactivate(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat)
1285 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1286 E_Input_Method *input_method = NULL;
1290 WTI_WARNING(resource,
1291 WL_DISPLAY_ERROR_INVALID_OBJECT,
1292 "No Text Input For Resource");
1296 if (text_input == g_text_input)
1298 g_text_input = NULL;
1302 /* FIXME: should get input_method object from seat. */
1303 if (g_input_method && g_input_method->resource)
1304 input_method = wl_resource_get_user_data(g_input_method->resource);
1309 WL_DISPLAY_ERROR_INVALID_OBJECT,
1310 "No Input Method For Seat");
1314 _e_text_input_deactivate(text_input, input_method, EINA_TRUE);
1318 _e_text_input_method_create_context(struct wl_client *client, E_Input_Method *input_method, E_Text_Input *text_input, Eina_Bool need_focus_out)
1320 E_Input_Method_Context *context = NULL;
1322 EINA_SAFETY_ON_NULL_RETURN_VAL(input_method, EINA_FALSE);
1323 EINA_SAFETY_ON_NULL_RETURN_VAL(input_method->resource, EINA_FALSE);
1324 EINA_SAFETY_ON_NULL_RETURN_VAL(text_input, EINA_FALSE);
1326 g_text_input = text_input;
1328 input_method->input = text_input;
1329 text_input->input_methods = eina_list_append(text_input->input_methods, input_method);
1331 if (!(context = E_NEW(E_Input_Method_Context, 1)))
1333 wl_client_post_no_memory(client);
1334 ERR("Could not allocate space for Input_Method_Context");
1339 wl_resource_create(wl_resource_get_client(input_method->resource),
1340 &wl_input_method_context_interface, 1, 0);
1342 if (context->resource)
1343 wl_resource_set_implementation(context->resource,
1344 &_e_text_input_method_context_implementation,
1345 context, _e_text_input_method_context_cb_resource_destroy);
1347 context->input = text_input;
1348 context->input_method = input_method;
1349 input_method->context = context;
1351 wl_input_method_send_activate(input_method->resource, context->resource, text_input->id, need_focus_out);
1357 _e_text_input_cb_input_panel_show(struct wl_client *client, struct wl_resource *resource)
1359 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1360 E_Input_Method *input_method = NULL;
1362 LOGD("text_input : %p\n", text_input);
1366 WTI_WARNING(resource,
1367 WL_DISPLAY_ERROR_INVALID_OBJECT,
1368 "No Text Input For Resource");
1372 if (g_disable_show_panel == EINA_TRUE)
1375 if (g_input_method && g_input_method->resource)
1376 input_method = wl_resource_get_user_data(g_input_method->resource);
1378 /* If input_method->context doesn't exist, create context struct to send input_panel_show event to Input Method(IME) correctly.
1379 * Because input_panel_show event can be called before focus_in(activate) by application.
1380 * And Input Method(IME) should know the state of their own input_panel to manage their resource when the input_panel is shown. */
1381 if (input_method && (!input_method->context || !input_method->context->resource))
1382 _e_text_input_method_create_context(client, input_method, text_input, EINA_TRUE);
1384 if (input_method && input_method->resource && input_method->context && input_method->context->resource)
1386 /* DO NOT show input panel surface until we get message "show complete" from input method,
1387 * in order to give a change to update UI */
1388 LOGD("IM::SHOW::WAIT_FOR_READY\n");
1390 g_show_client = client;
1391 wl_input_method_send_show_input_panel(input_method->resource, input_method->context->resource);
1393 /* we need to force update in order to release buffer
1394 * if we do not, client can't update
1395 * because they may in manual render state by frame callback mechanism,
1396 * and also don't have released buffer */
1397 e_input_panel_wait_update_set(EINA_TRUE);
1401 e_input_panel_visibility_change(EINA_TRUE);
1403 /* If the input panel state was WILL_HIDE, it means that the conformant area information needs to be restored */
1404 if (g_input_panel_state == E_INPUT_PANEL_STATE_WILL_HIDE)
1406 if (text_input->resource)
1407 wl_text_input_send_private_command(text_input->resource, 0, "CONFORMANT_RESTORE");
1410 text_input->input_panel_visibile = EINA_TRUE;
1411 g_input_panel_state = E_INPUT_PANEL_STATE_WILL_SHOW;
1412 g_show_text_input = text_input;
1414 if (text_input->resource)
1416 int x = 0, y = 0, w = 0, h = 0;
1417 if (e_input_panel_client_geometry_get(NULL, &x, &y, &w, &h))
1418 _e_text_input_send_input_panel_geometry(text_input->resource, x, y, w, h);
1420 wl_text_input_send_input_panel_state(text_input->resource, WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW);
1423 e_input_panel_transient_for_set(client_surface_ec);
1427 _e_text_input_cb_input_panel_hide(struct wl_client *client, struct wl_resource *resource)
1429 if (g_show_client == client) {
1430 _input_panel_hide(client, resource, EINA_FALSE);
1431 g_show_text_input = NULL;
1432 g_show_client = NULL;
1437 _e_text_input_cb_reset(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
1439 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1440 E_Input_Method *input_method = NULL;
1441 Eina_List *l = NULL;
1445 WTI_WARNING(resource,
1446 WL_DISPLAY_ERROR_INVALID_OBJECT,
1447 "No Text Input For Resource");
1451 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1453 if (!input_method || !input_method->context) continue;
1454 if (input_method->context->resource)
1455 wl_input_method_context_send_reset(input_method->context->resource);
1460 _e_text_input_cb_content_type_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t hint, uint32_t purpose)
1462 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1463 E_Input_Method *input_method = NULL;
1464 Eina_List *l = NULL;
1468 WTI_WARNING(resource,
1469 WL_DISPLAY_ERROR_INVALID_OBJECT,
1470 "No Text Input For Resource");
1474 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1476 if (!input_method || !input_method->context) continue;
1478 if (input_method->context->resource)
1479 wl_input_method_context_send_content_type(input_method->context->resource,
1485 _e_text_input_cb_cursor_rectangle_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
1487 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1491 WTI_WARNING(resource,
1492 WL_DISPLAY_ERROR_INVALID_OBJECT,
1493 "No Text Input For Resource");
1497 /* TODO: issue event update input_panel */
1501 _e_text_input_cb_preferred_language_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *language)
1503 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1504 E_Input_Method *input_method = NULL;
1505 Eina_List *l = NULL;
1509 WTI_WARNING(resource,
1510 WL_DISPLAY_ERROR_INVALID_OBJECT,
1511 "No Text Input For Resource");
1515 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1517 if (!input_method || !input_method->context) continue;
1519 if (input_method->context->resource)
1520 wl_input_method_context_send_preferred_language(input_method->context->resource,
1526 _e_text_input_cb_state_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial)
1528 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1529 E_Input_Method *input_method = NULL;
1530 Eina_List *l = NULL;
1534 WTI_WARNING(resource,
1535 WL_DISPLAY_ERROR_INVALID_OBJECT,
1536 "No Text Input For Resource");
1540 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1542 if (!input_method || !input_method->context) continue;
1544 if (input_method->context->resource)
1545 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
1550 _e_text_input_cb_action_invoke(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t button, uint32_t index)
1552 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1553 E_Input_Method *input_method = NULL;
1554 Eina_List *l = NULL;
1558 WTI_WARNING(resource,
1559 WL_DISPLAY_ERROR_INVALID_OBJECT,
1560 "No Text Input For Resource");
1564 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1566 if (!input_method || !input_method->context) continue;
1568 if (input_method->context->resource)
1569 wl_input_method_context_send_invoke_action(input_method->context->resource,
1575 _e_text_input_cb_return_key_type_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t return_key_type)
1577 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1578 E_Input_Method *input_method = NULL;
1579 Eina_List *l = NULL;
1583 WTI_WARNING(resource,
1584 WL_DISPLAY_ERROR_INVALID_OBJECT,
1585 "No Text Input For Resource");
1589 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1591 if (!input_method || !input_method->context) continue;
1593 if (input_method->context->resource)
1594 wl_input_method_context_send_return_key_type(input_method->context->resource,
1600 _e_text_input_cb_return_key_disabled_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t disabled)
1602 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1603 E_Input_Method *input_method = NULL;
1604 Eina_List *l = NULL;
1608 WTI_WARNING(resource,
1609 WL_DISPLAY_ERROR_INVALID_OBJECT,
1610 "No Text Input For Resource");
1614 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1616 if (!input_method || !input_method->context) continue;
1618 if (input_method->context->resource)
1619 wl_input_method_context_send_return_key_disabled(input_method->context->resource,
1625 _e_text_input_cb_input_panel_data_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *data, uint32_t length)
1627 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1628 E_Input_Method *input_method = NULL;
1629 Eina_List *l = NULL;
1633 WTI_WARNING(resource,
1634 WL_DISPLAY_ERROR_INVALID_OBJECT,
1635 "No Text Input For Resource");
1639 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1641 if (!input_method || !input_method->context) continue;
1643 if (input_method->context->resource)
1644 wl_input_method_context_send_input_panel_data(input_method->context->resource,
1648 /* Temporarily receiving WILL_HIDE_ACK via input_panel_data, will need for a new wayland protocol */
1649 const char *szWillHideAck = "WILL_HIDE_ACK";
1650 if (strncmp(data, szWillHideAck, strlen(szWillHideAck)) == 0)
1652 if (g_timer_will_hide)
1654 ecore_timer_del(g_timer_will_hide);
1655 g_timer_will_hide = NULL;
1657 INF("WILL_HIDE_ACK_RECVED, %d", g_input_panel_state);
1658 if (g_input_panel_state == E_INPUT_PANEL_STATE_WILL_HIDE)
1660 e_input_panel_visibility_change(EINA_FALSE);
1661 e_input_panel_transient_for_set(NULL);
1662 g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
1668 _e_text_input_cb_bidi_direction_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t bidi_direction)
1670 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1671 E_Input_Method *input_method = NULL;
1672 Eina_List *l = NULL;
1676 WTI_WARNING(resource,
1677 WL_DISPLAY_ERROR_INVALID_OBJECT,
1678 "No Text Input For Resource");
1682 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1684 if (!input_method || !input_method->context) continue;
1686 if (input_method->context->resource)
1687 wl_input_method_context_send_bidi_direction(input_method->context->resource,
1693 _e_text_input_cb_cursor_position_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t cursor_position)
1695 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1696 E_Input_Method *input_method = NULL;
1697 Eina_List *l = NULL;
1701 WTI_WARNING(resource,
1702 WL_DISPLAY_ERROR_INVALID_OBJECT,
1703 "No Text Input For Resource");
1707 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1709 if (!input_method || !input_method->context) continue;
1711 if (input_method->context->resource)
1712 wl_input_method_context_send_cursor_position(input_method->context->resource, cursor_position);
1717 _e_text_input_cb_process_input_device_event(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t type, const char *data, uint32_t length)
1719 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1720 E_Input_Method *input_method = NULL;
1721 Eina_List *l = NULL;
1725 WTI_WARNING(resource,
1726 WL_DISPLAY_ERROR_INVALID_OBJECT,
1727 "No Text Input For Resource");
1731 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1733 if (!input_method || !input_method->context) continue;
1735 if (input_method->context->resource)
1736 wl_input_method_context_send_process_input_device_event(input_method->context->resource,
1737 type, data, length);
1742 _e_text_input_cb_filter_key_event(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,
1743 uint32_t serial, uint32_t time, const char *keyname, uint32_t state,
1744 uint32_t modifiers, const char *dev_name, uint32_t dev_class, uint32_t dev_subclass)
1747 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1748 E_Input_Method *input_method = NULL;
1752 WTI_WARNING(resource,
1753 WL_DISPLAY_ERROR_INVALID_OBJECT,
1754 "No Text Input For Resource");
1758 /* FIXME: should get input_method object from seat. */
1759 if (g_input_method && g_input_method->resource)
1760 input_method = wl_resource_get_user_data(g_input_method->resource);
1762 if (input_method && input_method->context && input_method->context->resource)
1763 wl_input_method_context_send_filter_key_event(input_method->context->resource,
1764 serial, time, keyname, state, modifiers,
1765 dev_name, dev_class, dev_subclass);
1769 _e_text_input_cb_get_hide_permission(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
1771 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1772 uint32_t permission = 1;
1773 E_Client *focused_ec = NULL;
1777 WTI_WARNING(resource,
1778 WL_DISPLAY_ERROR_INVALID_OBJECT,
1779 "No Text Input For Resource");
1783 focused_ec = e_client_focused_get();
1786 if (focused_ec != client_surface_ec)
1788 E_Window_Type focus_win_type = focused_ec->netwm.type;
1789 LOGD("Window ID : 0x%08x, Name : %s, type : %d\n", (unsigned int)e_client_util_win_get(focused_ec), (char *)e_client_util_name_get(focused_ec), focus_win_type);
1791 if (focus_win_type == E_WINDOW_TYPE_NOTIFICATION ||
1792 focus_win_type == E_WINDOW_TYPE_POPUP_MENU)
1798 LOGD("Can't get focus window\n");
1801 if (text_input->resource)
1802 wl_text_input_send_hide_permission(text_input->resource, permission);
1806 _e_text_input_cb_set_capital_mode(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t mode)
1808 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1809 E_Input_Method *input_method = NULL;
1810 Eina_List *l = NULL;
1814 WTI_WARNING(resource,
1815 WL_DISPLAY_ERROR_INVALID_OBJECT,
1816 "No Text Input For Resource");
1820 EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1822 if (!input_method || !input_method->context) continue;
1823 if (input_method->context->resource)
1824 wl_input_method_context_send_capital_mode(input_method->context->resource, mode);
1829 _e_text_input_cb_resource_destroy(struct wl_resource *resource)
1831 E_Text_Input *text_input = wl_resource_get_user_data(resource);
1832 E_Input_Method *input_method = NULL;
1836 WTI_WARNING(resource,
1837 WL_DISPLAY_ERROR_INVALID_OBJECT,
1838 "No Text Input For Resource");
1842 if (g_show_text_input == text_input)
1844 if (text_input->input_panel_visibile)
1846 _input_panel_hide(g_client, resource, EINA_TRUE);
1849 g_show_text_input = NULL;
1852 if (g_text_input == text_input)
1854 g_text_input = NULL;
1858 EINA_LIST_FREE(text_input->input_methods, input_method)
1860 _e_text_input_deactivate(text_input, input_method, EINA_TRUE);
1867 _e_text_input_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
1869 wl_resource_destroy(resource);
1872 static const struct wl_text_input_interface _e_text_input_implementation = {
1873 _e_text_input_cb_destroy,
1874 _e_text_input_cb_activate,
1875 _e_text_input_cb_deactivate,
1876 _e_text_input_cb_input_panel_show,
1877 _e_text_input_cb_input_panel_hide,
1878 _e_text_input_cb_reset,
1879 _e_text_input_cb_content_type_set,
1880 _e_text_input_cb_cursor_rectangle_set,
1881 _e_text_input_cb_preferred_language_set,
1882 _e_text_input_cb_state_commit,
1883 _e_text_input_cb_action_invoke,
1884 _e_text_input_cb_return_key_type_set,
1885 _e_text_input_cb_return_key_disabled_set,
1886 _e_text_input_cb_input_panel_data_set,
1887 _e_text_input_cb_bidi_direction_set,
1888 _e_text_input_cb_cursor_position_set,
1889 _e_text_input_cb_process_input_device_event,
1890 _e_text_input_cb_filter_key_event,
1891 _e_text_input_cb_get_hide_permission,
1892 _e_text_input_cb_set_capital_mode
1896 _e_text_input_manager_cb_text_input_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
1898 E_Text_Input_Mgr *text_input_mgr = wl_resource_get_user_data(resource);
1899 E_Text_Input *text_input = NULL;
1901 if (!text_input_mgr)
1903 WTI_WARNING(resource,
1904 WL_DISPLAY_ERROR_INVALID_OBJECT,
1905 "No Text Input Manager For Resource");
1909 if (!(text_input = E_NEW(E_Text_Input, 1)))
1911 wl_client_post_no_memory(client);
1912 ERR("Could not allocate space for Text_Input");
1916 text_input->resource =
1917 wl_resource_create(client, &wl_text_input_interface, 1, id);
1919 if (!text_input->resource)
1921 wl_client_post_no_memory(client);
1922 ERR("Could not create the resource for text_input");
1926 text_input->id = g_text_input_count++;
1928 wl_resource_set_implementation(text_input->resource,
1929 &_e_text_input_implementation,
1930 text_input, _e_text_input_cb_resource_destroy);
1933 static const struct wl_text_input_manager_interface _e_text_input_manager_implementation = {
1934 _e_text_input_manager_cb_text_input_create
1938 _e_text_cb_bind_text_input_manager(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
1940 E_Text_Input_Mgr *text_input_mgr = data;
1942 text_input_mgr->resource =
1943 wl_resource_create(client,
1944 &wl_text_input_manager_interface, 1, id);
1946 if (text_input_mgr->resource)
1947 wl_resource_set_implementation(text_input_mgr->resource,
1948 &_e_text_input_manager_implementation,
1949 text_input_mgr, NULL);
1953 _e_text_input_method_cb_unbind(struct wl_resource *resource)
1956 E_Input_Method *input_method = wl_resource_get_user_data(resource);
1960 WTI_WARNING(resource,
1961 WL_DISPLAY_ERROR_INVALID_OBJECT,
1962 "No Input Method For Resource");
1966 if (input_method->resource != resource) return;
1968 if (input_method->input)
1969 _e_text_input_deactivate(input_method->input, input_method, EINA_TRUE);
1971 input_method->resource = NULL;
1972 input_method->context = NULL;
1976 _e_text_input_method_cb_bind(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
1979 E_Input_Method *input_method = data;
1980 struct wl_resource *resource = NULL;
1982 if (!input_method) return;
1984 if (input_method->resource)
1985 _e_text_input_method_cb_unbind(input_method->resource);
1987 if (input_method->resource)
1989 WTI_WARNING(input_method->resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1990 "input_method object already bound");
1994 resource = wl_resource_create(client, &wl_input_method_interface, 1, id);
1995 if (EINA_UNLIKELY(!resource))
1998 input_method->resource = resource;
2000 wl_resource_set_implementation(resource, NULL, input_method,
2001 _e_text_input_method_cb_unbind);
2005 _e_text_input_method_destroy(void *data)
2007 E_Input_Method *input_method = data;
2012 if (input_method->global)
2013 wl_global_destroy(input_method->global);
2019 _e_text_input_method_create(void)
2021 if (!(g_input_method = E_NEW(E_Input_Method, 1)))
2023 ERR("Could not allocate space for Input_Method");
2027 g_input_method->global =
2028 wl_global_create(e_comp_wl->wl.disp, &wl_input_method_interface, 1,
2029 g_input_method, _e_text_input_method_cb_bind);
2031 if (!g_input_method->global)
2033 free(g_input_method);
2034 g_input_method = NULL;
2038 _e_mod_text_input_shutdown_cb_add(_e_text_input_method_destroy, g_input_method);
2044 _e_text_input_manager_destroy(void *data)
2046 E_Text_Input_Mgr *text_input_mgr = data;
2047 if (!text_input_mgr) return;
2049 wl_global_destroy(text_input_mgr->global);
2050 free(text_input_mgr);
2054 _e_text_input_manager_create(void)
2056 E_Text_Input_Mgr *text_input_mgr;
2058 if (!(text_input_mgr = E_NEW(E_Text_Input_Mgr, 1)))
2060 ERR("Could not allocate space for Text_Input_Manager");
2064 text_input_mgr->global =
2065 wl_global_create(e_comp_wl->wl.disp,
2066 &wl_text_input_manager_interface, 1,
2067 text_input_mgr, _e_text_cb_bind_text_input_manager);
2069 if (!text_input_mgr->global)
2071 free(text_input_mgr);
2075 _e_mod_text_input_shutdown_cb_add(_e_text_input_manager_destroy, text_input_mgr);
2081 _e_mod_text_input_shutdown(void)
2083 E_Mod_Text_Input_Shutdown_Cb *cb;
2085 EINA_LIST_FREE(shutdown_list, cb)
2095 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Text_Input" };
2098 set_soft_keyboard_mode()
2100 g_disable_show_panel = EINA_FALSE;
2102 /* switch to S/W keyboard mode */
2104 if (vconf_get_bool(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0 && val != 0)
2105 vconf_set_bool(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
2109 _e_mod_eeze_udev_watch_cb(const char *text, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch)
2111 if (event == EEZE_UDEV_EVENT_REMOVE)
2112 set_soft_keyboard_mode();
2116 _e_text_input_method_context_cb_client_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
2121 int x = 0, y = 0, w = 0, h = 0;
2123 ev = (E_Event_Client *)event;
2124 EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
2127 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, ECORE_CALLBACK_PASS_ON);
2129 found = e_input_panel_client_find(ec);
2130 if (!found) return ECORE_CALLBACK_PASS_ON;
2131 if ((ec->w < 1) && (ec->h < 1)) return ECORE_CALLBACK_PASS_ON;
2133 if (g_text_input && g_text_input->resource)
2135 if (e_input_panel_client_geometry_get(NULL, &x, &y, &w, &h))
2136 _e_text_input_send_input_panel_geometry(g_text_input->resource, x, y, w, h);
2139 return ECORE_CALLBACK_PASS_ON;
2143 _pol_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
2145 if (EINA_UNLIKELY(!ec))
2148 if (ec == client_surface_ec)
2150 LOGD("transient_for_ec deleted, hiding input panel\n");
2151 e_input_panel_visibility_change(EINA_FALSE);
2152 e_input_panel_transient_for_set(NULL);
2153 g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
2154 if (g_timer_will_hide)
2156 ecore_timer_del(g_timer_will_hide);
2157 g_timer_will_hide = NULL;
2159 client_surface_ec = NULL;
2160 LOGD("TRANSIENT_FOR::Reset transient_for_ec to NULL\n");
2165 e_modapi_init(E_Module *m)
2167 if (!e_comp_wl) return NULL;
2169 if (!wti_log_init())
2172 /* FIXME: create only one input method object per seat. */
2173 if (!_e_text_input_method_create())
2176 if (!e_input_panel_init())
2179 if (!_e_text_input_manager_create())
2182 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_RESIZE, _e_text_input_method_context_cb_client_resize, NULL);
2184 vconf_notify_key_changed(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, _keyboard_mode_changed_cb, NULL);
2185 vconf_notify_key_changed(VCONFKEY_LANGSET, _display_language_changed_cb, NULL);
2187 /* Find the current display language when initializing */
2188 _display_language_changed_cb(NULL, NULL);
2190 eeze_udev_watch_hander = eeze_udev_watch_add(EEZE_UDEV_TYPE_KEYBOARD,
2191 EEZE_UDEV_EVENT_REMOVE,
2192 _e_mod_eeze_udev_watch_cb,
2194 if (!eeze_udev_watch_hander)
2197 E_CLIENT_HOOK_APPEND(hooks_ec, E_CLIENT_HOOK_DEL, _pol_cb_hook_client_del, NULL);
2201 _e_mod_text_input_shutdown();
2206 e_modapi_shutdown(E_Module *m EINA_UNUSED)
2208 E_FREE_LIST(handlers, ecore_event_handler_del);
2209 E_FREE_LIST(hooks_ec, e_client_hook_del);
2211 if (g_timer_will_hide)
2213 ecore_timer_del(g_timer_will_hide);
2214 g_timer_will_hide = NULL;
2217 vconf_ignore_key_changed(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, _keyboard_mode_changed_cb);
2218 vconf_ignore_key_changed(VCONFKEY_LANGSET, _display_language_changed_cb);
2220 if (eeze_udev_watch_hander)
2222 eeze_udev_watch_del(eeze_udev_watch_hander);
2223 eeze_udev_watch_hander = NULL;
2225 _e_mod_text_input_shutdown();
2227 e_input_panel_shutdown();
2235 e_modapi_save(E_Module *m EINA_UNUSED)