71ddd9b1bdcbe7ea045a4bb9e0bc8739b4bff174
[platform/core/uifw/e-mod-tizen-wl-textinput.git] / src / e_mod_main.c
1 #define E_COMP_WL
2 #include "e.h"
3 #include "e_mod_main.h"
4 #include <text-server-protocol.h>
5 #include <input-method-server-protocol.h>
6 #include <vconf.h>
7 #include <vconf-keys.h>
8 #include <Eeze.h>
9 #include <Ecore_Wayland.h>
10 #include <dlog.h>
11 #include <stdlib.h>
12 #include <system_info.h>
13
14 #ifdef LOG_TAG
15 #undef LOG_TAG
16 #endif
17 #define LOG_TAG "WL_TEXTINPUT"
18
19 #define WTI_WARNING(resource, code, msg)     (_e_text_input_log_show((resource), (code), (msg), __func__))
20
21 tizen_profile_t _get_tizen_profile()
22 {
23    static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
24    if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
25      return profile;
26
27    char *profileName;
28    system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
29    switch (*profileName)
30      {
31       case 'm':
32       case 'M':
33          profile = TIZEN_PROFILE_MOBILE;
34          break;
35       case 'w':
36       case 'W':
37          profile = TIZEN_PROFILE_WEARABLE;
38          break;
39       case 't':
40       case 'T':
41          profile = TIZEN_PROFILE_TV;
42          break;
43       case 'i':
44       case 'I':
45          profile = TIZEN_PROFILE_IVI;
46          break;
47       default: // common or unknown ==> ALL ARE COMMON.
48          profile = TIZEN_PROFILE_COMMON;
49      }
50    free(profileName);
51
52    return profile;
53 }
54
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();
57
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;
63
64 struct _E_Text_Input
65 {
66    struct wl_resource *resource;
67
68    Eina_List *input_methods;
69    Eina_Bool input_panel_visibile;
70    uint32_t id;
71 };
72
73 struct _E_Text_Input_Mgr
74 {
75    struct wl_global *global;
76    struct wl_resource *resource;
77
78    Eina_List *text_input_list;
79 };
80
81 struct _E_Input_Method
82 {
83    struct wl_global *global;
84    struct wl_resource *resource;
85
86    E_Text_Input *input;
87    E_Input_Method_Context *context;
88 };
89
90 struct _E_Input_Method_Context
91 {
92    struct wl_resource *resource;
93
94    E_Text_Input *input;
95    E_Input_Method *input_method;
96
97 #if ENABLE_GRAB_KEYBOARD
98    struct
99    {
100       struct wl_resource *resource;
101       Eina_List *handlers;
102       Eina_Bool grabbed;
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;
107       int mod_changed;
108    } kbd;
109 #endif
110 };
111
112 struct _E_Mod_Text_Input_Shutdown_Cb
113 {
114    void (*func)(void *data);
115    void *data;
116 };
117
118 struct _E_Input_Method_Keymap_Info
119 {
120    const char *language;
121    const char *rules;
122    const char *models;
123    const char *layout;
124 };
125
126 enum _E_Input_Panel_State
127 {
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,
132 };
133
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;
150
151 static Eina_List *hooks_ec = NULL;
152
153 const int WILL_HIDE_TIMER_INTERVAL = 1.0f;
154
155 #undef E_CLIENT_HOOK_APPEND
156 #define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
157   do                                      \
158     {                                     \
159        E_Client_Hook *_h;                 \
160        _h = e_client_hook_add(t, cb, d);  \
161        assert(_h);                        \
162        l = eina_list_append(l, _h);       \
163     }                                     \
164   while (0)
165
166 static struct _E_Input_Method_Keymap_Info g_keymap_info[] = {
167    {"en_US", "evdev", "pc105", "us"},
168    {"ru_RU", "evdev", "pc105", "ru"},
169 };
170
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);
173
174 static void
175 _e_text_input_log_show(struct wl_resource *resource, uint32_t code, const char *msg, const char *warning_msg)
176 {
177    LOGE("%s() is failed. msg : %s\n", warning_msg, msg);
178 }
179
180 static void
181 _e_text_input_send_input_panel_geometry(struct wl_resource *resource, int x, int y, int w, int h)
182 {
183    int angle = 0;
184    char geometry[128];
185
186    if (client_surface_ec)
187      {
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;
191
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);
194      }
195
196    snprintf(geometry, sizeof(geometry), "%d,%d,%d,%d", x, y, w, h);
197
198    switch(angle)
199      {
200       case 90:
201       case 270:
202          vconf_set_str(VCONFKEY_ISF_IME_RECENT_LAND_GEOMETRY, geometry);
203          break;
204       default:
205          vconf_set_str(VCONFKEY_ISF_IME_RECENT_PORT_GEOMETRY, geometry);
206          break;
207      }
208
209    LOGD("angle : %d, x : %d, y : %d, w : %d, h : %d\n", angle, x, y, w, h);
210
211    wl_text_input_send_input_panel_geometry(resource, x, y, w, h);
212 }
213
214 static Eina_Bool
215 _will_hide_timer_handler(void *data)
216 {
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)
219      {
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;
223      }
224
225    if (g_timer_will_hide)
226      {
227         ecore_timer_del(g_timer_will_hide);
228         g_timer_will_hide = NULL;
229      }
230
231    return ECORE_CALLBACK_CANCEL;
232 }
233
234 static void
235 _input_panel_hide(struct wl_client *client, struct wl_resource *resource, Eina_Bool force_hide)
236 {
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;
240
241    if (!text_input)
242      {
243         WTI_WARNING(resource,
244                     WL_DISPLAY_ERROR_INVALID_OBJECT,
245                     "No Text Input For Resource");
246         return;
247      }
248
249    text_input->input_panel_visibile = EINA_FALSE;
250
251    if (text_input->resource)
252      {
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);
255      }
256
257    if (force_hide)
258      {
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;
262      }
263    else
264      {
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");
269
270         if (g_timer_will_hide)
271           {
272              ecore_timer_del(g_timer_will_hide);
273              g_timer_will_hide = NULL;
274           }
275         g_timer_will_hide = ecore_timer_add(WILL_HIDE_TIMER_INTERVAL, _will_hide_timer_handler, NULL);
276      }
277
278    if (g_input_method && g_input_method->resource)
279      input_method = wl_resource_get_user_data(g_input_method->resource);
280
281    /*
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.
285     */
286    if (input_method &&
287        ((!input_method->context) || (!input_method->context->resource)))
288      _context_created = _e_text_input_method_create_context(client, input_method, text_input, EINA_FALSE);
289
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);
292
293    if (_context_created)
294      _e_text_input_deactivate(text_input, input_method, EINA_FALSE);
295
296    e_input_panel_wait_update_set(EINA_FALSE);
297 }
298
299 static void
300 _keyboard_mode_changed_cb(keynode_t *key, void* data)
301 {
302    int val = 0;
303    if (vconf_get_bool(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0)
304      {
305         if (val == 0)
306           {
307              g_disable_show_panel = EINA_FALSE;
308           }
309         else
310           {
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;
314           }
315      }
316 }
317
318 static void
319 _display_language_changed_cb(keynode_t *key, void* data)
320 {
321    int loop;
322    char *language = vconf_get_str(VCONFKEY_LANGSET);
323
324    /* Just in case we did not find any matching language string */
325    g_keymap_index = 0;
326    if (language)
327      {
328         for (loop = 0; loop < sizeof(g_keymap_info) / sizeof(struct _E_Input_Method_Keymap_Info); loop++)
329           {
330              if (strncmp(language, g_keymap_info[loop].language, strlen(g_keymap_info[loop].language)) == 0)
331                {
332                   g_keymap_index = loop;
333                }
334           }
335         free(language);
336      }
337    /* We do not want to change the current keymap related behavior in TV profile for now */
338    if (!_TV)
339      {
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);
343      }
344    g_keyboard_mode_engligh = EINA_TRUE;
345 }
346
347 #if ENABLE_GRAB_KEYBOARD
348 static void
349 _e_text_input_method_context_keyboard_grab_keyboard_state_update(E_Input_Method_Context *context, uint32_t keycode, Eina_Bool pressed)
350 {
351    enum xkb_key_direction dir;
352
353    if (!context->kbd.state) return;
354
355    if (pressed) dir = XKB_KEY_DOWN;
356    else dir = XKB_KEY_UP;
357
358    context->kbd.mod_changed =
359      xkb_state_update_key(context->kbd.state, keycode + 8, dir);
360 }
361
362 static void
363 _e_text_input_method_context_keyboard_grab_keyboard_modifiers_update(E_Input_Method_Context *context, struct wl_resource *keyboard)
364 {
365    uint32_t serial;
366
367    if (!context->input) return;
368    if (!context->kbd.state) return;
369
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);
378
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);
385 }
386
387 static void
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)
389 {
390    uint32_t serial, nk;
391
392    if (!context->input) return;
393    nk = keycode - 8;
394
395    /* update modifier state */
396    _e_text_input_method_context_keyboard_grab_keyboard_state_update(context, nk, state == WL_KEYBOARD_KEY_STATE_PRESSED);
397
398    serial = wl_display_next_serial(e_comp_wl->wl.disp);
399
400    wl_keyboard_send_key(context->kbd.resource, serial, timestamp, nk, state);
401    if (context->kbd.mod_changed)
402      {
403         _e_text_input_method_context_keyboard_grab_keyboard_modifiers_update(context, context->kbd.resource);
404         context->kbd.mod_changed = 0;
405      }
406 }
407
408 static Eina_Bool
409 _e_text_input_method_context_filter_hotkeys(E_Input_Method_Context *context, Ecore_Event_Key *ev)
410 {
411    if (!ev) return EINA_FALSE;
412    if (!context) return EINA_FALSE;
413
414    /* We do not want to change the current keymap related behavior in TV profile for now */
415    if (!_TV)
416      {
417         const char *keyname_space = "space";
418         if ((strncmp(ev->keyname, keyname_space, strlen(keyname_space)) == 0) && (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT))
419           {
420              int keymap_index;
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;
426
427              return EINA_TRUE;
428           }
429      }
430    return EINA_FALSE;
431 }
432
433 static Eina_Bool
434 _e_text_input_method_context_ecore_cb_key_down(void *data, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
435 {
436    E_Input_Method_Context *context = data;
437
438    if (!_e_text_input_method_context_filter_hotkeys(context, ev))
439      {
440         _e_text_input_method_context_key_send(context, ev->keycode, ev->timestamp,
441                                               WL_KEYBOARD_KEY_STATE_PRESSED);
442      }
443
444    return ECORE_CALLBACK_RENEW;
445 }
446
447 static Eina_Bool
448 _e_text_input_method_context_ecore_cb_key_up(void *data, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
449 {
450    E_Input_Method_Context *context = data;
451
452    _e_text_input_method_context_key_send(context, ev->keycode, ev->timestamp,
453                                          WL_KEYBOARD_KEY_STATE_RELEASED);
454
455    return ECORE_CALLBACK_RENEW;
456 }
457
458 static void
459 _e_text_input_method_context_grab_set(E_Input_Method_Context *context, Eina_Bool set)
460 {
461    if (set == context->kbd.grabbed)
462      return;
463
464    if (!context->input)
465      return;
466
467    context->kbd.grabbed = set;
468
469    if (set)
470      {
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,
477                               context);
478         E_LIST_HANDLER_APPEND(context->kbd.handlers, ECORE_EVENT_KEY_UP,
479                               _e_text_input_method_context_ecore_cb_key_up,
480                               context);
481
482         e_comp_grab_input(0, 1);
483      }
484    else
485      {
486         E_FREE_LIST(context->kbd.handlers, ecore_event_handler_del);
487
488         e_comp_ungrab_input(0, 1);
489
490         if (context->kbd.keymap)
491           {
492              xkb_map_unref(context->kbd.keymap);
493              context->kbd.keymap = NULL;
494           }
495
496         if (context->kbd.state)
497           {
498              xkb_state_unref(context->kbd.state);
499              context->kbd.state = NULL;
500           }
501      }
502 }
503 #endif
504
505 static void
506 _e_mod_text_input_shutdown_cb_add(void (*func)(void *data), void *data)
507 {
508    E_Mod_Text_Input_Shutdown_Cb *cb;
509
510    if (!(cb = E_NEW(E_Mod_Text_Input_Shutdown_Cb, 1)))
511      {
512         ERR("Could not allocate space for Text Input Shutdown Callback");
513         return;
514      }
515
516    cb->func = func;
517    cb->data = data;
518
519    shutdown_list = eina_list_append(shutdown_list, cb);
520 }
521
522 static void
523 _e_text_input_method_context_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
524 {
525    wl_resource_destroy(resource);
526 }
527
528 static void
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)
530 {
531    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
532
533    if (!context)
534      {
535         WTI_WARNING(resource,
536                     WL_DISPLAY_ERROR_INVALID_OBJECT,
537                     "No Input Method Context For Resource");
538         return;
539      }
540
541    if ((context->input) && (context->input->resource))
542      wl_text_input_send_commit_string(context->input->resource,
543                                       serial, text);
544 }
545
546 static void
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)
548 {
549    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
550
551    if (!context)
552      {
553         WTI_WARNING(resource,
554                     WL_DISPLAY_ERROR_INVALID_OBJECT,
555                     "No Input Method Context For Resource");
556         return;
557      }
558
559    if ((context->input) && (context->input->resource))
560      wl_text_input_send_preedit_string(context->input->resource,
561                                        serial, text, commit);
562 }
563
564 static void
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)
566 {
567    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
568
569    if (!context)
570      {
571         WTI_WARNING(resource,
572                     WL_DISPLAY_ERROR_INVALID_OBJECT,
573                     "No Input Method Context For Resource");
574         return;
575      }
576
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);
580 }
581
582 static void
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)
584 {
585    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
586
587    if (!context)
588      {
589         WTI_WARNING(resource,
590                     WL_DISPLAY_ERROR_INVALID_OBJECT,
591                     "No Input Method Context For Resource");
592         return;
593      }
594
595    if ((context->input) && (context->input->resource))
596      wl_text_input_send_preedit_styling(context->input->resource,
597                                         index, length, style);
598 }
599
600 static void
601 _e_text_input_method_context_cb_preedit_cursor(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t cursor)
602 {
603    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
604
605    if (!context)
606      {
607         WTI_WARNING(resource,
608                     WL_DISPLAY_ERROR_INVALID_OBJECT,
609                     "No Input Method Context For Resource");
610         return;
611      }
612
613    if ((context->input) && (context->input->resource))
614      wl_text_input_send_preedit_cursor(context->input->resource,
615                                        cursor);
616 }
617
618 static void
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)
620 {
621    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
622
623    if (!context)
624      {
625         WTI_WARNING(resource,
626                     WL_DISPLAY_ERROR_INVALID_OBJECT,
627                     "No Input Method Context For Resource");
628         return;
629      }
630
631    if ((context->input) && (context->input->resource))
632      wl_text_input_send_delete_surrounding_text(context->input->resource,
633                                                 index, length);
634 }
635
636 static void
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)
638 {
639    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
640
641    if (!context)
642      {
643         WTI_WARNING(resource,
644                     WL_DISPLAY_ERROR_INVALID_OBJECT,
645                     "No Input Method Context For Resource");
646         return;
647      }
648
649    if ((context->input) && (context->input->resource))
650      wl_text_input_send_cursor_position(context->input->resource,
651                                         index, anchor);
652 }
653
654 static void
655 _e_text_input_method_context_cb_modifiers_map(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_array *map)
656 {
657    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
658
659    if (!context)
660      {
661         WTI_WARNING(resource,
662                     WL_DISPLAY_ERROR_INVALID_OBJECT,
663                     "No Input Method Context For Resource");
664         return;
665      }
666
667    if ((context->input) && (context->input->resource))
668      wl_text_input_send_modifiers_map(context->input->resource, map);
669 }
670
671 static void
672 _e_keyevent_free(void *data EINA_UNUSED, void *ev)
673 {
674    Ecore_Event_Key *e = ev;
675
676    if (e->keyname)
677      eina_stringshare_del(e->keyname);
678
679    if (e->key)
680      eina_stringshare_del(e->key);
681
682    if (e->compose)
683      eina_stringshare_del(e->compose);
684
685    if (e->string)
686      eina_stringshare_del(e->string);
687
688    E_FREE(e);
689 }
690
691 static void
692 feed_key_event(const char *keyname, const char *key, const char *string, int keycode, int state)
693 {
694    Ecore_Event_Key *e = E_NEW(Ecore_Event_Key, 1);
695    if (!e) return;
696
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);
701
702    e->timestamp = 0; /* For distinguishing S/W keyboard event */
703    e->same_screen = 1;
704    e->keycode = keycode;
705
706    ecore_event_add(state ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP, e, _e_keyevent_free, NULL);
707 }
708
709 static void
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)
711 {
712    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
713
714    if (!context)
715      {
716         WTI_WARNING(resource,
717                     WL_DISPLAY_ERROR_INVALID_OBJECT,
718                     "No Input Method Context For Resource");
719         return;
720      }
721
722    if ((context->input) && (context->input->resource))
723      {
724         wl_text_input_send_keysym(context->input->resource,
725                                   serial, time, sym, state, modifiers);
726      }
727    else
728      {
729         char string[32], key[32], keyname[32];
730
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);
735
736         if (strcmp(keyname, "BackSpace") == 0)
737           {
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));
742
743              memset(string, 0, sizeof(string));
744              xkb_keysym_to_utf8(sym, string, 32);
745
746              if (state)
747                {
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 */
751                }
752           }
753      }
754 }
755
756 #if ENABLE_GRAB_KEYBOARD
757 static void
758 _e_text_input_method_context_keyboard_grab_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
759 {
760    wl_resource_destroy(resource);
761 }
762
763 static const struct wl_keyboard_interface _e_keyboard_grab_interface =
764 {
765    _e_text_input_method_context_keyboard_grab_cb_resource_destroy
766 };
767
768 static void
769 _e_text_input_method_context_keyboard_grab_cb_keyboard_unbind(struct wl_resource *resource)
770 {
771    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
772
773    if (!context)
774      {
775         WTI_WARNING(resource,
776                     WL_DISPLAY_ERROR_INVALID_OBJECT,
777                     "No Input Method Context For Resource");
778         return;
779      }
780
781    _e_text_input_method_context_grab_set(context, EINA_FALSE);
782
783    context->kbd.resource = NULL;
784 }
785 #endif
786
787 static void
788 _e_text_input_method_context_cb_keyboard_grab(struct wl_client *client, struct wl_resource *resource, uint32_t id)
789 {
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;
794
795    if (!context)
796      {
797         WTI_WARNING(resource,
798                     WL_DISPLAY_ERROR_INVALID_OBJECT,
799                     "No Input Method Context For Resource");
800         return;
801      }
802
803    keyboard = wl_resource_create(client, &wl_keyboard_interface, 1, id);
804    if (!keyboard)
805      {
806         wl_client_post_no_memory(client);
807         return;
808      }
809
810    wl_resource_set_implementation(keyboard, &_e_keyboard_grab_interface, context, _e_text_input_method_context_keyboard_grab_cb_keyboard_unbind);
811
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);
815
816    context->kbd.resource = keyboard;
817
818    _e_text_input_method_context_grab_set(context, EINA_TRUE);
819 #endif
820 }
821
822 static void
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)
824 {
825    DBG("Input Method Context - key %d", wl_resource_get_id(resource));
826
827    (void)client;
828    (void)resource;
829    (void)serial;
830    (void)time;
831    (void)key;
832    (void)state_w;
833 }
834
835 static void
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)
837 {
838    DBG("Input Method Context - modifiers %d", wl_resource_get_id(resource));
839
840    (void)client;
841    (void)resource;
842    (void)serial;
843    (void)mods_depressed;
844    (void)mods_latched;
845    (void)mods_locked;
846    (void)group;
847 }
848
849 static void
850 _e_text_input_method_context_cb_language(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *language)
851 {
852    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
853
854    if (!context)
855      {
856         WTI_WARNING(resource,
857                     WL_DISPLAY_ERROR_INVALID_OBJECT,
858                     "No Input Method Context For Resource");
859         return;
860      }
861
862    if ((context->input) && (context->input->resource))
863      wl_text_input_send_language(context->input->resource,
864                                  serial, language);
865 }
866
867 static void
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)
869 {
870    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
871
872    if (!context)
873      {
874         WTI_WARNING(resource,
875                     WL_DISPLAY_ERROR_INVALID_OBJECT,
876                     "No Input Method Context For Resource");
877         return;
878      }
879
880    if ((context->input) && (context->input->resource))
881      wl_text_input_send_text_direction(context->input->resource,
882                                        serial, direction);
883 }
884
885 static void
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)
887 {
888    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
889
890    if (!context)
891      {
892         WTI_WARNING(resource,
893                     WL_DISPLAY_ERROR_INVALID_OBJECT,
894                     "No Input Method Context For Resource");
895         return;
896      }
897
898    if ((context->input) && (context->input->resource))
899      wl_text_input_send_selection_region(context->input->resource,
900                                          serial, start, end);
901 }
902
903 static void
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)
905 {
906    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
907
908    if (!context)
909      {
910         WTI_WARNING(resource,
911                     WL_DISPLAY_ERROR_INVALID_OBJECT,
912                     "No Input Method Context For Resource");
913         return;
914      }
915
916    if ((context->input) && (context->input->resource))
917      wl_text_input_send_private_command(context->input->resource,
918                                         serial, command);
919 }
920
921 static void
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)
923 {
924    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
925
926    if (!context)
927      {
928         WTI_WARNING(resource,
929                     WL_DISPLAY_ERROR_INVALID_OBJECT,
930                     "No Input Method Context For Resource");
931         return;
932      }
933
934    if ((context->input) && (context->input->resource))
935      wl_text_input_send_input_panel_data(context->input->resource,
936                                          serial, data, length);
937 }
938
939 static void
940 _e_text_input_method_context_cb_hide_input_panel(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial)
941 {
942    E_Text_Input *text_input = g_text_input;
943    E_Input_Method *input_method = NULL;
944
945    if (!text_input)
946      {
947         WTI_WARNING(resource,
948                     WL_DISPLAY_ERROR_INVALID_OBJECT,
949                     "No Text Input For Resource");
950         return;
951      }
952
953    text_input->input_panel_visibile = EINA_FALSE;
954
955    if (g_text_input && g_text_input->resource && g_client)
956      _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
957
958    if (g_input_method && g_input_method->resource)
959      input_method = wl_resource_get_user_data(g_input_method->resource);
960
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);
963 }
964
965 static void
966 _e_text_input_method_context_cb_get_selection_text(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t fd)
967 {
968    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
969
970    if (!context)
971      {
972         WTI_WARNING(resource,
973                     WL_DISPLAY_ERROR_INVALID_OBJECT,
974                     "No Input Method Context For Resource");
975         close (fd);
976         return;
977      }
978
979    if ((context->input) && (context->input->resource))
980      wl_text_input_send_get_selection_text(context->input->resource, fd);
981
982    close (fd);
983 }
984
985 static void
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)
988 {
989    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
990
991    if (!context)
992      {
993         WTI_WARNING(resource,
994                     WL_DISPLAY_ERROR_INVALID_OBJECT,
995                     "No Input Method Context For Resource");
996         close (fd);
997         return;
998      }
999
1000    if ((context->input) && (context->input->resource))
1001      wl_text_input_send_get_surrounding_text(context->input->resource, maxlen_before, maxlen_after, fd);
1002
1003    close (fd);
1004 }
1005
1006 static void
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)
1009 {
1010     E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1011
1012     if (!context)
1013       {
1014          WTI_WARNING(resource,
1015                      WL_DISPLAY_ERROR_INVALID_OBJECT,
1016                      "No Input Method Context For Resource");
1017          return;
1018       }
1019
1020     if ((context->input) && (context->input->resource))
1021       wl_text_input_send_filter_key_event_done(context->input->resource,
1022                                           serial, state);
1023 }
1024
1025 static void
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)
1028 {
1029     E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1030
1031     if (!context)
1032       {
1033          WTI_WARNING(resource,
1034                      WL_DISPLAY_ERROR_INVALID_OBJECT,
1035                      "No Input Method Context For Resource");
1036          return;
1037       }
1038
1039     if ((context->input) && (context->input->resource))
1040       _e_text_input_send_input_panel_geometry(context->input->resource, x, y, width, height);
1041
1042 }
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
1067 };
1068
1069 static void
1070 _e_text_input_method_context_cb_resource_destroy(struct wl_resource *resource)
1071 {
1072    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1073
1074    if (!context)
1075      {
1076         WTI_WARNING(resource,
1077                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1078                     "No Input Method Context For Resource");
1079         return;
1080      }
1081
1082 #if ENABLE_GRAB_KEYBOARD
1083    if (context->kbd.resource)
1084      wl_resource_destroy(context->kbd.resource);
1085 #endif
1086
1087    if ((context->input_method) &&
1088        (context->input_method->context == context))
1089      context->input_method->context = NULL;
1090
1091    free(context);
1092 }
1093
1094 static Eina_Bool is_number_key(const char *str)
1095  {
1096     if (!str) return EINA_FALSE;
1097
1098     int result = atoi(str);
1099
1100     if (result == 0)
1101       {
1102          if (!strcmp(str, "0"))
1103            return EINA_TRUE;
1104          else
1105            return EINA_FALSE;
1106       }
1107     else
1108       return EINA_TRUE;
1109 }
1110
1111 static Eina_Bool
1112 _e_mod_ecore_key_down_cb(void *data, int type, void *event)
1113 {
1114    Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
1115
1116    if (g_disable_show_panel == EINA_TRUE)
1117      return ECORE_CALLBACK_PASS_ON;
1118
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;
1134
1135    if (g_text_input && g_text_input->resource && g_client)
1136      _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
1137
1138    g_disable_show_panel = EINA_TRUE;
1139
1140    return ECORE_CALLBACK_PASS_ON;
1141 }
1142
1143 static void
1144 _e_text_input_deactivate(E_Text_Input *text_input, E_Input_Method *input_method, Eina_Bool need_focus_in)
1145 {
1146    LOGD("text_input : %p\n", text_input);
1147
1148    if (text_input == g_text_input)
1149      {
1150         g_text_input = NULL;
1151         g_client = NULL;
1152      }
1153
1154    if (input_method->input == text_input)
1155      {
1156         if ((input_method->context) && (input_method->resource))
1157           {
1158 #if ENABLE_GRAB_KEYBOARD
1159              _e_text_input_method_context_grab_set(input_method->context,
1160                                                    EINA_FALSE);
1161 #endif
1162              /* TODO: finish the grab of keyboard. */
1163              wl_input_method_send_deactivate(input_method->resource,
1164                                              input_method->context->resource,
1165                                              need_focus_in);
1166           }
1167
1168         if (ecore_key_down_handler)
1169           {
1170              ecore_event_handler_del(ecore_key_down_handler);
1171              ecore_key_down_handler = NULL;
1172           }
1173
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;
1178
1179         text_input->input_methods = eina_list_remove(text_input->input_methods, input_method);
1180
1181         if (text_input->resource)
1182           wl_text_input_send_leave(text_input->resource);
1183
1184         if (_TV)
1185           g_disable_show_panel = EINA_FALSE;
1186      }
1187 }
1188
1189 static void
1190 _e_text_input_cb_activate(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, struct wl_resource *surface)
1191 {
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;
1196
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);
1201
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;
1207
1208    text_input = wl_resource_get_user_data(resource);
1209    g_text_input = text_input;
1210    g_client = client;
1211
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);
1215
1216    LOGD("text_input : %p\n", text_input);
1217
1218    old = input_method->input;
1219
1220    LOGD("old : %p, text_input : %p , %d", old, text_input, g_input_panel_state);
1221    if (old == text_input)
1222      return;
1223
1224    if (old)
1225      _e_text_input_deactivate(old, input_method, EINA_TRUE);
1226
1227    input_method->input = text_input;
1228    text_input->input_methods = eina_list_append(text_input->input_methods, input_method);
1229
1230    if (input_method->resource)
1231      {
1232         if (!(context = E_NEW(E_Input_Method_Context, 1)))
1233           {
1234              wl_client_post_no_memory(client);
1235              ERR("Could not allocate space for Input_Method_Context");
1236              return;
1237           }
1238
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,
1242                                                            NULL);
1243
1244         context->resource =
1245            wl_resource_create(wl_resource_get_client(input_method->resource),
1246                               &wl_input_method_context_interface, 1, 0);
1247
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);
1252
1253         context->input = text_input;
1254         context->input_method = input_method;
1255         input_method->context = context;
1256
1257         if (context->resource)
1258           wl_input_method_send_activate(input_method->resource, context->resource, text_input->id, EINA_TRUE);
1259      }
1260
1261    if (_TV)
1262      set_soft_keyboard_mode();
1263
1264    if (text_input->resource)
1265      wl_text_input_send_enter(text_input->resource, surface);
1266
1267    return;
1268
1269 err:
1270    if (resource)
1271      WTI_WARNING(resource,
1272                  WL_DISPLAY_ERROR_INVALID_OBJECT,
1273                  "No Text Input For Resource");
1274
1275    if (seat)
1276      WTI_WARNING(seat,
1277                  WL_DISPLAY_ERROR_INVALID_OBJECT,
1278                  "No Comp Data For Seat");
1279 }
1280
1281 static void
1282 _e_text_input_cb_deactivate(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat)
1283 {
1284    LOGD("");
1285    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1286    E_Input_Method *input_method = NULL;
1287
1288    if (!text_input)
1289      {
1290         WTI_WARNING(resource,
1291                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1292                     "No Text Input For Resource");
1293         return;
1294      }
1295
1296    if (text_input == g_text_input)
1297      {
1298         g_text_input = NULL;
1299         g_client = NULL;
1300      }
1301
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);
1305
1306    if (!input_method)
1307      {
1308         WTI_WARNING(seat,
1309                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1310                     "No Input Method For Seat");
1311         return;
1312      }
1313
1314    _e_text_input_deactivate(text_input, input_method, EINA_TRUE);
1315 }
1316
1317 static Eina_Bool
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)
1319 {
1320    E_Input_Method_Context *context = NULL;
1321
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);
1325
1326    g_text_input = text_input;
1327    g_client = client;
1328    input_method->input = text_input;
1329    text_input->input_methods = eina_list_append(text_input->input_methods, input_method);
1330
1331    if (!(context = E_NEW(E_Input_Method_Context, 1)))
1332      {
1333         wl_client_post_no_memory(client);
1334         ERR("Could not allocate space for Input_Method_Context");
1335         return EINA_FALSE;
1336      }
1337
1338    context->resource =
1339       wl_resource_create(wl_resource_get_client(input_method->resource),
1340                          &wl_input_method_context_interface, 1, 0);
1341
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);
1346
1347    context->input = text_input;
1348    context->input_method = input_method;
1349    input_method->context = context;
1350
1351    wl_input_method_send_activate(input_method->resource, context->resource, text_input->id, need_focus_out);
1352
1353    return EINA_TRUE;
1354 }
1355
1356 static void
1357 _e_text_input_cb_input_panel_show(struct wl_client *client, struct wl_resource *resource)
1358 {
1359    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1360    E_Input_Method *input_method = NULL;
1361
1362    LOGD("text_input : %p\n", text_input);
1363
1364    if (!text_input)
1365      {
1366         WTI_WARNING(resource,
1367                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1368                     "No Text Input For Resource");
1369         return;
1370      }
1371
1372    if (g_disable_show_panel == EINA_TRUE)
1373      return;
1374
1375    if (g_input_method && g_input_method->resource)
1376      input_method = wl_resource_get_user_data(g_input_method->resource);
1377
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);
1383
1384    if (input_method && input_method->resource && input_method->context && input_method->context->resource)
1385      {
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");
1389
1390         g_show_client = client;
1391         wl_input_method_send_show_input_panel(input_method->resource, input_method->context->resource);
1392
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);
1398      }
1399
1400    if (_TV)
1401      e_input_panel_visibility_change(EINA_TRUE);
1402
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)
1405      {
1406         if (text_input->resource)
1407           wl_text_input_send_private_command(text_input->resource, 0, "CONFORMANT_RESTORE");
1408      }
1409
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;
1413
1414    if (text_input->resource)
1415      {
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);
1419
1420         wl_text_input_send_input_panel_state(text_input->resource, WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW);
1421      }
1422
1423    e_input_panel_transient_for_set(client_surface_ec);
1424 }
1425
1426 static void
1427 _e_text_input_cb_input_panel_hide(struct wl_client *client, struct wl_resource *resource)
1428 {
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;
1433    }
1434 }
1435
1436 static void
1437 _e_text_input_cb_reset(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
1438 {
1439    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1440    E_Input_Method *input_method = NULL;
1441    Eina_List *l = NULL;
1442
1443    if (!text_input)
1444      {
1445         WTI_WARNING(resource,
1446                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1447                     "No Text Input For Resource");
1448         return;
1449      }
1450
1451    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1452      {
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);
1456      }
1457 }
1458
1459 static void
1460 _e_text_input_cb_content_type_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t hint, uint32_t purpose)
1461 {
1462    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1463    E_Input_Method *input_method = NULL;
1464    Eina_List *l = NULL;
1465
1466    if (!text_input)
1467      {
1468         WTI_WARNING(resource,
1469                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1470                     "No Text Input For Resource");
1471         return;
1472      }
1473
1474    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1475      {
1476         if (!input_method || !input_method->context) continue;
1477
1478         if (input_method->context->resource)
1479           wl_input_method_context_send_content_type(input_method->context->resource,
1480                                                     hint, purpose);
1481      }
1482 }
1483
1484 static void
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)
1486 {
1487    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1488
1489    if (!text_input)
1490      {
1491         WTI_WARNING(resource,
1492                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1493                     "No Text Input For Resource");
1494         return;
1495      }
1496
1497    /* TODO: issue event update input_panel */
1498 }
1499
1500 static void
1501 _e_text_input_cb_preferred_language_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *language)
1502 {
1503    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1504    E_Input_Method *input_method = NULL;
1505    Eina_List *l = NULL;
1506
1507    if (!text_input)
1508      {
1509         WTI_WARNING(resource,
1510                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1511                     "No Text Input For Resource");
1512         return;
1513      }
1514
1515    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1516      {
1517         if (!input_method || !input_method->context) continue;
1518
1519         if (input_method->context->resource)
1520           wl_input_method_context_send_preferred_language(input_method->context->resource,
1521                                                           language);
1522      }
1523 }
1524
1525 static void
1526 _e_text_input_cb_state_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial)
1527 {
1528    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1529    E_Input_Method *input_method = NULL;
1530    Eina_List *l = NULL;
1531
1532    if (!text_input)
1533      {
1534         WTI_WARNING(resource,
1535                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1536                     "No Text Input For Resource");
1537         return;
1538      }
1539
1540    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1541      {
1542         if (!input_method || !input_method->context) continue;
1543
1544         if (input_method->context->resource)
1545           wl_input_method_context_send_commit_state(input_method->context->resource, serial);
1546      }
1547 }
1548
1549 static void
1550 _e_text_input_cb_action_invoke(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t button, uint32_t index)
1551 {
1552    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1553    E_Input_Method *input_method = NULL;
1554    Eina_List *l = NULL;
1555
1556    if (!text_input)
1557      {
1558         WTI_WARNING(resource,
1559                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1560                     "No Text Input For Resource");
1561         return;
1562      }
1563
1564    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1565      {
1566         if (!input_method || !input_method->context) continue;
1567
1568         if (input_method->context->resource)
1569           wl_input_method_context_send_invoke_action(input_method->context->resource,
1570                                                      button, index);
1571      }
1572 }
1573
1574 static void
1575 _e_text_input_cb_return_key_type_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t return_key_type)
1576 {
1577    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1578    E_Input_Method *input_method = NULL;
1579    Eina_List *l = NULL;
1580
1581    if (!text_input)
1582      {
1583         WTI_WARNING(resource,
1584                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1585                     "No Text Input For Resource");
1586         return;
1587      }
1588
1589    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1590      {
1591         if (!input_method || !input_method->context) continue;
1592
1593         if (input_method->context->resource)
1594           wl_input_method_context_send_return_key_type(input_method->context->resource,
1595                                                        return_key_type);
1596      }
1597 }
1598
1599 static void
1600 _e_text_input_cb_return_key_disabled_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t disabled)
1601 {
1602    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1603    E_Input_Method *input_method = NULL;
1604    Eina_List *l = NULL;
1605
1606    if (!text_input)
1607      {
1608         WTI_WARNING(resource,
1609                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1610                     "No Text Input For Resource");
1611         return;
1612      }
1613
1614    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1615      {
1616         if (!input_method || !input_method->context) continue;
1617
1618         if (input_method->context->resource)
1619           wl_input_method_context_send_return_key_disabled(input_method->context->resource,
1620                                                            disabled);
1621      }
1622 }
1623
1624 static void
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)
1626 {
1627    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1628    E_Input_Method *input_method = NULL;
1629    Eina_List *l = NULL;
1630
1631    if (!text_input)
1632      {
1633         WTI_WARNING(resource,
1634                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1635                     "No Text Input For Resource");
1636         return;
1637      }
1638
1639    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1640      {
1641         if (!input_method || !input_method->context) continue;
1642
1643         if (input_method->context->resource)
1644           wl_input_method_context_send_input_panel_data(input_method->context->resource,
1645                                                         data, length);
1646      }
1647
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)
1651      {
1652         if (g_timer_will_hide)
1653           {
1654              ecore_timer_del(g_timer_will_hide);
1655              g_timer_will_hide = NULL;
1656           }
1657         INF("WILL_HIDE_ACK_RECVED, %d", g_input_panel_state);
1658         if (g_input_panel_state == E_INPUT_PANEL_STATE_WILL_HIDE)
1659           {
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;
1663           }
1664      }
1665 }
1666
1667 static void
1668 _e_text_input_cb_bidi_direction_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t bidi_direction)
1669 {
1670    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1671    E_Input_Method *input_method = NULL;
1672    Eina_List *l = NULL;
1673
1674    if (!text_input)
1675      {
1676         WTI_WARNING(resource,
1677                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1678                     "No Text Input For Resource");
1679         return;
1680      }
1681
1682    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1683      {
1684         if (!input_method || !input_method->context) continue;
1685
1686         if (input_method->context->resource)
1687           wl_input_method_context_send_bidi_direction(input_method->context->resource,
1688                                                        bidi_direction);
1689      }
1690 }
1691
1692 static void
1693 _e_text_input_cb_cursor_position_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,  uint32_t cursor_position)
1694 {
1695    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1696    E_Input_Method *input_method = NULL;
1697    Eina_List *l = NULL;
1698
1699    if (!text_input)
1700      {
1701         WTI_WARNING(resource,
1702                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1703                     "No Text Input For Resource");
1704         return;
1705      }
1706
1707    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1708      {
1709         if (!input_method || !input_method->context) continue;
1710
1711         if (input_method->context->resource)
1712           wl_input_method_context_send_cursor_position(input_method->context->resource, cursor_position);
1713      }
1714 }
1715
1716 static void
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)
1718 {
1719    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1720    E_Input_Method *input_method = NULL;
1721    Eina_List *l = NULL;
1722
1723    if (!text_input)
1724      {
1725         WTI_WARNING(resource,
1726                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1727                     "No Text Input For Resource");
1728         return;
1729      }
1730
1731    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1732      {
1733         if (!input_method || !input_method->context) continue;
1734
1735         if (input_method->context->resource)
1736           wl_input_method_context_send_process_input_device_event(input_method->context->resource,
1737                                                                   type, data, length);
1738      }
1739 }
1740
1741 static void
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)
1745
1746 {
1747   E_Text_Input *text_input = wl_resource_get_user_data(resource);
1748   E_Input_Method *input_method = NULL;
1749
1750   if (!text_input)
1751     {
1752        WTI_WARNING(resource,
1753                    WL_DISPLAY_ERROR_INVALID_OBJECT,
1754                    "No Text Input For Resource");
1755        return;
1756     }
1757
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);
1761
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);
1766 }
1767
1768 static void
1769 _e_text_input_cb_get_hide_permission(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
1770 {
1771    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1772    uint32_t permission = 1;
1773    E_Client *focused_ec = NULL;
1774
1775    if (!text_input)
1776      {
1777         WTI_WARNING(resource,
1778                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1779                     "No Text Input For Resource");
1780         return;
1781      }
1782
1783    focused_ec = e_client_focused_get();
1784    if (focused_ec)
1785      {
1786         if (focused_ec != client_surface_ec)
1787           {
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);
1790
1791              if (focus_win_type == E_WINDOW_TYPE_NOTIFICATION ||
1792                  focus_win_type == E_WINDOW_TYPE_POPUP_MENU)
1793                permission = 0;
1794           }
1795      }
1796    else
1797      {
1798         LOGD("Can't get focus window\n");
1799      }
1800
1801    if (text_input->resource)
1802      wl_text_input_send_hide_permission(text_input->resource, permission);
1803 }
1804
1805 static void
1806 _e_text_input_cb_set_capital_mode(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t mode)
1807 {
1808    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1809    E_Input_Method *input_method = NULL;
1810    Eina_List *l = NULL;
1811
1812    if (!text_input)
1813      {
1814         WTI_WARNING(resource,
1815                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1816                     "No Text Input For Resource");
1817         return;
1818      }
1819
1820    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1821      {
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);
1825      }
1826 }
1827
1828 static void
1829 _e_text_input_cb_resource_destroy(struct wl_resource *resource)
1830 {
1831    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1832    E_Input_Method *input_method = NULL;
1833
1834    if (!text_input)
1835      {
1836         WTI_WARNING(resource,
1837                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1838                     "No Text Input For Resource");
1839         return;
1840      }
1841
1842    if (g_show_text_input == text_input)
1843      {
1844         if (text_input->input_panel_visibile)
1845           {
1846               _input_panel_hide(g_client, resource, EINA_TRUE);
1847           }
1848
1849         g_show_text_input = NULL;
1850      }
1851
1852    if (g_text_input == text_input)
1853      {
1854         g_text_input = NULL;
1855         g_client = NULL;
1856      }
1857
1858    EINA_LIST_FREE(text_input->input_methods, input_method)
1859      {
1860         _e_text_input_deactivate(text_input, input_method, EINA_TRUE);
1861      }
1862
1863    free(text_input);
1864 }
1865
1866 static void
1867 _e_text_input_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
1868 {
1869     wl_resource_destroy(resource);
1870 }
1871
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
1893 };
1894
1895 static void
1896 _e_text_input_manager_cb_text_input_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
1897 {
1898    E_Text_Input_Mgr *text_input_mgr = wl_resource_get_user_data(resource);
1899    E_Text_Input *text_input = NULL;
1900
1901    if (!text_input_mgr)
1902      {
1903         WTI_WARNING(resource,
1904                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1905                     "No Text Input Manager For Resource");
1906         return;
1907      }
1908
1909    if (!(text_input = E_NEW(E_Text_Input, 1)))
1910      {
1911         wl_client_post_no_memory(client);
1912         ERR("Could not allocate space for Text_Input");
1913         return;
1914      }
1915
1916    text_input->resource =
1917       wl_resource_create(client, &wl_text_input_interface, 1, id);
1918
1919    if (!text_input->resource)
1920      {
1921         wl_client_post_no_memory(client);
1922         ERR("Could not create the resource for text_input");
1923         free(text_input);
1924         return;
1925      }
1926    text_input->id = g_text_input_count++;
1927
1928    wl_resource_set_implementation(text_input->resource,
1929                                   &_e_text_input_implementation,
1930                                   text_input, _e_text_input_cb_resource_destroy);
1931 }
1932
1933 static const struct wl_text_input_manager_interface _e_text_input_manager_implementation = {
1934      _e_text_input_manager_cb_text_input_create
1935 };
1936
1937 static void
1938 _e_text_cb_bind_text_input_manager(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
1939 {
1940    E_Text_Input_Mgr *text_input_mgr = data;
1941
1942    text_input_mgr->resource =
1943       wl_resource_create(client,
1944                          &wl_text_input_manager_interface, 1, id);
1945
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);
1950 }
1951
1952 static void
1953 _e_text_input_method_cb_unbind(struct wl_resource *resource)
1954 {
1955    LOGD("");
1956    E_Input_Method *input_method = wl_resource_get_user_data(resource);
1957
1958    if (!input_method)
1959      {
1960         WTI_WARNING(resource,
1961                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1962                     "No Input Method For Resource");
1963         return;
1964      }
1965
1966    if (input_method->resource != resource) return;
1967
1968    if (input_method->input)
1969      _e_text_input_deactivate(input_method->input, input_method, EINA_TRUE);
1970
1971    input_method->resource = NULL;
1972    input_method->context = NULL;
1973 }
1974
1975 static void
1976 _e_text_input_method_cb_bind(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
1977 {
1978    LOGD("");
1979    E_Input_Method *input_method = data;
1980    struct wl_resource *resource = NULL;
1981
1982    if (!input_method) return;
1983
1984    if (input_method->resource)
1985      _e_text_input_method_cb_unbind(input_method->resource);
1986
1987    if (input_method->resource)
1988      {
1989         WTI_WARNING(input_method->resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1990                     "input_method object already bound");
1991         return;
1992      }
1993
1994    resource = wl_resource_create(client, &wl_input_method_interface, 1, id);
1995    if (EINA_UNLIKELY(!resource))
1996      return;
1997
1998    input_method->resource = resource;
1999
2000    wl_resource_set_implementation(resource, NULL, input_method,
2001                                   _e_text_input_method_cb_unbind);
2002 }
2003
2004 static void
2005 _e_text_input_method_destroy(void *data)
2006 {
2007    E_Input_Method *input_method = data;
2008
2009    if (!input_method)
2010      return;
2011
2012    if (input_method->global)
2013      wl_global_destroy(input_method->global);
2014
2015    free(input_method);
2016 }
2017
2018 static Eina_Bool
2019 _e_text_input_method_create(void)
2020 {
2021    if (!(g_input_method = E_NEW(E_Input_Method, 1)))
2022      {
2023         ERR("Could not allocate space for Input_Method");
2024         return EINA_FALSE;
2025      }
2026
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);
2030
2031    if (!g_input_method->global)
2032      {
2033         free(g_input_method);
2034         g_input_method = NULL;
2035         return EINA_FALSE;
2036      }
2037
2038    _e_mod_text_input_shutdown_cb_add(_e_text_input_method_destroy, g_input_method);
2039
2040    return EINA_TRUE;
2041 }
2042
2043 static void
2044 _e_text_input_manager_destroy(void *data)
2045 {
2046    E_Text_Input_Mgr *text_input_mgr = data;
2047    if (!text_input_mgr) return;
2048
2049    wl_global_destroy(text_input_mgr->global);
2050    free(text_input_mgr);
2051 }
2052
2053 static Eina_Bool
2054 _e_text_input_manager_create(void)
2055 {
2056    E_Text_Input_Mgr *text_input_mgr;
2057
2058    if (!(text_input_mgr = E_NEW(E_Text_Input_Mgr, 1)))
2059      {
2060         ERR("Could not allocate space for Text_Input_Manager");
2061         return EINA_FALSE;
2062      }
2063
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);
2068
2069    if (!text_input_mgr->global)
2070      {
2071         free(text_input_mgr);
2072         return EINA_FALSE;
2073      }
2074
2075    _e_mod_text_input_shutdown_cb_add(_e_text_input_manager_destroy, text_input_mgr);
2076
2077    return EINA_TRUE;
2078 }
2079
2080 static void
2081 _e_mod_text_input_shutdown(void)
2082 {
2083    E_Mod_Text_Input_Shutdown_Cb *cb;
2084
2085    EINA_LIST_FREE(shutdown_list, cb)
2086      {
2087         if (cb)
2088           {
2089              cb->func(cb->data);
2090              free(cb);
2091           }
2092      }
2093 }
2094
2095 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Text_Input" };
2096
2097 static void
2098 set_soft_keyboard_mode()
2099 {
2100    g_disable_show_panel = EINA_FALSE;
2101
2102    /* switch to S/W keyboard mode */
2103    int val = 0;
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);
2106 }
2107
2108 static void
2109 _e_mod_eeze_udev_watch_cb(const char *text, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch)
2110 {
2111    if (event == EEZE_UDEV_EVENT_REMOVE)
2112      set_soft_keyboard_mode();
2113 }
2114
2115 static Eina_Bool
2116 _e_text_input_method_context_cb_client_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
2117 {
2118    E_Event_Client *ev;
2119    E_Client *ec;
2120    Eina_Bool found;
2121    int x = 0, y = 0, w = 0, h = 0;
2122
2123    ev = (E_Event_Client *)event;
2124    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
2125
2126    ec = ev->ec;
2127    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, ECORE_CALLBACK_PASS_ON);
2128
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;
2132
2133    if (g_text_input && g_text_input->resource)
2134      {
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);
2137      }
2138
2139    return ECORE_CALLBACK_PASS_ON;
2140 }
2141
2142 static void
2143 _pol_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
2144 {
2145    if (EINA_UNLIKELY(!ec))
2146      return;
2147
2148    if (ec == client_surface_ec)
2149      {
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)
2155           {
2156              ecore_timer_del(g_timer_will_hide);
2157              g_timer_will_hide = NULL;
2158           }
2159         client_surface_ec = NULL;
2160         LOGD("TRANSIENT_FOR::Reset transient_for_ec to NULL\n");
2161      }
2162 }
2163
2164 E_API void *
2165 e_modapi_init(E_Module *m)
2166 {
2167    if (!e_comp_wl) return NULL;
2168
2169    if (!wti_log_init())
2170      return NULL;
2171
2172    /* FIXME: create only one input method object per seat. */
2173    if (!_e_text_input_method_create())
2174      return NULL;
2175
2176    if (!e_input_panel_init())
2177      goto err;
2178
2179    if (!_e_text_input_manager_create())
2180      goto err;
2181
2182    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_RESIZE, _e_text_input_method_context_cb_client_resize, NULL);
2183
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);
2186
2187    /* Find the current display language when initializing */
2188    _display_language_changed_cb(NULL, NULL);
2189
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,
2193                                                 NULL);
2194    if (!eeze_udev_watch_hander)
2195      goto err;
2196
2197    E_CLIENT_HOOK_APPEND(hooks_ec, E_CLIENT_HOOK_DEL, _pol_cb_hook_client_del, NULL);
2198
2199    return m;
2200 err:
2201    _e_mod_text_input_shutdown();
2202    return NULL;
2203 }
2204
2205 E_API int
2206 e_modapi_shutdown(E_Module *m EINA_UNUSED)
2207 {
2208    E_FREE_LIST(handlers, ecore_event_handler_del);
2209    E_FREE_LIST(hooks_ec, e_client_hook_del);
2210
2211    if (g_timer_will_hide)
2212      {
2213         ecore_timer_del(g_timer_will_hide);
2214         g_timer_will_hide = NULL;
2215      }
2216
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);
2219
2220    if (eeze_udev_watch_hander)
2221      {
2222         eeze_udev_watch_del(eeze_udev_watch_hander);
2223         eeze_udev_watch_hander = NULL;
2224      }
2225    _e_mod_text_input_shutdown();
2226
2227    e_input_panel_shutdown();
2228
2229    wti_log_shutdown();
2230
2231    return 1;
2232 }
2233
2234 E_API int
2235 e_modapi_save(E_Module *m EINA_UNUSED)
2236 {
2237    /* do nothing */
2238    return 1;
2239 }