ef7194873591064c02be4b0824c1d369524c387c
[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 <dlog.h>
10 #include <stdlib.h>
11 #include <system_info.h>
12
13 #ifdef LOG_TAG
14 #undef LOG_TAG
15 #endif
16 #define LOG_TAG "WL_TEXTINPUT"
17
18 #define WTI_WARNING(resource, code, msg)     (_e_text_input_log_show((resource), (code), (msg), __func__))
19
20 tizen_profile_t _get_tizen_profile()
21 {
22    static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
23    if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
24      return profile;
25
26    char *profileName;
27    system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
28    switch (*profileName)
29      {
30       case 'm':
31       case 'M':
32          profile = TIZEN_PROFILE_MOBILE;
33          break;
34       case 'w':
35       case 'W':
36          profile = TIZEN_PROFILE_WEARABLE;
37          break;
38       case 't':
39       case 'T':
40          profile = TIZEN_PROFILE_TV;
41          break;
42       case 'i':
43       case 'I':
44          profile = TIZEN_PROFILE_IVI;
45          break;
46       default: // common or unknown ==> ALL ARE COMMON.
47          profile = TIZEN_PROFILE_COMMON;
48      }
49    free(profileName);
50
51    return profile;
52 }
53
54 static Eina_Bool _e_text_input_method_context_cb_client_resize(void *data EINA_UNUSED, int type, void *event);
55 static void set_soft_keyboard_mode();
56
57 typedef struct _E_Text_Input E_Text_Input;
58 typedef struct _E_Text_Input_Mgr E_Text_Input_Mgr;
59 typedef struct _E_Input_Method E_Input_Method;
60 typedef struct _E_Input_Method_Context E_Input_Method_Context;
61 typedef struct _E_Mod_Text_Input_Shutdown_Cb E_Mod_Text_Input_Shutdown_Cb;
62
63 struct _E_Text_Input
64 {
65    struct wl_resource *resource;
66
67    Eina_List *input_methods;
68    Eina_Bool input_panel_visibile;
69    uint32_t id;
70 };
71
72 struct _E_Text_Input_Mgr
73 {
74    struct wl_global *global;
75    struct wl_resource *resource;
76
77    Eina_List *text_input_list;
78 };
79
80 struct _E_Input_Method
81 {
82    struct wl_global *global;
83    struct wl_resource *resource;
84
85    E_Text_Input *input;
86    E_Input_Method_Context *context;
87 };
88
89 struct _E_Input_Method_Context
90 {
91    struct wl_resource *resource;
92
93    E_Text_Input *input;
94    E_Input_Method *input_method;
95
96 #if ENABLE_GRAB_KEYBOARD
97    struct
98    {
99       struct wl_resource *resource;
100       Eina_List *handlers;
101       Eina_Bool grabbed;
102       struct xkb_keymap *keymap;
103       struct xkb_state *state;
104       xkb_mod_mask_t mod_depressed, mod_latched, mod_locked;
105       xkb_layout_index_t mod_group;
106       int mod_changed;
107    } kbd;
108 #endif
109 };
110
111 struct _E_Mod_Text_Input_Shutdown_Cb
112 {
113    void (*func)(void *data);
114    void *data;
115 };
116
117 /* This represents the overall input panel's state including the candidate area */
118 enum _E_Input_Panel_State
119 {
120     E_INPUT_PANEL_STATE_DID_HIDE,
121     E_INPUT_PANEL_STATE_WILL_HIDE,
122     E_INPUT_PANEL_STATE_DID_SHOW,
123     E_INPUT_PANEL_STATE_WILL_SHOW,
124 };
125
126 static E_Input_Method *g_input_method = NULL;
127 static E_Text_Input *g_text_input = NULL;
128 static struct wl_client *g_client = NULL;
129 static Eina_List *shutdown_list = NULL;
130 static Eina_Bool g_disable_show_panel = EINA_FALSE;
131 static Eeze_Udev_Watch *eeze_udev_watch_hander = NULL;
132 static Ecore_Event_Handler *ecore_key_down_handler = NULL;
133 static Eina_List *handlers = NULL;
134 static uint32_t g_text_input_count = 1;
135 static Ecore_Timer *g_timer_will_hide  = NULL;
136 static enum _E_Input_Panel_State g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
137 static E_Client *client_surface_ec = NULL;
138 static E_Text_Input *g_show_text_input = NULL;
139 static struct wl_client *g_show_client = NULL;
140 static Eina_Bool g_updated_geometry = EINA_FALSE;
141
142 /* The candidate's show state that was requested by the application or IME */
143 static Eina_Bool g_show_state_candidate = EINA_FALSE;
144
145 static Eina_List *hooks_ec = NULL;
146
147 const int WILL_HIDE_TIMER_INTERVAL = 1.0f;
148
149 #undef E_CLIENT_HOOK_APPEND
150 #define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
151   do                                      \
152     {                                     \
153        E_Client_Hook *_h;                 \
154        _h = e_client_hook_add(t, cb, d);  \
155        assert(_h);                        \
156        l = eina_list_append(l, _h);       \
157     }                                     \
158   while (0)
159
160 static void _e_text_input_cb_input_panel_show(struct wl_client *client, struct wl_resource *resource);
161 static void _e_text_input_deactivate(E_Text_Input *text_input, E_Input_Method *input_method, Eina_Bool need_focus_in);
162 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);
163
164 E_Client *
165 e_text_input_client_surface_get(void)
166 {
167    return client_surface_ec;
168 }
169
170 static void
171 _e_text_input_log_show(struct wl_resource *resource, uint32_t code, const char *msg, const char *warning_msg)
172 {
173    LOGE("%s() is failed. msg : %s\n", warning_msg, msg);
174 }
175
176 static void
177 _e_text_input_send_input_panel_geometry(struct wl_resource *resource, int x, int y, int w, int h)
178 {
179    int angle = 0;
180    char geometry[128];
181
182    if (client_surface_ec)
183      {
184         angle = client_surface_ec->e.state.rot.ang.next < 0 ?
185                 client_surface_ec->e.state.rot.ang.curr :
186                 client_surface_ec->e.state.rot.ang.next;
187
188         LOGD("curr : %d, next : %d, angle : %d\n", client_surface_ec->e.state.rot.ang.curr,
189            client_surface_ec->e.state.rot.ang.next, angle);
190      }
191
192    snprintf(geometry, sizeof(geometry), "%d,%d,%d,%d", x, y, w, h);
193
194    switch(angle)
195      {
196       case 90:
197       case 270:
198          vconf_set_str(VCONFKEY_ISF_IME_RECENT_LAND_GEOMETRY, geometry);
199          break;
200       default:
201          vconf_set_str(VCONFKEY_ISF_IME_RECENT_PORT_GEOMETRY, geometry);
202          break;
203      }
204
205    LOGD("angle : %d, x : %d, y : %d, w : %d, h : %d\n", angle, x, y, w, h);
206
207    wl_text_input_send_input_panel_geometry(resource, x, y, w, h);
208 }
209
210 static Eina_Bool
211 _will_hide_timer_handler(void *data)
212 {
213    INF("TIMED OUT while waiting for WILL_HIDE_ACK : %d", g_input_panel_state);
214    if (g_input_panel_state == E_INPUT_PANEL_STATE_WILL_HIDE)
215      {
216         e_input_panel_visibility_change(EINA_FALSE);
217         e_input_panel_transient_for_set(NULL);
218         g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
219      }
220
221    if (g_timer_will_hide)
222      {
223         ecore_timer_del(g_timer_will_hide);
224         g_timer_will_hide = NULL;
225      }
226
227    return ECORE_CALLBACK_CANCEL;
228 }
229
230 static void
231 _input_panel_hide(struct wl_client *client, struct wl_resource *resource, Eina_Bool force_hide)
232 {
233    E_Text_Input *text_input = wl_resource_get_user_data(resource);
234    E_Input_Method *input_method = NULL;
235    Eina_Bool _context_created = EINA_FALSE;
236    E_Zone *zone = NULL;
237    double timeout;
238
239    if (!text_input)
240      {
241         WTI_WARNING(resource,
242                     WL_DISPLAY_ERROR_INVALID_OBJECT,
243                     "No Text Input For Resource");
244         return;
245      }
246
247    text_input->input_panel_visibile = EINA_FALSE;
248
249    if (text_input->resource)
250      {
251         wl_text_input_send_input_panel_geometry(text_input->resource, 0, 0, 0, 0);
252         wl_text_input_send_input_panel_state(text_input->resource, WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE);
253      }
254
255    if (force_hide)
256      {
257         e_input_panel_visibility_change(EINA_FALSE);
258         e_input_panel_transient_for_set(NULL);
259         g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
260      }
261    else
262      {
263         g_input_panel_state = E_INPUT_PANEL_STATE_WILL_HIDE;
264         /* Temporarily sending private command, will need for a new wayland protocol */
265         if (text_input->resource)
266           wl_text_input_send_private_command(text_input->resource, 0, "CONFORMANT_RESET");
267
268         if (g_timer_will_hide)
269           {
270              ecore_timer_del(g_timer_will_hide);
271              g_timer_will_hide = NULL;
272           }
273
274         zone = e_zone_current_get();
275         if (zone && (zone->display_state == E_ZONE_DISPLAY_STATE_OFF))
276           timeout = 0.0f;
277         else
278           timeout = WILL_HIDE_TIMER_INTERVAL;
279         g_timer_will_hide = ecore_timer_add(timeout, _will_hide_timer_handler, NULL);
280      }
281
282    if (g_input_method && g_input_method->resource)
283      input_method = wl_resource_get_user_data(g_input_method->resource);
284
285    /*
286       If input_method->context is already deleted, create context struct again to send input_panel_hide event to Input Method(IME) correctly.
287       Because input_panel_hide event can be called after focus_out(deactivate) by application.
288       And Input Method(IME) should know the state of their own input_panel to manage their resource when the input_panel is hidden.
289     */
290    if (input_method &&
291        ((!input_method->context) || (!input_method->context->resource)))
292      _context_created = _e_text_input_method_create_context(client, input_method, text_input, EINA_FALSE);
293
294    if (input_method && input_method->resource && input_method->context && input_method->context->resource)
295      wl_input_method_send_hide_input_panel(input_method->resource, input_method->context->resource);
296
297    if (_context_created)
298      _e_text_input_deactivate(text_input, input_method, EINA_FALSE);
299
300    e_input_panel_wait_update_set(EINA_FALSE);
301
302    /* When the input panel suface is hidden, the candidate will hide too */
303    g_show_state_candidate = EINA_FALSE;
304 }
305
306 static void
307 _keyboard_mode_changed_cb(keynode_t *key, void* data)
308 {
309    bool val = vconf_keynode_get_bool(key);
310    LOGD("keyboard mode : %d\n", val);
311
312    if (val == false)
313      {
314 #ifdef SUPPORT_CANDIDATE_ONEWINDOW
315         /* Switching to S/W keyboard mode, hide input panel since it could be displaying candidate only */
316         if (g_disable_show_panel && g_text_input && g_text_input->resource && g_client)
317           _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
318 #endif
319         g_disable_show_panel = EINA_FALSE;
320      }
321    else
322      {
323 #ifdef SUPPORT_CANDIDATE_ONEWINDOW
324         /* Switching to H/W keyboard mode, hide input panel only if there is no candidate */
325         if (!g_show_state_candidate && g_text_input && g_text_input->resource && g_client)
326 #else
327         if (g_text_input && g_text_input->resource && g_client)
328 #endif
329           _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
330
331         g_disable_show_panel = EINA_TRUE;
332      }
333 }
334
335
336 #if ENABLE_GRAB_KEYBOARD
337 static void
338 _e_text_input_method_context_keyboard_grab_keyboard_state_update(E_Input_Method_Context *context, uint32_t keycode, Eina_Bool pressed)
339 {
340    enum xkb_key_direction dir;
341
342    if (!context->kbd.state) return;
343
344    if (pressed) dir = XKB_KEY_DOWN;
345    else dir = XKB_KEY_UP;
346
347    context->kbd.mod_changed =
348      xkb_state_update_key(context->kbd.state, keycode + 8, dir);
349 }
350
351 static void
352 _e_text_input_method_context_keyboard_grab_keyboard_modifiers_update(E_Input_Method_Context *context, struct wl_resource *keyboard)
353 {
354    uint32_t serial;
355
356    if (!context->input) return;
357    if (!context->kbd.state) return;
358
359    context->kbd.mod_depressed =
360      xkb_state_serialize_mods(context->kbd.state, XKB_STATE_DEPRESSED);
361    context->kbd.mod_latched =
362      xkb_state_serialize_mods(context->kbd.state, XKB_STATE_MODS_LATCHED);
363    context->kbd.mod_locked =
364      xkb_state_serialize_mods(context->kbd.state, XKB_STATE_MODS_LOCKED);
365    context->kbd.mod_group =
366      xkb_state_serialize_layout(context->kbd.state, XKB_STATE_LAYOUT_EFFECTIVE);
367
368    serial = wl_display_next_serial(e_comp_wl->wl.disp);
369    wl_keyboard_send_modifiers(keyboard, serial,
370                               context->kbd.mod_depressed,
371                               context->kbd.mod_latched,
372                               context->kbd.mod_locked,
373                               context->kbd.mod_group);
374 }
375
376 static void
377 _e_text_input_method_context_key_send(E_Input_Method_Context *context, unsigned int keycode, unsigned int timestamp, enum wl_keyboard_key_state state)
378 {
379    uint32_t serial, nk;
380
381    if (!context->input) return;
382    nk = keycode - 8;
383
384    /* update modifier state */
385    _e_text_input_method_context_keyboard_grab_keyboard_state_update(context, nk, state == WL_KEYBOARD_KEY_STATE_PRESSED);
386
387    serial = wl_display_next_serial(e_comp_wl->wl.disp);
388
389    wl_keyboard_send_key(context->kbd.resource, serial, timestamp, nk, state);
390    if (context->kbd.mod_changed)
391      {
392         _e_text_input_method_context_keyboard_grab_keyboard_modifiers_update(context, context->kbd.resource);
393         context->kbd.mod_changed = 0;
394      }
395 }
396
397 static Eina_Bool
398 _e_text_input_method_context_ecore_cb_key_down(void *data, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
399 {
400    E_Input_Method_Context *context = data;
401
402    _e_text_input_method_context_key_send(context, ev->keycode, ev->timestamp,
403                                          WL_KEYBOARD_KEY_STATE_PRESSED);
404
405    return ECORE_CALLBACK_RENEW;
406 }
407
408 static Eina_Bool
409 _e_text_input_method_context_ecore_cb_key_up(void *data, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
410 {
411    E_Input_Method_Context *context = data;
412
413    _e_text_input_method_context_key_send(context, ev->keycode, ev->timestamp,
414                                          WL_KEYBOARD_KEY_STATE_RELEASED);
415
416    return ECORE_CALLBACK_RENEW;
417 }
418
419 static void
420 _e_text_input_method_context_grab_set(E_Input_Method_Context *context, Eina_Bool set)
421 {
422    if (set == context->kbd.grabbed)
423      return;
424
425    if (!context->input)
426      return;
427
428    context->kbd.grabbed = set;
429
430    if (set)
431      {
432         if (context->kbd.keymap) xkb_map_unref(context->kbd.keymap);
433         if (context->kbd.state) xkb_state_unref(context->kbd.state);
434         context->kbd.keymap = xkb_map_ref(e_comp_wl->xkb.keymap);
435         context->kbd.state = xkb_state_new(e_comp_wl->xkb.keymap);
436         E_LIST_HANDLER_APPEND(context->kbd.handlers, ECORE_EVENT_KEY_DOWN,
437                               _e_text_input_method_context_ecore_cb_key_down,
438                               context);
439         E_LIST_HANDLER_APPEND(context->kbd.handlers, ECORE_EVENT_KEY_UP,
440                               _e_text_input_method_context_ecore_cb_key_up,
441                               context);
442
443         e_comp_grab_input(0, 1);
444      }
445    else
446      {
447         E_FREE_LIST(context->kbd.handlers, ecore_event_handler_del);
448
449         e_comp_ungrab_input(0, 1);
450
451         if (context->kbd.keymap)
452           {
453              xkb_map_unref(context->kbd.keymap);
454              context->kbd.keymap = NULL;
455           }
456
457         if (context->kbd.state)
458           {
459              xkb_state_unref(context->kbd.state);
460              context->kbd.state = NULL;
461           }
462      }
463 }
464 #endif
465
466 static void
467 _e_mod_text_input_shutdown_cb_add(void (*func)(void *data), void *data)
468 {
469    E_Mod_Text_Input_Shutdown_Cb *cb;
470
471    if (!(cb = E_NEW(E_Mod_Text_Input_Shutdown_Cb, 1)))
472      {
473         ERR("Could not allocate space for Text Input Shutdown Callback");
474         return;
475      }
476
477    cb->func = func;
478    cb->data = data;
479
480    shutdown_list = eina_list_append(shutdown_list, cb);
481 }
482
483 static void
484 _e_text_input_method_context_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
485 {
486    wl_resource_destroy(resource);
487 }
488
489 static void
490 _e_text_input_method_context_cb_string_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *text)
491 {
492    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
493
494    if (!context)
495      {
496         WTI_WARNING(resource,
497                     WL_DISPLAY_ERROR_INVALID_OBJECT,
498                     "No Input Method Context For Resource");
499         return;
500      }
501
502    if ((context->input) && (context->input->resource))
503      wl_text_input_send_commit_string(context->input->resource,
504                                       serial, text);
505 }
506
507 static void
508 _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)
509 {
510    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
511
512    if (!context)
513      {
514         WTI_WARNING(resource,
515                     WL_DISPLAY_ERROR_INVALID_OBJECT,
516                     "No Input Method Context For Resource");
517         return;
518      }
519
520    if ((context->input) && (context->input->resource))
521      wl_text_input_send_preedit_string(context->input->resource,
522                                        serial, text, commit);
523 }
524
525 static void
526 _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)
527 {
528    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
529
530    if (!context)
531      {
532         WTI_WARNING(resource,
533                     WL_DISPLAY_ERROR_INVALID_OBJECT,
534                     "No Input Method Context For Resource");
535         return;
536      }
537
538    if ((context->input) && (context->input->resource))
539      wl_text_input_send_recapture_string(context->input->resource,
540                                          serial, index, length, preedit, preedit_commit, commit);
541 }
542
543 static void
544 _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)
545 {
546    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
547
548    if (!context)
549      {
550         WTI_WARNING(resource,
551                     WL_DISPLAY_ERROR_INVALID_OBJECT,
552                     "No Input Method Context For Resource");
553         return;
554      }
555
556    if ((context->input) && (context->input->resource))
557      wl_text_input_send_preedit_styling(context->input->resource,
558                                         index, length, style);
559 }
560
561 static void
562 _e_text_input_method_context_cb_preedit_cursor(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t cursor)
563 {
564    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
565
566    if (!context)
567      {
568         WTI_WARNING(resource,
569                     WL_DISPLAY_ERROR_INVALID_OBJECT,
570                     "No Input Method Context For Resource");
571         return;
572      }
573
574    if ((context->input) && (context->input->resource))
575      wl_text_input_send_preedit_cursor(context->input->resource,
576                                        cursor);
577 }
578
579 static void
580 _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)
581 {
582    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
583
584    if (!context)
585      {
586         WTI_WARNING(resource,
587                     WL_DISPLAY_ERROR_INVALID_OBJECT,
588                     "No Input Method Context For Resource");
589         return;
590      }
591
592    if ((context->input) && (context->input->resource))
593      wl_text_input_send_delete_surrounding_text(context->input->resource,
594                                                 index, length);
595 }
596
597 static void
598 _e_text_input_method_context_cb_cursor_position(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t index, int32_t anchor)
599 {
600    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
601
602    if (!context)
603      {
604         WTI_WARNING(resource,
605                     WL_DISPLAY_ERROR_INVALID_OBJECT,
606                     "No Input Method Context For Resource");
607         return;
608      }
609
610    if ((context->input) && (context->input->resource))
611      wl_text_input_send_cursor_position(context->input->resource,
612                                         index, anchor);
613 }
614
615 static void
616 _e_text_input_method_context_cb_modifiers_map(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_array *map)
617 {
618    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
619
620    if (!context)
621      {
622         WTI_WARNING(resource,
623                     WL_DISPLAY_ERROR_INVALID_OBJECT,
624                     "No Input Method Context For Resource");
625         return;
626      }
627
628    if ((context->input) && (context->input->resource))
629      wl_text_input_send_modifiers_map(context->input->resource, map);
630 }
631
632 static void
633 _e_keyevent_free(void *data EINA_UNUSED, void *ev)
634 {
635    Ecore_Event_Key *e = ev;
636
637    if (e->keyname)
638      eina_stringshare_del(e->keyname);
639
640    if (e->key)
641      eina_stringshare_del(e->key);
642
643    if (e->compose)
644      eina_stringshare_del(e->compose);
645
646    if (e->string)
647      eina_stringshare_del(e->string);
648
649    E_FREE(e);
650 }
651
652 static void
653 feed_key_event(const char *keyname, const char *key, const char *string, int keycode, int state)
654 {
655    Ecore_Event_Key *e = E_NEW(Ecore_Event_Key, 1);
656    if (!e) return;
657
658    e->keyname = (char *)eina_stringshare_add(keyname);
659    e->key = (char *)eina_stringshare_add(key);
660    e->string = (char *)eina_stringshare_add(string);
661    e->compose = (char *)eina_stringshare_add(e->string);
662
663    e->timestamp = 0; /* For distinguishing S/W keyboard event */
664    e->same_screen = 1;
665    e->keycode = keycode;
666
667    ecore_event_add(state ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP, e, _e_keyevent_free, NULL);
668 }
669
670 static void
671 _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)
672 {
673    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
674
675    if (!context)
676      {
677         WTI_WARNING(resource,
678                     WL_DISPLAY_ERROR_INVALID_OBJECT,
679                     "No Input Method Context For Resource");
680         return;
681      }
682
683    if ((context->input) && (context->input->resource))
684      {
685         wl_text_input_send_keysym(context->input->resource,
686                                   serial, time, sym, state, modifiers);
687      }
688    else
689      {
690         char string[32], key[32], keyname[32];
691
692         memset(keyname, 0, sizeof(keyname));
693         xkb_keysym_get_name(sym, keyname, sizeof(keyname));
694         if (keyname[0] == '\0')
695           snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
696
697         if (strcmp(keyname, "BackSpace") == 0)
698           {
699              /* backspace key should be supported in the multibutton entry of elementary
700                 even though it losts focus */
701              memset(key, 0, sizeof(key));
702              xkb_keysym_get_name(sym, key, sizeof(key));
703
704              memset(string, 0, sizeof(string));
705              xkb_keysym_to_utf8(sym, string, 32);
706
707              if (state)
708                {
709                   /* Backspace keycode (22) */
710                   feed_key_event(keyname, key, string, 22, 1); /* key down */
711                   feed_key_event(keyname, key, string, 22, 0); /* key up */
712                }
713           }
714      }
715 }
716
717 #if ENABLE_GRAB_KEYBOARD
718 static void
719 _e_text_input_method_context_keyboard_grab_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
720 {
721    wl_resource_destroy(resource);
722 }
723
724 static const struct wl_keyboard_interface _e_keyboard_grab_interface =
725 {
726    _e_text_input_method_context_keyboard_grab_cb_resource_destroy
727 };
728
729 static void
730 _e_text_input_method_context_keyboard_grab_cb_keyboard_unbind(struct wl_resource *resource)
731 {
732    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
733
734    if (!context)
735      {
736         WTI_WARNING(resource,
737                     WL_DISPLAY_ERROR_INVALID_OBJECT,
738                     "No Input Method Context For Resource");
739         return;
740      }
741
742    _e_text_input_method_context_grab_set(context, EINA_FALSE);
743
744    context->kbd.resource = NULL;
745 }
746 #endif
747
748 static void
749 _e_text_input_method_context_cb_keyboard_grab(struct wl_client *client, struct wl_resource *resource, uint32_t id)
750 {
751    DBG("Input Method Context - grab keyboard %d", wl_resource_get_id(resource));
752 #if ENABLE_GRAB_KEYBOARD
753    E_Input_Method_Context *context  = wl_resource_get_user_data(resource);
754    struct wl_resource *keyboard = NULL;
755
756    if (!context)
757      {
758         WTI_WARNING(resource,
759                     WL_DISPLAY_ERROR_INVALID_OBJECT,
760                     "No Input Method Context For Resource");
761         return;
762      }
763
764    keyboard = wl_resource_create(client, &wl_keyboard_interface, 1, id);
765    if (!keyboard)
766      {
767         wl_client_post_no_memory(client);
768         return;
769      }
770
771    wl_resource_set_implementation(keyboard, &_e_keyboard_grab_interface, context, _e_text_input_method_context_keyboard_grab_cb_keyboard_unbind);
772
773    /* send current keymap */
774    wl_keyboard_send_keymap(keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
775                            e_comp_wl->xkb.fd, e_comp_wl->xkb.size);
776
777    context->kbd.resource = keyboard;
778
779    _e_text_input_method_context_grab_set(context, EINA_TRUE);
780 #endif
781 }
782
783 static void
784 _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)
785 {
786    DBG("Input Method Context - key %d", wl_resource_get_id(resource));
787
788    (void)client;
789    (void)resource;
790    (void)serial;
791    (void)time;
792    (void)key;
793    (void)state_w;
794 }
795
796 static void
797 _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)
798 {
799    DBG("Input Method Context - modifiers %d", wl_resource_get_id(resource));
800
801    (void)client;
802    (void)resource;
803    (void)serial;
804    (void)mods_depressed;
805    (void)mods_latched;
806    (void)mods_locked;
807    (void)group;
808 }
809
810 static void
811 _e_text_input_method_context_cb_language(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *language)
812 {
813    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
814
815    if (!context)
816      {
817         WTI_WARNING(resource,
818                     WL_DISPLAY_ERROR_INVALID_OBJECT,
819                     "No Input Method Context For Resource");
820         return;
821      }
822
823    if ((context->input) && (context->input->resource))
824      wl_text_input_send_language(context->input->resource,
825                                  serial, language);
826 }
827
828 static void
829 _e_text_input_method_context_cb_text_direction(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, uint32_t direction)
830 {
831    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
832
833    if (!context)
834      {
835         WTI_WARNING(resource,
836                     WL_DISPLAY_ERROR_INVALID_OBJECT,
837                     "No Input Method Context For Resource");
838         return;
839      }
840
841    if ((context->input) && (context->input->resource))
842      wl_text_input_send_text_direction(context->input->resource,
843                                        serial, direction);
844 }
845
846 static void
847 _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)
848 {
849    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
850
851    if (!context)
852      {
853         WTI_WARNING(resource,
854                     WL_DISPLAY_ERROR_INVALID_OBJECT,
855                     "No Input Method Context For Resource");
856         return;
857      }
858
859    if ((context->input) && (context->input->resource))
860      wl_text_input_send_selection_region(context->input->resource,
861                                          serial, start, end);
862 }
863
864 static void
865 _e_text_input_method_context_cb_private_command(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *command)
866 {
867    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
868
869    if (!context)
870      {
871         WTI_WARNING(resource,
872                     WL_DISPLAY_ERROR_INVALID_OBJECT,
873                     "No Input Method Context For Resource");
874         return;
875      }
876
877    if ((context->input) && (context->input->resource))
878      wl_text_input_send_private_command(context->input->resource,
879                                         serial, command);
880 }
881
882 static void
883 _e_text_input_method_context_cb_commit_content(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *content, const char *description, const char *mime_types)
884 {
885    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
886
887    if (!context)
888      {
889         WTI_WARNING(resource,
890                     WL_DISPLAY_ERROR_INVALID_OBJECT,
891                     "No Input Method Context For Resource");
892         return;
893      }
894
895    if ((context->input) && (context->input->resource))
896      wl_text_input_send_commit_content(context->input->resource,
897                                        serial, content, description, mime_types);
898 }
899
900 static void
901 _e_text_input_method_context_cb_input_panel_event(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, uint32_t event_type, uint32_t value)
902 {
903    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
904
905    if (!context)
906      {
907         WTI_WARNING(resource,
908                     WL_DISPLAY_ERROR_INVALID_OBJECT,
909                     "No Input Method Context For Resource");
910         return;
911      }
912
913    if ((context->input) && (context->input->resource))
914      wl_text_input_send_input_panel_event(context->input->resource,
915                                           serial, event_type, value);
916 }
917
918 static void
919 _e_text_input_method_context_cb_update_candidate_state(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t state)
920 {
921     E_Input_Method_Context *context = wl_resource_get_user_data(resource);
922
923     if (!context)
924       {
925          WTI_WARNING(resource,
926                      WL_DISPLAY_ERROR_INVALID_OBJECT,
927                      "No Input Method Context For Resource");
928          return;
929       }
930
931     LOGD("Candidate State : %d", state);
932     Eina_Bool prev_show_state = g_show_state_candidate;
933     g_show_state_candidate = state;
934     if (g_input_panel_state == E_INPUT_PANEL_STATE_DID_HIDE)
935       prev_show_state = EINA_FALSE;
936
937     if (!state)
938       {
939          /* If the candidate state has been changed to OFF when panel is not in show state, */
940          if (!g_show_state_candidate && prev_show_state && g_disable_show_panel && g_client && g_text_input)
941             _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
942       }
943     else
944       {
945          /* If the candidate state has been changed to ON when panel is not in show state */
946          if (g_show_state_candidate && !prev_show_state && g_disable_show_panel && g_client && g_text_input)
947             {
948                _e_text_input_cb_input_panel_show(g_client, g_text_input->resource);
949                int x = 0, y = 0, w = 0, h = 0;
950                if (e_input_panel_client_geometry_get(NULL, &x, &y, &w, &h) && !(w <= 1 || h <= 1))
951                  _e_text_input_send_input_panel_geometry(g_text_input->resource, x, y, w, h);
952             }
953       }
954 }
955
956 static void
957 _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)
958 {
959    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
960
961    if (!context)
962      {
963         WTI_WARNING(resource,
964                     WL_DISPLAY_ERROR_INVALID_OBJECT,
965                     "No Input Method Context For Resource");
966         return;
967      }
968
969    if ((context->input) && (context->input->resource))
970      wl_text_input_send_input_panel_data(context->input->resource,
971                                          serial, data, length);
972 }
973
974 static void
975 _e_text_input_method_context_cb_hide_input_panel(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial)
976 {
977    E_Text_Input *text_input = g_text_input;
978    E_Input_Method *input_method = NULL;
979
980    if (!text_input)
981      {
982         WTI_WARNING(resource,
983                     WL_DISPLAY_ERROR_INVALID_OBJECT,
984                     "No Text Input For Resource");
985         return;
986      }
987
988    text_input->input_panel_visibile = EINA_FALSE;
989
990    if (g_text_input && g_text_input->resource && g_client)
991      _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
992
993    if (g_input_method && g_input_method->resource)
994      input_method = wl_resource_get_user_data(g_input_method->resource);
995
996    if (input_method && input_method->resource && input_method->context && input_method->context->resource)
997      wl_input_method_send_hide_input_panel(input_method->resource, input_method->context->resource);
998 }
999
1000 static void
1001 _e_text_input_method_context_cb_get_selection_text(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t fd)
1002 {
1003    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1004
1005    if (!context)
1006      {
1007         WTI_WARNING(resource,
1008                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1009                     "No Input Method Context For Resource");
1010         close (fd);
1011         return;
1012      }
1013
1014    if ((context->input) && (context->input->resource))
1015      wl_text_input_send_get_selection_text(context->input->resource, fd);
1016
1017    close (fd);
1018 }
1019
1020 static void
1021 _e_text_input_method_context_cb_get_surrounding_text(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,
1022                                                      uint32_t maxlen_before, uint32_t maxlen_after, int32_t fd)
1023 {
1024    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1025
1026    if (!context)
1027      {
1028         WTI_WARNING(resource,
1029                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1030                     "No Input Method Context For Resource");
1031         close (fd);
1032         return;
1033      }
1034
1035    if ((context->input) && (context->input->resource))
1036      wl_text_input_send_get_surrounding_text(context->input->resource, maxlen_before, maxlen_after, fd);
1037
1038    close (fd);
1039 }
1040
1041 static void
1042 _e_text_input_method_context_cb_filter_key_event_done(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,
1043                                                       uint32_t serial, uint32_t state)
1044 {
1045     E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1046
1047     if (!context)
1048       {
1049          WTI_WARNING(resource,
1050                      WL_DISPLAY_ERROR_INVALID_OBJECT,
1051                      "No Input Method Context For Resource");
1052          return;
1053       }
1054
1055     if ((context->input) && (context->input->resource))
1056       wl_text_input_send_filter_key_event_done(context->input->resource,
1057                                           serial, state);
1058 }
1059
1060 static void
1061 _e_text_input_method_context_cb_update_ise_geometry(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,
1062                                                       uint32_t serial, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
1063 {
1064     E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1065
1066     if (!context)
1067       {
1068          WTI_WARNING(resource,
1069                      WL_DISPLAY_ERROR_INVALID_OBJECT,
1070                      "No Input Method Context For Resource");
1071          return;
1072       }
1073
1074     if ((context->input) && (context->input->resource))
1075       {
1076          _e_text_input_send_input_panel_geometry(context->input->resource, x, y, width, height);
1077          g_updated_geometry = EINA_TRUE;
1078       }
1079
1080 }
1081
1082 static void
1083 _e_text_input_method_context_cb_reshow_input_panel(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
1084 {
1085     e_input_panel_transient_for_set(client_surface_ec);
1086     e_input_panel_wait_update_set(EINA_TRUE);
1087 }
1088 static const struct wl_input_method_context_interface _e_text_input_method_context_implementation = {
1089      _e_text_input_method_context_cb_destroy,
1090      _e_text_input_method_context_cb_string_commit,
1091      _e_text_input_method_context_cb_preedit_string,
1092      _e_text_input_method_context_cb_preedit_styling,
1093      _e_text_input_method_context_cb_preedit_cursor,
1094      _e_text_input_method_context_cb_surrounding_text_delete,
1095      _e_text_input_method_context_cb_cursor_position,
1096      _e_text_input_method_context_cb_modifiers_map,
1097      _e_text_input_method_context_cb_keysym,
1098      _e_text_input_method_context_cb_keyboard_grab,
1099      _e_text_input_method_context_cb_key,
1100      _e_text_input_method_context_cb_modifiers,
1101      _e_text_input_method_context_cb_language,
1102      _e_text_input_method_context_cb_text_direction,
1103      _e_text_input_method_context_cb_selection_region,
1104      _e_text_input_method_context_cb_private_command,
1105      _e_text_input_method_context_cb_input_panel_data_update,
1106      _e_text_input_method_context_cb_hide_input_panel,
1107      _e_text_input_method_context_cb_get_selection_text,
1108      _e_text_input_method_context_cb_get_surrounding_text,
1109      _e_text_input_method_context_cb_filter_key_event_done,
1110      _e_text_input_method_context_cb_update_ise_geometry,
1111      _e_text_input_method_context_cb_recapture_string,
1112      _e_text_input_method_context_cb_input_panel_event,
1113      _e_text_input_method_context_cb_commit_content,
1114      _e_text_input_method_context_cb_update_candidate_state,
1115      _e_text_input_method_context_cb_reshow_input_panel,
1116 };
1117
1118 static void
1119 _e_text_input_method_context_cb_resource_destroy(struct wl_resource *resource)
1120 {
1121    E_Input_Method_Context *context = wl_resource_get_user_data(resource);
1122
1123    if (!context)
1124      {
1125         WTI_WARNING(resource,
1126                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1127                     "No Input Method Context For Resource");
1128         return;
1129      }
1130
1131 #if ENABLE_GRAB_KEYBOARD
1132    if (context->kbd.resource)
1133      wl_resource_destroy(context->kbd.resource);
1134 #endif
1135
1136    if ((context->input_method) &&
1137        (context->input_method->context == context))
1138      context->input_method->context = NULL;
1139
1140    free(context);
1141 }
1142
1143 static Eina_Bool is_number_key(const char *str)
1144  {
1145     if (!str) return EINA_FALSE;
1146
1147     int result = atoi(str);
1148
1149     if (result == 0)
1150       {
1151          if (!strcmp(str, "0"))
1152            return EINA_TRUE;
1153          else
1154            return EINA_FALSE;
1155       }
1156     else
1157       return EINA_TRUE;
1158 }
1159
1160 static Eina_Bool
1161 _e_mod_ecore_key_down_cb(void *data, int type, void *event)
1162 {
1163    Ecore_Event_Key *ev = (Ecore_Event_Key *)event;
1164
1165    if (g_disable_show_panel == EINA_TRUE)
1166      return ECORE_CALLBACK_PASS_ON;
1167
1168    /* process remote controller key exceptionally */
1169    if (((!strcmp(ev->key, "Down") ||
1170          !strcmp(ev->key, "KP_Down") ||
1171          !strcmp(ev->key, "Up") ||
1172          !strcmp(ev->key, "KP_Up") ||
1173          !strcmp(ev->key, "Right") ||
1174          !strcmp(ev->key, "KP_Right") ||
1175          !strcmp(ev->key, "Left") ||
1176          !strcmp(ev->key, "KP_Left")) && !ev->string) ||
1177        !strcmp(ev->key, "Return") ||
1178        !strcmp(ev->key, "Pause") ||
1179        !strcmp(ev->key, "NoSymbol") ||
1180        !strncmp(ev->key, "XF86", 4) ||
1181        is_number_key(ev->string))
1182      return ECORE_CALLBACK_PASS_ON;
1183
1184    if (g_text_input && g_text_input->resource && g_client)
1185      _input_panel_hide(g_client, g_text_input->resource, EINA_FALSE);
1186
1187    g_disable_show_panel = EINA_TRUE;
1188
1189    return ECORE_CALLBACK_PASS_ON;
1190 }
1191
1192 static void
1193 _e_text_input_deactivate(E_Text_Input *text_input, E_Input_Method *input_method, Eina_Bool need_focus_in)
1194 {
1195    LOGD("text_input : %p\n", text_input);
1196
1197    if (text_input == g_text_input)
1198      {
1199         g_text_input = NULL;
1200         g_client = NULL;
1201      }
1202
1203    if (input_method->input == text_input)
1204      {
1205         if ((input_method->context) && (input_method->resource))
1206           {
1207 #if ENABLE_GRAB_KEYBOARD
1208              _e_text_input_method_context_grab_set(input_method->context,
1209                                                    EINA_FALSE);
1210 #endif
1211              /* TODO: finish the grab of keyboard. */
1212              wl_input_method_send_deactivate(input_method->resource,
1213                                              input_method->context->resource,
1214                                              need_focus_in);
1215           }
1216
1217         if (ecore_key_down_handler)
1218           {
1219              ecore_event_handler_del(ecore_key_down_handler);
1220              ecore_key_down_handler = NULL;
1221           }
1222
1223         LOGD("Resetting input_method->input : %p", input_method->input);
1224         input_method->input = NULL;
1225         if (input_method->context) input_method->context->input = NULL;
1226         input_method->context = NULL;
1227
1228         text_input->input_methods = eina_list_remove(text_input->input_methods, input_method);
1229
1230         if (text_input->resource)
1231           wl_text_input_send_leave(text_input->resource);
1232
1233         if (_TV)
1234           g_disable_show_panel = EINA_FALSE;
1235      }
1236 }
1237
1238 static void
1239 _e_text_input_cb_activate(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, struct wl_resource *surface)
1240 {
1241    E_Text_Input *text_input = NULL;
1242    E_Input_Method *input_method = NULL;
1243    E_Text_Input *old = NULL;
1244    E_Input_Method_Context *context = NULL;
1245    E_Client *ec = NULL;
1246
1247    EINA_SAFETY_ON_NULL_GOTO(resource, err);
1248    EINA_SAFETY_ON_NULL_GOTO(seat, err);
1249    EINA_SAFETY_ON_NULL_GOTO(g_input_method, err);
1250    EINA_SAFETY_ON_NULL_GOTO(g_input_method->resource, err);
1251
1252    /* Store application window's E_Client* value for setting transient_for information later */
1253    ec = wl_resource_get_user_data(surface);
1254    EINA_SAFETY_ON_NULL_GOTO(ec, err);
1255    EINA_SAFETY_ON_TRUE_GOTO(e_object_is_del(E_OBJECT(ec)), err);
1256    client_surface_ec = ec;
1257
1258    text_input = wl_resource_get_user_data(resource);
1259    g_text_input = text_input;
1260    g_client = client;
1261
1262    /* FIXME: should get input_method object from seat. */
1263    input_method = wl_resource_get_user_data(g_input_method->resource);
1264    EINA_SAFETY_ON_NULL_GOTO(input_method, err);
1265
1266    old = input_method->input;
1267
1268    LOGD("old : %p, text_input : %p, %d", old, text_input, g_input_panel_state);
1269    if (old == text_input)
1270      return;
1271
1272    if (old)
1273      _e_text_input_deactivate(old, input_method, EINA_TRUE);
1274
1275    input_method->input = text_input;
1276    text_input->input_methods = eina_list_append(text_input->input_methods, input_method);
1277
1278    if (input_method->resource)
1279      {
1280         if (!(context = E_NEW(E_Input_Method_Context, 1)))
1281           {
1282              wl_client_post_no_memory(client);
1283              ERR("Could not allocate space for Input_Method_Context");
1284              return;
1285           }
1286
1287         if (!ecore_key_down_handler)
1288           ecore_key_down_handler = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
1289                                                            _e_mod_ecore_key_down_cb,
1290                                                            NULL);
1291
1292         context->resource =
1293            wl_resource_create(wl_resource_get_client(input_method->resource),
1294                               &wl_input_method_context_interface, 1, 0);
1295
1296         if (context->resource)
1297           wl_resource_set_implementation(context->resource,
1298                                          &_e_text_input_method_context_implementation,
1299                                          context, _e_text_input_method_context_cb_resource_destroy);
1300
1301         context->input = text_input;
1302         context->input_method = input_method;
1303         input_method->context = context;
1304
1305         if (context->resource)
1306           wl_input_method_send_activate(input_method->resource, context->resource, text_input->id, EINA_TRUE);
1307      }
1308
1309    if (_TV)
1310      set_soft_keyboard_mode();
1311
1312    if (text_input->resource)
1313      wl_text_input_send_enter(text_input->resource, surface);
1314
1315    return;
1316
1317 err:
1318    if (resource)
1319      WTI_WARNING(resource,
1320                  WL_DISPLAY_ERROR_INVALID_OBJECT,
1321                  "No Text Input For Resource");
1322
1323    if (seat)
1324      WTI_WARNING(seat,
1325                  WL_DISPLAY_ERROR_INVALID_OBJECT,
1326                  "No Comp Data For Seat");
1327 }
1328
1329 static void
1330 _e_text_input_cb_deactivate(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat)
1331 {
1332    LOGD("");
1333    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1334    E_Input_Method *input_method = NULL;
1335
1336    if (!text_input)
1337      {
1338         WTI_WARNING(resource,
1339                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1340                     "No Text Input For Resource");
1341         return;
1342      }
1343
1344    if (text_input == g_text_input)
1345      {
1346         g_text_input = NULL;
1347         g_client = NULL;
1348      }
1349
1350    /* FIXME: should get input_method object from seat. */
1351    if (g_input_method && g_input_method->resource)
1352      input_method = wl_resource_get_user_data(g_input_method->resource);
1353
1354    if (!input_method)
1355      {
1356         WTI_WARNING(seat,
1357                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1358                     "No Input Method For Seat");
1359         return;
1360      }
1361
1362    _e_text_input_deactivate(text_input, input_method, EINA_TRUE);
1363 }
1364
1365 static Eina_Bool
1366 _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)
1367 {
1368    E_Input_Method_Context *context = NULL;
1369
1370    EINA_SAFETY_ON_NULL_RETURN_VAL(input_method, EINA_FALSE);
1371    EINA_SAFETY_ON_NULL_RETURN_VAL(input_method->resource, EINA_FALSE);
1372    EINA_SAFETY_ON_NULL_RETURN_VAL(text_input, EINA_FALSE);
1373
1374    g_text_input = text_input;
1375    g_client = client;
1376    input_method->input = text_input;
1377    text_input->input_methods = eina_list_append(text_input->input_methods, input_method);
1378
1379    if (!(context = E_NEW(E_Input_Method_Context, 1)))
1380      {
1381         wl_client_post_no_memory(client);
1382         ERR("Could not allocate space for Input_Method_Context");
1383         return EINA_FALSE;
1384      }
1385
1386    context->resource =
1387       wl_resource_create(wl_resource_get_client(input_method->resource),
1388                          &wl_input_method_context_interface, 1, 0);
1389
1390    if (context->resource)
1391      wl_resource_set_implementation(context->resource,
1392                                     &_e_text_input_method_context_implementation,
1393                                     context, _e_text_input_method_context_cb_resource_destroy);
1394
1395    context->input = text_input;
1396    context->input_method = input_method;
1397    input_method->context = context;
1398
1399    wl_input_method_send_activate(input_method->resource, context->resource, text_input->id, need_focus_out);
1400
1401    return EINA_TRUE;
1402 }
1403
1404 static void
1405 _e_text_input_cb_input_panel_show(struct wl_client *client, struct wl_resource *resource)
1406 {
1407    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1408    E_Input_Method *input_method = NULL;
1409
1410    LOGD("text_input : %p\n", text_input);
1411
1412    if (!text_input)
1413      {
1414         WTI_WARNING(resource,
1415                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1416                     "No Text Input For Resource");
1417         return;
1418      }
1419
1420 #ifndef SUPPORT_CANDIDATE_ONEWINDOW
1421    if (g_disable_show_panel == EINA_TRUE)
1422      return;
1423 #endif
1424
1425    if (g_input_method && g_input_method->resource)
1426      input_method = wl_resource_get_user_data(g_input_method->resource);
1427
1428    /* If input_method->context doesn't exist, create context struct to send input_panel_show event to Input Method(IME) correctly.
1429     * Because input_panel_show event can be called before focus_in(activate) by application.
1430     * And Input Method(IME) should know the state of their own input_panel to manage their resource when the input_panel is shown. */
1431    if (input_method && (!input_method->context || !input_method->context->resource))
1432      _e_text_input_method_create_context(client, input_method, text_input, EINA_TRUE);
1433
1434 #ifdef SUPPORT_CANDIDATE_ONEWINDOW
1435    if (g_disable_show_panel == EINA_TRUE)
1436      {
1437         if (g_show_state_candidate == EINA_TRUE)
1438           {
1439              g_input_panel_state = E_INPUT_PANEL_STATE_DID_SHOW;
1440              g_show_client = client;
1441              e_input_panel_visibility_change(EINA_TRUE);
1442              e_input_panel_transient_for_set(client_surface_ec);
1443           }
1444        return;
1445      }
1446 #endif
1447
1448    if (input_method && input_method->resource && input_method->context && input_method->context->resource)
1449      {
1450         /* DO NOT show input panel surface until we get message "show complete" from input method,
1451          * in order to give a change to update UI */
1452         LOGD("IM::SHOW::WAIT_FOR_READY\n");
1453
1454         g_show_client = client;
1455         wl_input_method_send_show_input_panel(input_method->resource, input_method->context->resource);
1456
1457         /* we need to force update in order to release buffer
1458          * if we do not, client can't update
1459          * because they may in manual render state by frame callback mechanism,
1460          * and also don't have released buffer */
1461         e_input_panel_wait_update_set(EINA_TRUE);
1462      }
1463
1464    /* If the input panel state was WILL_HIDE, it means that the conformant area information needs to be restored */
1465    if (g_input_panel_state == E_INPUT_PANEL_STATE_WILL_HIDE)
1466      {
1467         if (text_input->resource)
1468           wl_text_input_send_private_command(text_input->resource, 0, "CONFORMANT_RESTORE");
1469      }
1470
1471    text_input->input_panel_visibile = EINA_TRUE;
1472    g_input_panel_state = E_INPUT_PANEL_STATE_WILL_SHOW;
1473    g_show_text_input = text_input;
1474
1475    g_updated_geometry = EINA_FALSE;
1476
1477    e_input_panel_transient_for_set(client_surface_ec);
1478 }
1479
1480 static void
1481 _e_text_input_cb_input_panel_hide(struct wl_client *client, struct wl_resource *resource)
1482 {
1483    if (g_show_client == client) {
1484       _input_panel_hide(client, resource, EINA_FALSE);
1485       g_show_text_input = NULL;
1486       g_show_client = NULL;
1487    }
1488 }
1489
1490 static void
1491 _e_text_input_cb_reset(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
1492 {
1493    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1494    E_Input_Method *input_method = NULL;
1495    Eina_List *l = NULL;
1496
1497    if (!text_input)
1498      {
1499         WTI_WARNING(resource,
1500                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1501                     "No Text Input For Resource");
1502         return;
1503      }
1504
1505    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1506      {
1507         if (!input_method || !input_method->context) continue;
1508         if (input_method->context->resource)
1509           wl_input_method_context_send_reset(input_method->context->resource);
1510      }
1511 }
1512
1513 static void
1514 _e_text_input_cb_content_type_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t hint, uint32_t purpose)
1515 {
1516    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1517    E_Input_Method *input_method = NULL;
1518    Eina_List *l = NULL;
1519
1520    if (!text_input)
1521      {
1522         WTI_WARNING(resource,
1523                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1524                     "No Text Input For Resource");
1525         return;
1526      }
1527
1528    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1529      {
1530         if (!input_method || !input_method->context) continue;
1531
1532         if (input_method->context->resource)
1533           wl_input_method_context_send_content_type(input_method->context->resource,
1534                                                     hint, purpose);
1535      }
1536 }
1537
1538 static void
1539 _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)
1540 {
1541    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1542
1543    if (!text_input)
1544      {
1545         WTI_WARNING(resource,
1546                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1547                     "No Text Input For Resource");
1548         return;
1549      }
1550
1551    /* TODO: issue event update input_panel */
1552 }
1553
1554 static void
1555 _e_text_input_cb_preferred_language_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *language)
1556 {
1557    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1558    E_Input_Method *input_method = NULL;
1559    Eina_List *l = NULL;
1560
1561    if (!text_input)
1562      {
1563         WTI_WARNING(resource,
1564                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1565                     "No Text Input For Resource");
1566         return;
1567      }
1568
1569    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1570      {
1571         if (!input_method || !input_method->context) continue;
1572
1573         if (input_method->context->resource)
1574           wl_input_method_context_send_preferred_language(input_method->context->resource,
1575                                                           language);
1576      }
1577 }
1578
1579 static void
1580 _e_text_input_cb_state_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial)
1581 {
1582    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1583    E_Input_Method *input_method = NULL;
1584    Eina_List *l = NULL;
1585
1586    if (!text_input)
1587      {
1588         WTI_WARNING(resource,
1589                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1590                     "No Text Input For Resource");
1591         return;
1592      }
1593
1594    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1595      {
1596         if (!input_method || !input_method->context) continue;
1597
1598         if (input_method->context->resource)
1599           wl_input_method_context_send_commit_state(input_method->context->resource, serial);
1600      }
1601 }
1602
1603 static void
1604 _e_text_input_cb_action_invoke(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t button, uint32_t index)
1605 {
1606    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1607    E_Input_Method *input_method = NULL;
1608    Eina_List *l = NULL;
1609
1610    if (!text_input)
1611      {
1612         WTI_WARNING(resource,
1613                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1614                     "No Text Input For Resource");
1615         return;
1616      }
1617
1618    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1619      {
1620         if (!input_method || !input_method->context) continue;
1621
1622         if (input_method->context->resource)
1623           wl_input_method_context_send_invoke_action(input_method->context->resource,
1624                                                      button, index);
1625      }
1626 }
1627
1628 static void
1629 _e_text_input_cb_return_key_type_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t return_key_type)
1630 {
1631    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1632    E_Input_Method *input_method = NULL;
1633    Eina_List *l = NULL;
1634
1635    if (!text_input)
1636      {
1637         WTI_WARNING(resource,
1638                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1639                     "No Text Input For Resource");
1640         return;
1641      }
1642
1643    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1644      {
1645         if (!input_method || !input_method->context) continue;
1646
1647         if (input_method->context->resource)
1648           wl_input_method_context_send_return_key_type(input_method->context->resource,
1649                                                        return_key_type);
1650      }
1651 }
1652
1653 static void
1654 _e_text_input_cb_return_key_disabled_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t disabled)
1655 {
1656    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1657    E_Input_Method *input_method = NULL;
1658    Eina_List *l = NULL;
1659
1660    if (!text_input)
1661      {
1662         WTI_WARNING(resource,
1663                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1664                     "No Text Input For Resource");
1665         return;
1666      }
1667
1668    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1669      {
1670         if (!input_method || !input_method->context) continue;
1671
1672         if (input_method->context->resource)
1673           wl_input_method_context_send_return_key_disabled(input_method->context->resource,
1674                                                            disabled);
1675      }
1676 }
1677
1678 static void
1679 _e_text_input_cb_input_panel_data_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *data, uint32_t length)
1680 {
1681    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1682    E_Input_Method *input_method = NULL;
1683    Eina_List *l = NULL;
1684
1685    if (!text_input)
1686      {
1687         WTI_WARNING(resource,
1688                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1689                     "No Text Input For Resource");
1690         return;
1691      }
1692
1693    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1694      {
1695         if (!input_method || !input_method->context) continue;
1696
1697         if (input_method->context->resource)
1698           wl_input_method_context_send_input_panel_data(input_method->context->resource,
1699                                                         data, length);
1700      }
1701
1702    /* Temporarily receiving WILL_HIDE_ACK via input_panel_data, will need for a new wayland protocol */
1703    const char *szWillHideAck = "WILL_HIDE_ACK";
1704    if (strncmp(data, szWillHideAck, strlen(szWillHideAck)) == 0)
1705      {
1706         if (g_timer_will_hide)
1707           {
1708              ecore_timer_del(g_timer_will_hide);
1709              g_timer_will_hide = NULL;
1710           }
1711         INF("WILL_HIDE_ACK_RECVED, %d", g_input_panel_state);
1712         if (g_input_panel_state == E_INPUT_PANEL_STATE_WILL_HIDE)
1713           {
1714              e_input_panel_visibility_change(EINA_FALSE);
1715              e_input_panel_transient_for_set(NULL);
1716              g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
1717           }
1718      }
1719 }
1720
1721 static void
1722 _e_text_input_cb_bidi_direction_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t bidi_direction)
1723 {
1724    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1725    E_Input_Method *input_method = NULL;
1726    Eina_List *l = NULL;
1727
1728    if (!text_input)
1729      {
1730         WTI_WARNING(resource,
1731                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1732                     "No Text Input For Resource");
1733         return;
1734      }
1735
1736    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1737      {
1738         if (!input_method || !input_method->context) continue;
1739
1740         if (input_method->context->resource)
1741           wl_input_method_context_send_bidi_direction(input_method->context->resource,
1742                                                        bidi_direction);
1743      }
1744 }
1745
1746 static void
1747 _e_text_input_cb_cursor_position_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,  uint32_t cursor_position)
1748 {
1749    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1750    E_Input_Method *input_method = NULL;
1751    Eina_List *l = NULL;
1752
1753    if (!text_input)
1754      {
1755         WTI_WARNING(resource,
1756                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1757                     "No Text Input For Resource");
1758         return;
1759      }
1760
1761    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1762      {
1763         if (!input_method || !input_method->context) continue;
1764
1765         if (input_method->context->resource)
1766           wl_input_method_context_send_cursor_position(input_method->context->resource, cursor_position);
1767      }
1768 }
1769
1770 static void
1771 _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)
1772 {
1773    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1774    E_Input_Method *input_method = NULL;
1775    Eina_List *l = NULL;
1776
1777    if (!text_input)
1778      {
1779         WTI_WARNING(resource,
1780                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1781                     "No Text Input For Resource");
1782         return;
1783      }
1784
1785    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1786      {
1787         if (!input_method || !input_method->context) continue;
1788
1789         if (input_method->context->resource)
1790           wl_input_method_context_send_process_input_device_event(input_method->context->resource,
1791                                                                   type, data, length);
1792      }
1793 }
1794
1795 static void
1796 _e_text_input_cb_filter_key_event(struct wl_client *client EINA_UNUSED, struct wl_resource *resource,
1797                                   uint32_t serial, uint32_t time, const char *keyname, uint32_t state,
1798                                   uint32_t modifiers, const char *dev_name, uint32_t dev_class,
1799                                   uint32_t dev_subclass, uint32_t keycode)
1800
1801 {
1802   E_Text_Input *text_input = wl_resource_get_user_data(resource);
1803   E_Input_Method *input_method = NULL;
1804
1805   if (!text_input)
1806     {
1807        WTI_WARNING(resource,
1808                    WL_DISPLAY_ERROR_INVALID_OBJECT,
1809                    "No Text Input For Resource");
1810        return;
1811     }
1812
1813    /* FIXME: should get input_method object from seat. */
1814    if (g_input_method && g_input_method->resource)
1815      input_method = wl_resource_get_user_data(g_input_method->resource);
1816
1817    if (input_method && input_method->context && input_method->context->resource)
1818      {
1819         wl_input_method_context_send_filter_key_event(input_method->context->resource,
1820                                                       serial, time, keyname, state, modifiers,
1821                                                       dev_name, dev_class, dev_subclass, keycode);
1822      }
1823    else
1824      {
1825         if (text_input->resource)
1826           wl_text_input_send_filter_key_event_done(text_input->resource, serial, false);
1827
1828         WTI_WARNING(resource,
1829                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1830                     "No Input Method");
1831      }
1832
1833 }
1834
1835 static void
1836 _e_text_input_cb_get_hide_permission(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
1837 {
1838    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1839    uint32_t permission = 1;
1840    E_Client *focused_ec = NULL;
1841
1842    if (!text_input)
1843      {
1844         WTI_WARNING(resource,
1845                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1846                     "No Text Input For Resource");
1847         return;
1848      }
1849
1850    focused_ec = e_client_focused_get();
1851    if (focused_ec)
1852      {
1853         if (focused_ec != client_surface_ec)
1854           {
1855              E_Window_Type focus_win_type = focused_ec->netwm.type;
1856              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);
1857
1858              if (focus_win_type == E_WINDOW_TYPE_NOTIFICATION ||
1859                  focus_win_type == E_WINDOW_TYPE_POPUP_MENU)
1860                permission = 0;
1861           }
1862      }
1863    else
1864      {
1865         LOGD("Can't get focus window\n");
1866      }
1867
1868    if (text_input->resource)
1869      wl_text_input_send_hide_permission(text_input->resource, permission);
1870 }
1871
1872 static void
1873 _e_text_input_cb_set_capital_mode(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t mode)
1874 {
1875    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1876    E_Input_Method *input_method = NULL;
1877    Eina_List *l = NULL;
1878
1879    if (!text_input)
1880      {
1881         WTI_WARNING(resource,
1882                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1883                     "No Text Input For Resource");
1884         return;
1885      }
1886
1887    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1888      {
1889         if (!input_method || !input_method->context) continue;
1890         if (input_method->context->resource)
1891           wl_input_method_context_send_capital_mode(input_method->context->resource, mode);
1892      }
1893 }
1894
1895 static void
1896 _e_text_input_cb_prediction_hint_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *prediction_hint)
1897 {
1898    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1899    E_Input_Method *input_method = NULL;
1900    Eina_List *l = NULL;
1901
1902    if (!text_input)
1903      {
1904         WTI_WARNING(resource,
1905                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1906                     "No Text Input For Resource");
1907         return;
1908      }
1909
1910    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1911      {
1912         if (!input_method || !input_method->context) continue;
1913
1914         if (input_method->context->resource)
1915           wl_input_method_context_send_prediction_hint(input_method->context->resource, prediction_hint);
1916      }
1917 }
1918
1919 static void
1920 _e_text_input_cb_prediction_hint_data_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *key, const char *value)
1921 {
1922    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1923    E_Input_Method *input_method = NULL;
1924    Eina_List *l = NULL;
1925
1926    if (!text_input)
1927      {
1928         WTI_WARNING(resource,
1929                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1930                     "No Text Input For Resource");
1931         return;
1932      }
1933
1934    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1935      {
1936         if (!input_method || !input_method->context) continue;
1937
1938         if (input_method->context->resource)
1939           wl_input_method_context_send_prediction_hint_data(input_method->context->resource, key, value);
1940      }
1941 }
1942
1943 static void
1944 _e_text_input_cb_mime_type_accept_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *mime_type)
1945 {
1946    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1947    E_Input_Method *input_method = NULL;
1948    Eina_List *l = NULL;
1949
1950    if (!text_input)
1951      {
1952         WTI_WARNING(resource,
1953                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1954                     "No Text Input For Resource");
1955         return;
1956      }
1957
1958    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1959      {
1960         if (!input_method || !input_method->context) continue;
1961
1962         if (input_method->context->resource)
1963           wl_input_method_context_send_mime_type(input_method->context->resource, mime_type);
1964      }
1965 }
1966
1967 static void
1968 _e_text_input_cb_input_panel_position_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t x, uint32_t y)
1969 {
1970    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1971
1972    if (!text_input)
1973      {
1974         WTI_WARNING(resource,
1975                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1976                     "No Text Input For Resource");
1977         return;
1978      }
1979    e_input_panel_floating_position_set(x, y);
1980 }
1981
1982 static void
1983 _e_text_input_cb_finalize_content(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *text, uint32_t cursor_position)
1984 {
1985    E_Text_Input *text_input = wl_resource_get_user_data(resource);
1986    E_Input_Method *input_method = NULL;
1987    Eina_List *l = NULL;
1988
1989    if (!text_input)
1990      {
1991         WTI_WARNING(resource,
1992                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1993                     "No Text Input For Resource");
1994         return;
1995      }
1996
1997    EINA_LIST_FOREACH(text_input->input_methods, l, input_method)
1998      {
1999         if (!input_method || !input_method->context) continue;
2000
2001         if (input_method->context->resource)
2002           wl_input_method_context_send_finalized_content(input_method->context->resource, text, cursor_position);
2003      }
2004 }
2005
2006 static void
2007 _e_text_input_cb_resource_destroy(struct wl_resource *resource)
2008 {
2009    E_Text_Input *text_input = wl_resource_get_user_data(resource);
2010    E_Input_Method *input_method = NULL;
2011
2012    if (!text_input)
2013      {
2014         WTI_WARNING(resource,
2015                     WL_DISPLAY_ERROR_INVALID_OBJECT,
2016                     "No Text Input For Resource");
2017         return;
2018      }
2019
2020    if (g_show_text_input == text_input)
2021      {
2022         if (text_input->input_panel_visibile)
2023           {
2024               _input_panel_hide(g_client, resource, EINA_TRUE);
2025           }
2026
2027         g_show_text_input = NULL;
2028      }
2029
2030    if (g_text_input == text_input)
2031      {
2032         g_text_input = NULL;
2033         g_client = NULL;
2034      }
2035
2036    EINA_LIST_FREE(text_input->input_methods, input_method)
2037      {
2038         if (input_method)
2039           _e_text_input_deactivate(text_input, input_method, EINA_TRUE);
2040      }
2041
2042    free(text_input);
2043 }
2044
2045 static void
2046 _e_text_input_cb_destroy(struct wl_client *client, struct wl_resource *resource)
2047 {
2048     LOGD("");
2049     E_Text_Input *text_input = wl_resource_get_user_data(resource);
2050     E_Input_Method *input_method = NULL;
2051     Eina_Bool _context_created = EINA_FALSE;
2052
2053     if (!text_input)
2054       {
2055          WTI_WARNING(resource,
2056                      WL_DISPLAY_ERROR_INVALID_OBJECT,
2057                      "No Text Input For Resource");
2058          return;
2059       }
2060
2061     if (g_input_method && g_input_method->resource)
2062       input_method = wl_resource_get_user_data(g_input_method->resource);
2063
2064     if (!input_method)
2065       {
2066          WTI_WARNING(resource,
2067                      WL_DISPLAY_ERROR_INVALID_OBJECT,
2068                      "No Input Method For Seat");
2069          return;
2070       }
2071
2072     if ((!input_method->context) || (!input_method->context->resource))
2073       _context_created = _e_text_input_method_create_context(client, input_method, text_input, EINA_FALSE);
2074
2075     if (input_method->resource && input_method->context && input_method->context->resource)
2076       wl_input_method_send_destroy(input_method->resource, input_method->context->resource);
2077
2078     if (_context_created)
2079       _e_text_input_deactivate(text_input, input_method, EINA_FALSE);
2080
2081     wl_resource_destroy(resource);
2082 }
2083
2084 static const struct wl_text_input_interface _e_text_input_implementation = {
2085      _e_text_input_cb_destroy,
2086      _e_text_input_cb_activate,
2087      _e_text_input_cb_deactivate,
2088      _e_text_input_cb_input_panel_show,
2089      _e_text_input_cb_input_panel_hide,
2090      _e_text_input_cb_reset,
2091      _e_text_input_cb_content_type_set,
2092      _e_text_input_cb_cursor_rectangle_set,
2093      _e_text_input_cb_preferred_language_set,
2094      _e_text_input_cb_state_commit,
2095      _e_text_input_cb_action_invoke,
2096      _e_text_input_cb_return_key_type_set,
2097      _e_text_input_cb_return_key_disabled_set,
2098      _e_text_input_cb_input_panel_data_set,
2099      _e_text_input_cb_bidi_direction_set,
2100      _e_text_input_cb_cursor_position_set,
2101      _e_text_input_cb_process_input_device_event,
2102      _e_text_input_cb_filter_key_event,
2103      _e_text_input_cb_get_hide_permission,
2104      _e_text_input_cb_set_capital_mode,
2105      _e_text_input_cb_prediction_hint_set,
2106      _e_text_input_cb_mime_type_accept_set,
2107      _e_text_input_cb_input_panel_position_set,
2108      _e_text_input_cb_finalize_content,
2109      _e_text_input_cb_prediction_hint_data_set
2110 };
2111
2112 static void
2113 _e_text_input_manager_cb_text_input_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
2114 {
2115    E_Text_Input_Mgr *text_input_mgr = wl_resource_get_user_data(resource);
2116    E_Text_Input *text_input = NULL;
2117
2118    if (!text_input_mgr)
2119      {
2120         WTI_WARNING(resource,
2121                     WL_DISPLAY_ERROR_INVALID_OBJECT,
2122                     "No Text Input Manager For Resource");
2123         return;
2124      }
2125
2126    if (!(text_input = E_NEW(E_Text_Input, 1)))
2127      {
2128         wl_client_post_no_memory(client);
2129         ERR("Could not allocate space for Text_Input");
2130         return;
2131      }
2132
2133    text_input->resource =
2134       wl_resource_create(client, &wl_text_input_interface, 1, id);
2135
2136    if (!text_input->resource)
2137      {
2138         wl_client_post_no_memory(client);
2139         ERR("Could not create the resource for text_input");
2140         free(text_input);
2141         return;
2142      }
2143    text_input->id = g_text_input_count++;
2144
2145    wl_resource_set_implementation(text_input->resource,
2146                                   &_e_text_input_implementation,
2147                                   text_input, _e_text_input_cb_resource_destroy);
2148 }
2149
2150 static const struct wl_text_input_manager_interface _e_text_input_manager_implementation = {
2151      _e_text_input_manager_cb_text_input_create
2152 };
2153
2154 static void
2155 _e_text_cb_bind_text_input_manager(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
2156 {
2157    E_Text_Input_Mgr *text_input_mgr = data;
2158
2159    text_input_mgr->resource =
2160       wl_resource_create(client,
2161                          &wl_text_input_manager_interface, 1, id);
2162
2163    if (text_input_mgr->resource)
2164      wl_resource_set_implementation(text_input_mgr->resource,
2165                                     &_e_text_input_manager_implementation,
2166                                     text_input_mgr, NULL);
2167 }
2168
2169 static void
2170 _e_text_input_method_cb_unbind(struct wl_resource *resource)
2171 {
2172    LOGD("");
2173    E_Input_Method *input_method = wl_resource_get_user_data(resource);
2174
2175    if (!input_method)
2176      {
2177         WTI_WARNING(resource,
2178                     WL_DISPLAY_ERROR_INVALID_OBJECT,
2179                     "No Input Method For Resource");
2180         return;
2181      }
2182
2183    if (input_method->resource != resource) return;
2184
2185    if (input_method->input)
2186      _e_text_input_deactivate(input_method->input, input_method, EINA_TRUE);
2187
2188    input_method->resource = NULL;
2189    input_method->context = NULL;
2190
2191    if (vconf_set_bool(VCONFKEY_ISF_BIND, 0) != 0)
2192      LOGW("failed to set isf bind\n");
2193 }
2194
2195 static void
2196 _e_text_input_method_cb_bind(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
2197 {
2198    LOGD("");
2199    E_Input_Method *input_method = data;
2200    struct wl_resource *resource = NULL;
2201
2202    if (!input_method) return;
2203
2204    if (input_method->resource)
2205      _e_text_input_method_cb_unbind(input_method->resource);
2206
2207    if (input_method->resource)
2208      {
2209         WTI_WARNING(input_method->resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
2210                     "input_method object already bound");
2211         return;
2212      }
2213
2214    resource = wl_resource_create(client, &wl_input_method_interface, 1, id);
2215    if (EINA_UNLIKELY(!resource))
2216      return;
2217
2218    input_method->resource = resource;
2219
2220    wl_resource_set_implementation(resource, NULL, input_method,
2221                                   _e_text_input_method_cb_unbind);
2222
2223    if (vconf_set_bool(VCONFKEY_ISF_BIND, 1) != 0)
2224      LOGW("failed to set isf bind\n");
2225 }
2226
2227 static void
2228 _e_text_input_method_destroy(void *data)
2229 {
2230    E_Input_Method *input_method = data;
2231
2232    if (!input_method)
2233      return;
2234
2235    if (input_method->global)
2236      wl_global_destroy(input_method->global);
2237
2238    free(input_method);
2239 }
2240
2241 static Eina_Bool
2242 _e_text_input_method_create(void)
2243 {
2244    if (!(g_input_method = E_NEW(E_Input_Method, 1)))
2245      {
2246         ERR("Could not allocate space for Input_Method");
2247         return EINA_FALSE;
2248      }
2249
2250    g_input_method->global =
2251       wl_global_create(e_comp_wl->wl.disp, &wl_input_method_interface, 1,
2252                        g_input_method, _e_text_input_method_cb_bind);
2253
2254    if (!g_input_method->global)
2255      {
2256         free(g_input_method);
2257         g_input_method = NULL;
2258         return EINA_FALSE;
2259      }
2260
2261    _e_mod_text_input_shutdown_cb_add(_e_text_input_method_destroy, g_input_method);
2262
2263    return EINA_TRUE;
2264 }
2265
2266 static void
2267 _e_text_input_manager_destroy(void *data)
2268 {
2269    E_Text_Input_Mgr *text_input_mgr = data;
2270    if (!text_input_mgr) return;
2271
2272    wl_global_destroy(text_input_mgr->global);
2273    free(text_input_mgr);
2274 }
2275
2276 static Eina_Bool
2277 _e_text_input_manager_create(void)
2278 {
2279    E_Text_Input_Mgr *text_input_mgr;
2280
2281    if (!(text_input_mgr = E_NEW(E_Text_Input_Mgr, 1)))
2282      {
2283         ERR("Could not allocate space for Text_Input_Manager");
2284         return EINA_FALSE;
2285      }
2286
2287    text_input_mgr->global =
2288       wl_global_create(e_comp_wl->wl.disp,
2289                        &wl_text_input_manager_interface, 1,
2290                        text_input_mgr, _e_text_cb_bind_text_input_manager);
2291
2292    if (!text_input_mgr->global)
2293      {
2294         free(text_input_mgr);
2295         return EINA_FALSE;
2296      }
2297
2298    _e_mod_text_input_shutdown_cb_add(_e_text_input_manager_destroy, text_input_mgr);
2299
2300    return EINA_TRUE;
2301 }
2302
2303 static void
2304 _e_mod_text_input_shutdown(void)
2305 {
2306    E_Mod_Text_Input_Shutdown_Cb *cb;
2307
2308    EINA_LIST_FREE(shutdown_list, cb)
2309      {
2310         if (cb)
2311           {
2312              cb->func(cb->data);
2313              free(cb);
2314           }
2315      }
2316 }
2317
2318 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Text_Input" };
2319
2320 static void
2321 set_soft_keyboard_mode()
2322 {
2323    g_disable_show_panel = EINA_FALSE;
2324
2325    /* switch to S/W keyboard mode */
2326    int val = 0;
2327    if (vconf_get_bool(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &val) == 0 && val != 0)
2328      vconf_set_bool(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0);
2329 }
2330
2331 static void
2332 _e_mod_eeze_udev_watch_cb(const char *text, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch)
2333 {
2334    if (event == EEZE_UDEV_EVENT_REMOVE)
2335      set_soft_keyboard_mode();
2336 }
2337
2338 static Eina_Bool
2339 _e_text_input_method_context_cb_client_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
2340 {
2341    E_Event_Client *ev;
2342    E_Client *ec;
2343    Eina_Bool found;
2344    int x = 0, y = 0, w = 0, h = 0;
2345
2346    ev = (E_Event_Client *)event;
2347    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
2348
2349    ec = ev->ec;
2350    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, ECORE_CALLBACK_PASS_ON);
2351
2352    found = e_input_panel_client_find(ec);
2353    if (!found) return ECORE_CALLBACK_PASS_ON;
2354    if ((ec->w < 1) && (ec->h < 1)) return ECORE_CALLBACK_PASS_ON;
2355
2356    if (g_text_input && g_text_input->resource && g_input_panel_state != E_INPUT_PANEL_STATE_WILL_HIDE && g_input_panel_state != E_INPUT_PANEL_STATE_DID_HIDE)
2357      {
2358         if (e_input_panel_client_geometry_get(NULL, &x, &y, &w, &h) && !(w <= 1 || h <= 1))
2359           _e_text_input_send_input_panel_geometry(g_text_input->resource, x, y, w, h);
2360      }
2361
2362    return ECORE_CALLBACK_PASS_ON;
2363 }
2364
2365 static void
2366 _pol_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
2367 {
2368    if (EINA_UNLIKELY(!ec))
2369      return;
2370
2371    if (ec == client_surface_ec)
2372      {
2373         LOGD("transient_for_ec deleted, hiding input panel\n");
2374         e_input_panel_visibility_change(EINA_FALSE);
2375         e_input_panel_transient_for_set(NULL);
2376
2377         if(!e_input_panel_surface_destroy(ec))
2378           LOGE("fail to remove surface\n");
2379
2380         g_input_panel_state = E_INPUT_PANEL_STATE_DID_HIDE;
2381         if (g_timer_will_hide)
2382           {
2383              ecore_timer_del(g_timer_will_hide);
2384              g_timer_will_hide = NULL;
2385           }
2386         client_surface_ec = NULL;
2387         LOGD("TRANSIENT_FOR::Reset transient_for_ec to NULL\n");
2388      }
2389 }
2390
2391 void
2392 e_text_input_update_input_panel_state(Eina_Bool state)
2393 {
2394    if (!g_text_input || !g_text_input->resource) return;
2395
2396    E_Text_Input *text_input = wl_resource_get_user_data(g_text_input->resource);
2397
2398    if (!text_input)
2399      {
2400         WTI_WARNING(g_text_input->resource,
2401                     WL_DISPLAY_ERROR_INVALID_OBJECT,
2402                     "No Text Input For Resource");
2403         return;
2404      }
2405
2406    if (text_input->resource)
2407      {
2408         if (!g_updated_geometry)
2409           {
2410              int x = 0, y = 0, w = 0, h = 0;
2411              if (e_input_panel_client_geometry_get(NULL, &x, &y, &w, &h) && !(w <= 1 || h <= 1))
2412                _e_text_input_send_input_panel_geometry(text_input->resource, x, y, w, h);
2413              g_updated_geometry = EINA_TRUE;
2414           }
2415         uint32_t input_panel_state = WL_TEXT_INPUT_INPUT_PANEL_STATE_HIDE;
2416         if (state) input_panel_state = WL_TEXT_INPUT_INPUT_PANEL_STATE_SHOW;
2417         wl_text_input_send_input_panel_state(text_input->resource, input_panel_state);
2418      }
2419 }
2420
2421 E_API void *
2422 e_modapi_init(E_Module *m)
2423 {
2424    if (!e_comp_wl) return NULL;
2425
2426    if (!wti_log_init())
2427      return NULL;
2428
2429    /* FIXME: create only one input method object per seat. */
2430    if (!_e_text_input_method_create())
2431      return NULL;
2432
2433    if (!e_input_panel_init())
2434      goto err;
2435
2436    if (!_e_text_input_manager_create())
2437      goto err;
2438
2439    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_RESIZE, _e_text_input_method_context_cb_client_resize, NULL);
2440
2441    vconf_notify_key_changed(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, _keyboard_mode_changed_cb, NULL);
2442
2443    eeze_udev_watch_hander = eeze_udev_watch_add(EEZE_UDEV_TYPE_KEYBOARD,
2444                                                 EEZE_UDEV_EVENT_REMOVE,
2445                                                 _e_mod_eeze_udev_watch_cb,
2446                                                 NULL);
2447    if (!eeze_udev_watch_hander)
2448      goto err;
2449
2450    E_CLIENT_HOOK_APPEND(hooks_ec, E_CLIENT_HOOK_DEL, _pol_cb_hook_client_del, NULL);
2451
2452    return m;
2453 err:
2454    _e_mod_text_input_shutdown();
2455    return NULL;
2456 }
2457
2458 E_API int
2459 e_modapi_shutdown(E_Module *m EINA_UNUSED)
2460 {
2461    E_FREE_LIST(handlers, ecore_event_handler_del);
2462    E_FREE_LIST(hooks_ec, e_client_hook_del);
2463
2464    if (g_timer_will_hide)
2465      {
2466         ecore_timer_del(g_timer_will_hide);
2467         g_timer_will_hide = NULL;
2468      }
2469
2470    vconf_ignore_key_changed(VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, _keyboard_mode_changed_cb);
2471
2472    if (eeze_udev_watch_hander)
2473      {
2474         eeze_udev_watch_del(eeze_udev_watch_hander);
2475         eeze_udev_watch_hander = NULL;
2476      }
2477    _e_mod_text_input_shutdown();
2478
2479    e_input_panel_shutdown();
2480
2481    wti_log_shutdown();
2482
2483    return 1;
2484 }
2485
2486 E_API int
2487 e_modapi_save(E_Module *m EINA_UNUSED)
2488 {
2489    /* do nothing */
2490    return 1;
2491 }