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