add code to check effect state while handling hide keyboard request
[platform/core/uifw/e-mod-tizen-wl-textinput.git] / src / e_mod_input_panel.c
1 #define E_COMP_WL
2 #include "e.h"
3 #include "e_mod_main.h"
4 #include <vconf.h>
5 #include <vconf-keys.h>
6 #include <input-method-server-protocol.h>
7
8 #define WTI_WARNING(resource, code, msg)     (_e_input_panel_log_show((resource), (code), (msg), __func__))
9 #define WAIT_UPDATE_TIMER_INTERVAL 2.0f
10
11 typedef struct _E_Input_Panel E_Input_Panel;
12 typedef struct _E_Input_Panel_Surface E_Input_Panel_Surface;
13 typedef struct _E_Input_Panel_Floating_Info E_Input_Panel_Floating_Info;
14
15 typedef enum
16 {
17    E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE,
18    E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL,
19 } E_Input_Panel_Coordinate_Type;
20
21 struct _E_Input_Panel
22 {
23    struct wl_global *global;
24    struct wl_resource *resource;
25    Eina_List *surfaces;
26
27    Ecore_Event_Handler *buf_change_handler;
28    Ecore_Idle_Enterer *idle_enter;
29
30    Eina_Bool wait_update; /* wait update state for global input panel object */
31 };
32
33 struct _E_Input_Panel_Surface
34 {
35    struct wl_resource *resource;
36
37    E_Input_Panel *input_panel;
38    E_Client *ec;
39
40    struct
41    {
42       Ecore_Event_Handler *rot_change_end;
43       Ecore_Event_Handler *buf_change;
44       Ecore_Event_Handler *rot_geometry_set;
45    } eh;
46
47    Eina_Bool panel;
48    Eina_Bool showing;
49    Eina_Bool need_show;
50
51    Eina_Bool resizing;
52    Ecore_Timer *resize_timer;
53
54    E_Client_Hook *hook_del;
55    E_Policy_Hook *hook_rotation_geometry_set;
56 };
57
58 struct _E_Input_Panel_Floating_Info
59 {
60    Eina_Bool moving_req;
61    Eina_Bool mouse_pressed;
62    Eina_Bool init_portrait_position;
63    Eina_Bool init_landscape_position;
64    int before_canvas_x;
65    int before_canvas_y;
66
67    struct
68    {
69       int portrait_x;
70       int portrait_y;
71       int landscape_x;
72       int landscape_y;
73    } start_position;
74 };
75
76 E_Input_Panel *g_input_panel = NULL;
77 E_Input_Panel_Floating_Info *g_floating_info = NULL;
78 Eina_List *handlers = NULL;
79 static Eina_Bool panel_show_need_rerun = EINA_FALSE;
80 static Ecore_Timer *g_timer_wait_update  = NULL;
81
82 static E_Input_Panel_Surface *
83 _e_input_panel_surface_get(E_Client *ec)
84 {
85    E_Input_Panel_Surface *ips;
86    Eina_List *l;
87    Eina_List *l_next;
88
89    if (!g_input_panel) return NULL;
90
91    EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
92      {
93         if (!ips || !ips->ec) continue;
94         if (ips->ec == ec)
95           {
96              return ips;
97           }
98      }
99
100    return NULL;
101 }
102
103 static void
104 _e_input_panel_start_drawing(E_Input_Panel_Surface *ips)
105 {
106    if (!ips) return;
107    if (!ips->resizing) return;
108
109    if (ips->resize_timer)
110      {
111         ecore_timer_del(ips->resize_timer);
112         ips->resize_timer = NULL;
113      }
114
115    LOGD("Norender pop by resizing keyboard");
116    e_comp_canvas_norender_pop();
117    ips->resizing = EINA_FALSE;
118 }
119
120 static Eina_Bool
121 _resize_timeout_cb(void *data)
122 {
123    E_Input_Panel_Surface *ips = NULL;
124
125    LOGE("TIMED OUT while waiting for resizing keyboard");
126
127    ips = data;
128    if (!ips) return ECORE_CALLBACK_CANCEL;
129
130    LOGD("Norender pop by resizing keyboard timeout");
131    e_comp_canvas_norender_pop();
132    ips->resizing = EINA_FALSE;
133
134    return ECORE_CALLBACK_CANCEL;
135 }
136
137 static void
138 _e_input_panel_stop_drawing(E_Input_Panel_Surface *ips)
139 {
140    if (!ips) return;
141    if (ips->resizing) return;
142
143    LOGD("Norender push by resizing keyboard");
144    e_comp_canvas_norender_push();
145    ips->resizing = EINA_TRUE;
146
147    if (!ips->resize_timer)
148      {
149         ips->resize_timer = ecore_timer_add(WAIT_UPDATE_TIMER_INTERVAL,
150                                             _resize_timeout_cb, ips);
151      }
152 }
153
154 static void
155 _e_input_panel_log_show(struct wl_resource *resource, uint32_t code, const char *msg, const char *warning_msg)
156 {
157    LOGW("%s() is failed\n", warning_msg);
158    wl_resource_post_error(resource, code, "%s", msg);
159 }
160
161 static Eina_Bool
162 _e_input_panel_is_effect_running(E_Client *ec)
163 {
164    if ((e_comp_object_is_animating(ec->frame)) ||
165        (evas_object_data_get(ec->frame, "effect_running")))
166      return EINA_TRUE;
167    return EINA_FALSE;
168 }
169
170 static void
171 _e_input_panel_surface_append(E_Input_Panel *input_panel, E_Input_Panel_Surface *ips, struct wl_resource *resource)
172 {
173    if (!input_panel || !ips) return;
174
175    E_Client *client_surface = e_text_input_client_surface_get();
176    ips->resource = resource;
177    input_panel->surfaces = eina_list_append(input_panel->surfaces, ips);
178    LOGD("input_panel %p ips %p resource %p client surface %p", input_panel, ips, resource, client_surface);
179
180    if (client_surface)
181      e_input_panel_transient_for_set(client_surface);
182
183    /* When a new input panel surface is created and if we have failed
184     * showing input panel previously, try to show it again here */
185    if (input_panel->surfaces && panel_show_need_rerun)
186      e_input_panel_visibility_change(EINA_TRUE);
187 }
188
189 static void
190 _e_input_panel_surface_cb_toplevel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *output_resource EINA_UNUSED, uint32_t position EINA_UNUSED)
191 {
192    E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
193    E_Input_Panel *input_panel = NULL;
194
195    if (!ips)
196      {
197         WTI_WARNING(resource,
198                     WL_DISPLAY_ERROR_INVALID_OBJECT,
199                     "No Input Panel Surface For Surface");
200         return;
201      }
202
203    if (!(input_panel = ips->input_panel)) return;
204
205    /* Do not append duplicated surface - And need to check if the surface really needs to be appended here,
206     * since the newly created surface is already being appended at function _e_input_panel_cb_surface_get() */
207    if (eina_list_data_find(input_panel->surfaces, ips) != ips)
208      {
209         _e_input_panel_surface_append(input_panel, ips, resource);
210      }
211    ips->panel = EINA_FALSE;
212 }
213
214 static void
215 _e_input_panel_surface_cb_overlay_panel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
216 {
217    E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
218    E_Input_Panel *input_panel = NULL;
219
220    if (!ips)
221      {
222         WTI_WARNING(resource,
223                     WL_DISPLAY_ERROR_INVALID_OBJECT,
224                     "No Input Panel Surface For Surface");
225         return;
226      }
227
228    if (!(input_panel = ips->input_panel)) return;
229
230    /* Do not append duplicated surface - And need to check if the surface really needs to be appended here,
231    * since the newly created surface is already being appended at function _e_input_panel_cb_surface_get() */
232    if (eina_list_data_find(input_panel->surfaces, ips) != ips)
233      {
234         _e_input_panel_surface_append(input_panel, ips, resource);
235      }
236    ips->panel = EINA_TRUE;
237 }
238
239 static void
240 _e_input_panel_surface_show(E_Input_Panel_Surface *ips)
241 {
242    Eina_List *l = NULL;
243    E_Input_Panel_Surface *surface = NULL;
244    E_Client *focused_ec = NULL;
245
246    if (!g_input_panel) return;
247
248    /* When NULL passed, find the most appropriate surface */
249    if (!ips)
250      {
251         EINA_LIST_FOREACH(g_input_panel->surfaces, l, surface)
252           {
253              if (surface && surface->ec)
254                {
255                   if (surface->ec->parent == e_client_focused_get())
256                     {
257                        ips = surface;
258                     }
259                }
260           }
261      }
262
263    if (!ips) return;
264
265    LOGD("parent:%p, focus:%p, wait_update %d\n",
266         ips->ec ? ips->ec->parent : NULL, e_client_focused_get(), g_input_panel->wait_update);
267
268    if (g_input_panel->wait_update)
269      {
270         focused_ec = e_client_focused_get();
271         e_input_panel_wait_update_set(EINA_FALSE);
272         if (ips->ec->parent)
273           {
274              if (ips->ec->parent == focused_ec)
275                {
276                   e_policy_conformant_part_update(ips->ec);
277                   e_input_panel_visibility_change(EINA_TRUE);
278
279                   e_text_input_update_input_panel_state(EINA_TRUE);
280                }
281              else
282                e_input_panel_visibility_change(EINA_FALSE);
283           }
284         else
285           e_input_panel_visibility_change(EINA_FALSE);
286      }
287 }
288
289 static void _wait_update_timer_del()
290 {
291    if (g_timer_wait_update)
292      {
293         LOGD("deleting wait_update timer");
294         ecore_timer_del(g_timer_wait_update);
295         g_timer_wait_update = NULL;
296      }
297 }
298
299 static Eina_Bool
300 _wait_update_timer_handler(void *data)
301 {
302    LOGE("TIMED OUT while waiting for ready_set");
303
304    _e_input_panel_surface_show(NULL);
305
306    g_timer_wait_update = NULL;
307
308    return ECORE_CALLBACK_CANCEL;
309 }
310
311 static void
312 _e_input_panel_surface_cb_ready_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t state EINA_UNUSED)
313 {
314    E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
315
316    if (!g_input_panel) return;
317
318    if (!ips)
319      {
320         WTI_WARNING(resource,
321                     WL_DISPLAY_ERROR_INVALID_OBJECT,
322                     "No Input Panel Surface For Surface");
323         return;
324      }
325
326    LOGD("IPS::SHOW::READY\n");
327
328    // base_output_resolution
329    e_client_base_output_resolution_transform_adjust(ips->ec);
330
331    _e_input_panel_surface_show(ips);
332 }
333
334 static void
335  _e_input_panel_surface_cb_floating_panel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t state)
336 {
337    E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
338
339    if (!ips)
340      {
341         WTI_WARNING(resource,
342                     WL_DISPLAY_ERROR_INVALID_OBJECT,
343                     "No Input Panel Surface For Surface");
344         return;
345      }
346
347    if (!ips->ec) return;
348
349    if (ips->ec->vkbd.floating == state) return;
350
351    ips->ec->vkbd.floating = !!state;
352
353    if (ips->ec->vkbd.floating)
354      e_policy_conformant_part_del(ips->ec);
355    else
356      e_policy_conformant_part_add(ips->ec);
357 }
358
359 static void
360 _e_input_panel_surface_cb_floating_drag_enabled_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t enabled)
361 {
362    E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
363
364    if (!ips)
365      {
366         WTI_WARNING(resource,
367                     WL_DISPLAY_ERROR_INVALID_OBJECT,
368                     "No Input Panel Surface For Surface");
369         return;
370      }
371
372    g_floating_info->moving_req = !!enabled;
373 }
374
375 static const struct wl_input_panel_surface_interface _e_input_panel_surface_implementation = {
376      _e_input_panel_surface_cb_toplevel_set,
377      _e_input_panel_surface_cb_overlay_panel_set,
378      _e_input_panel_surface_cb_ready_set,
379      _e_input_panel_surface_cb_floating_panel_set,
380      _e_input_panel_surface_cb_floating_drag_enabled_set
381 };
382
383 static void
384 _e_input_panel_surface_resource_destroy(struct wl_resource *resource)
385 {
386    LOGD("");
387    E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
388    E_Input_Panel *input_panel = NULL;
389    E_Client *ec = NULL;
390
391    if (!ips)
392      {
393         WTI_WARNING(resource,
394                     WL_DISPLAY_ERROR_INVALID_OBJECT,
395                     "No Input Panel Surface For Surface");
396         return;
397      }
398
399    if (!(input_panel = ips->input_panel)) return;
400
401    ec = ips->ec;
402    if (ec && (!e_object_is_del(E_OBJECT(ec))))
403      {
404         if (ec->comp_data)
405           {
406              if (ec->comp_data->mapped)
407                {
408                   if ((ec->comp_data->shell.surface) &&
409                       (ec->comp_data->shell.unmap))
410                     ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
411                }
412              if (ec->parent)
413                {
414                   ec->parent->transients =
415                      eina_list_remove(ec->parent->transients, ec);
416                }
417              ec->comp_data->shell.surface = NULL;
418           }
419      }
420
421    if (ips->resizing)
422      {
423         LOGD("Destroyed Waiting Resize Input Surface. Starting Drawing Again");
424         _e_input_panel_start_drawing(ips);
425      }
426
427    LOGD("Removing ips %p from input panel %p", ips, input_panel);
428    input_panel->surfaces = eina_list_remove(input_panel->surfaces, ips);
429    E_FREE_FUNC(ips->eh.rot_geometry_set, ecore_event_handler_del);
430    E_FREE_FUNC(ips->eh.rot_change_end, ecore_event_handler_del);
431    E_FREE_FUNC(ips->eh.buf_change, ecore_event_handler_del);
432    E_FREE_FUNC(ips->hook_del, e_client_hook_del);
433    E_FREE_FUNC(ips->hook_rotation_geometry_set, e_policy_hook_del);
434    free(ips);
435 }
436
437 static void
438 _e_input_panel_init_floating_position(E_Client *ec)
439 {
440    int zx, zy, zw, zh;
441
442    if (!ec || !g_floating_info) return;
443
444    e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
445
446    switch (ec->e.state.rot.ang.curr)
447      {
448         case 90:
449         case 270:
450            if (!g_floating_info->init_landscape_position)
451              {
452                 g_floating_info->start_position.landscape_x = (zh - ec->client.h) / 2;
453                 g_floating_info->start_position.landscape_y = (zw - ec->client.w) / 2;
454                 g_floating_info->init_landscape_position = EINA_TRUE;
455              }
456            break;
457         case 0:
458         case 180:
459         default:
460            if (!g_floating_info->init_portrait_position)
461              {
462                 g_floating_info->start_position.portrait_x = (zw - ec->client.w) / 2;
463                 g_floating_info->start_position.portrait_y = (zh - ec->client.h) / 2;
464                 g_floating_info->init_portrait_position = EINA_TRUE;
465              }
466            break;
467      }
468 }
469
470 static void
471 _e_input_panel_stay_within_screen(E_Client *ec, int x, int y, int *new_x, int *new_y)
472 {
473    int zx, zy, zw, zh;
474
475    if (!ec || !g_floating_info) return;
476
477    e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
478
479    switch (ec->e.state.rot.ang.curr)
480      {
481         case 90:
482         case 270:
483            if (x < 0)
484              *new_x = 0;
485            else if (x > zh - ec->client.h)
486              *new_x = zh - ec->client.h;
487            else
488              *new_x = x;
489
490            if (y < 0)
491              *new_y = 0;
492            else if (y > zw - ec->client.w)
493              *new_y = zw - ec->client.w;
494            else
495              *new_y = y;
496            break;
497         case 0:
498         case 180:
499         default:
500            if (x < 0)
501              *new_x = 0;
502            else if (x > zw - ec->client.w)
503              *new_x = zw - ec->client.w;
504            else
505              *new_x = x;
506
507            if (y < 0)
508              *new_y = 0;
509            else if (y > zh - ec->client.h)
510              *new_y = zh - ec->client.h;
511            else
512              *new_y = y;
513            break;
514      }
515 }
516
517 static void
518 _e_input_panel_convert_floating_position(E_Client *ec, int x, int y, int *new_x, int *new_y, E_Input_Panel_Coordinate_Type cur_type)
519 {
520    int zx, zy, zw, zh;
521    int cur_angle;
522
523    if (!ec || !g_floating_info) return;
524
525    cur_angle = ec->e.state.rot.ang.curr;
526    if ((!g_floating_info->init_portrait_position && (cur_angle == 0 || cur_angle == 180)) ||
527     (!g_floating_info->init_landscape_position && (cur_angle == 90 || cur_angle == 270)))
528      _e_input_panel_init_floating_position(ec);
529
530    e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
531
532    switch (cur_angle)
533      {
534         case 90:
535            if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
536              {
537                 *new_x = zh - y - ec->client.h;
538                 *new_y = x;
539              }
540            else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
541              {
542                 *new_x = y;
543                 *new_y = zh - x - ec->client.h;
544              }
545            break;
546         case 180:
547            if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
548              {
549                 *new_x = zh - y - ec->client.h;
550                 *new_y = zw - x - ec->client.w;
551              }
552            else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
553              {
554                 *new_x = zw - x - ec->client.w;
555                 *new_y = zh - y - ec->client.h;
556              }
557            break;
558         case 270:
559            if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
560              {
561                 *new_x = y;
562                 *new_y = zw - x - ec->client.w;
563              }
564            else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
565              {
566                 *new_x = zw - y - ec->client.w;
567                 *new_y = x;
568              }
569            break;
570         case 0:
571         default:
572            *new_x = x;
573            *new_y = y;
574            break;
575      }
576 }
577
578 static void
579 _e_input_panel_position_set(E_Client *ec, int w, int h)
580 {
581    int nx, ny;
582    int zx, zy, zw, zh;
583    Eina_Bool is_portrait;
584
585    if (!ec || !g_floating_info) return;
586
587    e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
588
589    /* Get the position of center bottom each angles */
590    switch (ec->e.state.rot.ang.curr)
591      {
592         case 90:
593            nx = zx + zw - w;
594            ny = zy + (zh - h) / 2;
595            is_portrait = EINA_FALSE;
596            break;
597         case 180:
598            nx = zx + (zw - w) / 2;
599            ny = zy;
600            is_portrait = EINA_TRUE;
601            break;
602         case 270:
603            nx = zx;
604            ny = zy + (zh - h) / 2;
605            is_portrait = EINA_FALSE;
606            break;
607         case 0:
608         default:
609            nx = zx + (zw - w) / 2;
610            ny = zy + zh - h;
611            is_portrait = EINA_TRUE;
612            break;
613      }
614
615    if (ec->vkbd.floating)
616      {
617         int sx, sy;
618         if ((is_portrait && !g_floating_info->init_portrait_position) || (!is_portrait && !g_floating_info->init_landscape_position))
619           _e_input_panel_init_floating_position(ec);
620
621         if (is_portrait)
622           _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.portrait_x, g_floating_info->start_position.portrait_y, &sx, &sy);
623         else
624           _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.landscape_x, g_floating_info->start_position.landscape_y, &sx, &sy);
625
626         _e_input_panel_convert_floating_position(ec, sx, sy, &nx, &ny, E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL);
627      }
628
629    e_client_util_move_without_frame(ec, nx, ny);
630 }
631
632 static void
633 _ips_show(E_Client *ec)
634 {
635    if (ec->visible)
636      return;
637
638    LOGD("IPS::SHOW\n");
639
640    _e_input_panel_position_set(ec, ec->client.w, ec->client.h);
641
642    ec->visible = EINA_TRUE;
643    evas_object_geometry_set(ec->frame, ec->x, ec->y, ec->w, ec->h);
644    evas_object_show(ec->frame);
645    e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
646 }
647
648 static void
649 _e_input_panel_surface_visible_update(E_Input_Panel_Surface *ips)
650 {
651    E_Client *ec;
652
653    if (!ips) return;
654
655    if (!(ec = ips->ec)) return;
656
657    if (e_object_is_del(E_OBJECT(ec))) return;
658    if ((ips->showing) && (e_pixmap_usable_get(ec->pixmap)))
659      {
660         /* Now we can assure that previous SHOW request actually succeeded,
661          * no need for trying re-run panel show command */
662         if (panel_show_need_rerun)
663           e_input_panel_show_need_rerun_set(EINA_FALSE);
664
665         if (_e_input_panel_is_effect_running(ips->ec))
666           ips->need_show = EINA_TRUE;
667         else if (ips->resizing)
668           {
669              LOGD("Keyboard is currently resizing. set need_show.");
670              ips->need_show = EINA_TRUE;
671           }
672         else
673           {
674              _ips_show(ips->ec);
675              ips->need_show = EINA_FALSE;
676           }
677      }
678    else
679      {
680         LOGD("IPS::DEFER_SHOW::HIDE\n");
681         ec->visible = EINA_FALSE;
682         /* We have to reset the flag of pending_show to prevent showing after
683          * finish the rotation. Directly set this value, since there is no way
684          * to tell it needs to be hidden to rotation module for now. */
685         ec->e.state.rot.pending_show = 0;
686         evas_object_hide(ec->frame);
687         E_FREE_FUNC(ips->eh.buf_change, ecore_event_handler_del);
688         ips->need_show = EINA_FALSE;
689      }
690 }
691
692 static void
693 _e_input_panel_surface_configure(struct wl_resource *resource, Evas_Coord x EINA_UNUSED, Evas_Coord y EINA_UNUSED, Evas_Coord w, Evas_Coord h)
694 {
695    E_Input_Panel_Surface *ips;
696    E_Client *ec;
697
698    if (!(ips = wl_resource_get_user_data(resource)))
699      {
700         WTI_WARNING(resource,
701                     WL_DISPLAY_ERROR_INVALID_OBJECT,
702                     "No Input Panel Surface For Surface");
703         return;
704      }
705
706    if (!(ec = ips->ec))
707      {
708         WTI_WARNING(resource,
709                     WL_DISPLAY_ERROR_INVALID_OBJECT,
710                     "No Client For Input Panel Surface");
711         return;
712      }
713
714    e_client_util_resize_without_frame(ec, w, h);
715
716    if (ips->showing)
717      _e_input_panel_surface_visible_update(ips);
718 }
719
720 static void
721 _e_input_panel_surface_map(struct wl_resource *resource)
722 {
723    E_Input_Panel_Surface *ips;
724    E_Client *ec;
725
726    if (!(ips = wl_resource_get_user_data(resource)))
727      {
728         WTI_WARNING(resource,
729                     WL_DISPLAY_ERROR_INVALID_OBJECT,
730                     "No Input Panel Surface For Surface");
731         return;
732      }
733
734    if (!(ec = ips->ec))
735      {
736         WTI_WARNING(resource,
737                     WL_DISPLAY_ERROR_INVALID_OBJECT,
738                     "No Client For Input Panel Surface");
739         return;
740      }
741
742    if (!ec->comp_data)
743      {
744         WTI_WARNING(resource,
745                     WL_DISPLAY_ERROR_INVALID_OBJECT,
746                     "No Data For Client");
747         return;
748      }
749
750    /* NOTE: we need to set mapped, so that avoid showing evas_object and continue buffer's commit process. */
751    if ((!ec->comp_data->mapped) && (e_pixmap_usable_get(ec->pixmap)))
752      {
753         ec->comp_data->mapped = EINA_TRUE;
754         ec->first_mapped = EINA_TRUE;
755      }
756 }
757
758 static void
759 _e_input_panel_surface_unmap(struct wl_resource *resource)
760 {
761    E_Input_Panel_Surface *ips = NULL;
762    E_Client *ec = NULL;
763
764    if (!(ips = wl_resource_get_user_data(resource)))
765      {
766         WTI_WARNING(resource,
767                     WL_DISPLAY_ERROR_INVALID_OBJECT,
768                     "No Input Panel Surface For Surface");
769         return;
770      }
771
772    if (!(ec = ips->ec))
773      {
774         WTI_WARNING(resource,
775                     WL_DISPLAY_ERROR_INVALID_OBJECT,
776                     "No Client For Input Panel Surface");
777         return;
778      }
779
780    if (!ec->comp_data)
781      {
782         WTI_WARNING(resource,
783                     WL_DISPLAY_ERROR_INVALID_OBJECT,
784                     "No Data For Client");
785         return;
786      }
787
788    if (e_object_is_del(E_OBJECT(ec))) return;
789
790    if (ec->comp_data->mapped)
791      {
792         ec->visible = EINA_FALSE;
793         evas_object_hide(ec->frame);
794         ec->comp_data->mapped = EINA_FALSE;
795      }
796 }
797
798 static Eina_Bool
799 _e_input_panel_client_cb_rotation_change_end(void *data, int type, void *event)
800 {
801    E_Client *ec;
802    E_Input_Panel_Surface *ips = data;
803    E_Event_Client_Rotation_Change_End *ev = event;
804
805    ec = ev->ec;
806    if (ec != ips->ec)
807      goto end;
808
809    if (ips->showing) {
810       LOGD("current angle : %d", ec->e.state.rot.ang.curr);
811       _e_input_panel_position_set(ec, ec->client.w, ec->client.h);
812    }
813
814 end:
815    return ECORE_CALLBACK_PASS_ON;
816 }
817
818 static Eina_Bool
819 _e_input_panel_client_cb_rotation_geometry_set(void *data, int type, void *event)
820 {
821    E_Client *ec;
822    E_Input_Panel_Surface *ips = data;
823    E_Event_Client_Rotation_Geometry_Set *ev = event;
824    int i;
825    int w, h;
826
827    ec = ev->ec;
828    if (ec != ips->ec)
829      goto end;
830
831    if (!ips->showing)
832      goto end;
833
834    if (ips->resizing)
835      goto end;
836
837    if (ev->angle != ec->e.state.rot.ang.curr)
838      goto end;
839
840    evas_object_geometry_get(ec->frame, NULL, NULL, &w, &h);
841
842    switch (ev->angle)
843      {
844       case 0:   i = 0; break;
845       case 90:  i = 1; break;
846       case 180: i = 2; break;
847       case 270: i = 3; break;
848       default:  i = 0; break;
849      }
850
851    if ((w != ec->e.state.rot.geom[i].w) ||
852        (h != ec->e.state.rot.geom[i].h))
853      {
854         LOGD("Resizing by Rotation Geometry. Pending Drawing");
855         _e_input_panel_stop_drawing(ips);
856      }
857
858 end:
859    return ECORE_CALLBACK_PASS_ON;
860 }
861
862 static void
863 _e_input_panel_client_cb_remove(void *data, E_Client *ec)
864 {
865    E_Input_Panel_Surface *ips = data;
866
867    if (ec == ips->ec)
868      {
869         LOGD("Remove IPS's ec. ips:%p, ips->ec:%p", ips, ips->ec);
870         ips->ec = NULL;
871      }
872 }
873
874 static void
875 _e_ips_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
876 {
877    E_Input_Panel_Surface *ips = NULL;
878    E_Client *ec;
879    int w, h;
880    int angle;
881    int i;
882
883    ec = data;
884    if (e_object_is_del(E_OBJECT(ec)))
885      return;
886
887    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
888
889    LOGD("current angle : %d", ec->e.state.rot.ang.curr);
890    _e_input_panel_position_set(ec, w, h);
891
892    ips = _e_input_panel_surface_get(ec);
893    if (!ips) return;
894    if (!ips->resizing) return;
895
896    angle = ec->e.state.rot.ang.curr;
897    switch (angle)
898      {
899       case 0:   i = 0; break;
900       case 90:  i = 1; break;
901       case 180: i = 2; break;
902       case 270: i = 3; break;
903       default:  i = 0; break;
904      }
905
906    if ((w == ec->e.state.rot.geom[i].w) ||
907        (h == ec->e.state.rot.geom[i].h))
908      {
909         LOGD("Resize Done to Rotation Geometry. Starting Drawing Again");
910         _e_input_panel_start_drawing(ips);
911      }
912 }
913
914 static void
915 _e_ips_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
916 {
917    E_Client *ec;
918
919    ec = data;
920    if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
921      return;
922
923    g_floating_info->mouse_pressed = EINA_FALSE;
924    g_floating_info->moving_req = EINA_FALSE;
925 }
926
927 static void
928 _e_ips_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
929 {
930    E_Client *ec;
931    Evas_Event_Mouse_Move *ev = event_info;
932
933    ec = data;
934    if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
935      return;
936
937    g_floating_info->mouse_pressed = EINA_TRUE;
938    g_floating_info->before_canvas_x = ev->cur.canvas.x;
939    g_floating_info->before_canvas_y = ev->cur.canvas.y;
940 }
941
942 static void
943 _e_ips_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
944 {
945    E_Client *ec;
946    Evas_Event_Mouse_Move *ev = event_info;
947    Evas_Coord x, y, w, h;
948    int b_x = 0, b_y = 0, n_x = 0, n_y = 0;
949    int d_x, d_y;
950
951    ec = data;
952    if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
953      return;
954
955    if (!g_floating_info->moving_req || !g_floating_info->mouse_pressed)
956      return;
957
958    evas_object_geometry_get(obj, &x, &y, &w, &h);
959
960    d_x = x + (ev->cur.canvas.x - g_floating_info->before_canvas_x);
961    d_y = y + (ev->cur.canvas.y - g_floating_info->before_canvas_y);
962
963    _e_input_panel_convert_floating_position(ec, d_x, d_y, &b_x, &b_y, E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE);
964    _e_input_panel_stay_within_screen(ec, b_x, b_y, &n_x, &n_y);
965
966    g_floating_info->before_canvas_x = ev->cur.canvas.x;
967    g_floating_info->before_canvas_y = ev->cur.canvas.y;
968
969    if (ec->e.state.rot.ang.curr == 90 || ec->e.state.rot.ang.curr == 270)
970      {
971         g_floating_info->start_position.landscape_x = n_x;
972         g_floating_info->start_position.landscape_y = n_y;
973      }
974    else
975      {
976         g_floating_info->start_position.portrait_x = n_x;
977         g_floating_info->start_position.portrait_y = n_y;
978      }
979
980    _e_input_panel_convert_floating_position(ec, n_x, n_y, &d_x, &d_y, E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL);
981    evas_object_move(obj, d_x, d_y);
982 }
983
984 static void
985 _e_input_panel_rotation_geometry_set(void *data, E_Client *ec)
986 {
987    E_Input_Panel_Surface *ips;
988    int i;
989    int w, h;
990    int cur_angle;
991
992    ips = data;
993    if (!ips) return;
994
995    if (ec != ips->ec)
996      return;
997
998    if (ips->resizing)
999      return;
1000
1001    evas_object_geometry_get(ec->frame, NULL, NULL, &w, &h);
1002
1003    cur_angle = ec->e.state.rot.ang.curr;
1004    switch (cur_angle)
1005      {
1006       case 0:   i = 0; break;
1007       case 90:  i = 1; break;
1008       case 180: i = 2; break;
1009       case 270: i = 3; break;
1010       default:  i = 0; break;
1011      }
1012
1013    if ((w != ec->e.state.rot.geom[i].w) ||
1014        (h != ec->e.state.rot.geom[i].h))
1015      {
1016         LOGD("Resizing by Rotation Geometry. Pending Drawing...");
1017         _e_input_panel_stop_drawing(ips);
1018      }
1019 }
1020
1021 static void
1022 _e_input_panel_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
1023 {
1024    E_Input_Panel *input_panel = wl_resource_get_user_data(resource);
1025    E_Client *ec = wl_resource_get_user_data(surface_resource);
1026    E_Input_Panel_Surface *ips = NULL;
1027    E_Comp_Client_Data *cdata = NULL;
1028
1029    LOGD("client %p input_panel %p ec %p resource %p surface_resource %p",
1030            client, input_panel, ec, resource, surface_resource);
1031
1032    if (!input_panel)
1033      {
1034         WTI_WARNING(resource,
1035                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1036                     "No Input Panel Surface For Surface");
1037         return;
1038      }
1039
1040    if (!ec)
1041      {
1042         WTI_WARNING(surface_resource,
1043                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1044                     "No E_Client Set On Surface");
1045         return;
1046      }
1047
1048    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL)
1049      return;
1050
1051    if (!(cdata = ec->comp_data))
1052      {
1053         WTI_WARNING(surface_resource,
1054                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1055                     "No Data For Client");
1056         return;
1057      }
1058
1059    /* check for existing shell surface */
1060    if (cdata->shell.surface)
1061      {
1062         WTI_WARNING(surface_resource,
1063                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1064                     "Client already has shell surface");
1065         return;
1066      }
1067
1068    if (!(cdata->shell.surface =
1069          wl_resource_create(client, &wl_input_panel_surface_interface, 1, id)))
1070      {
1071         wl_resource_post_no_memory(surface_resource);
1072         /* NOTE: Cleanup E_client. */
1073         return;
1074      }
1075
1076    if (ec->ignored)
1077        e_client_unignore(ec);
1078
1079    /* set input panel client properties */
1080    ec->borderless = EINA_TRUE;
1081    ec->argb = EINA_TRUE;
1082    ec->lock_border = EINA_TRUE;
1083    ec->lock_focus_in = ec->lock_focus_out = EINA_TRUE;
1084    ec->netwm.state.skip_taskbar = EINA_TRUE;
1085    ec->netwm.state.skip_pager = EINA_TRUE;
1086    ec->no_shape_cut = EINA_TRUE;
1087    ec->border_size = 0;
1088    ec->vkbd.vkbd = 1;
1089    ec->icccm.window_role = eina_stringshare_add("input_panel_surface");
1090    if (!ec->icccm.title)
1091      ec->icccm.title = eina_stringshare_add("Keyboard");
1092
1093    /* skip iconify */
1094    ec->exp_iconify.skip_iconify = 1;
1095    evas_object_layer_set(ec->frame, E_LAYER_CLIENT_ABOVE);
1096    e_client_raise(ec);
1097
1098    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE, _e_ips_cb_evas_resize, ec);
1099    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOUSE_UP, _e_ips_cb_mouse_up, ec);
1100    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOUSE_DOWN, _e_ips_cb_mouse_down, ec);
1101    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOUSE_MOVE, _e_ips_cb_mouse_move, ec);
1102
1103    cdata->surface = surface_resource;
1104    cdata->shell.configure_send = NULL;
1105    cdata->shell.configure = _e_input_panel_surface_configure;
1106    cdata->shell.ping = NULL;
1107    cdata->shell.map = _e_input_panel_surface_map;
1108    cdata->shell.unmap = _e_input_panel_surface_unmap;
1109
1110    if (!(ips = E_NEW(E_Input_Panel_Surface, 1)))
1111      {
1112         wl_client_post_no_memory(client);
1113         return;
1114      }
1115
1116    ips->ec = ec;
1117    ips->input_panel = input_panel;
1118
1119    LOGD("Create IPS.. ips:%p, input_panel:%p, ec:%p", ips, input_panel, ec);
1120
1121    _e_input_panel_surface_append(input_panel, ips, resource);
1122
1123    wl_resource_set_implementation(cdata->shell.surface,
1124                                   &_e_input_panel_surface_implementation,
1125                                   ips, _e_input_panel_surface_resource_destroy);
1126
1127    ips->eh.rot_change_end =
1128       ecore_event_handler_add(E_EVENT_CLIENT_ROTATION_CHANGE_END,
1129                               _e_input_panel_client_cb_rotation_change_end, ips);
1130
1131    ips->eh.rot_geometry_set =
1132       ecore_event_handler_add(E_EVENT_CLIENT_ROTATION_GEOMETRY_SET,
1133                               _e_input_panel_client_cb_rotation_geometry_set, ips);
1134
1135
1136    ips->hook_del = e_client_hook_add(E_CLIENT_HOOK_DEL, _e_input_panel_client_cb_remove, ips);
1137    ips->hook_rotation_geometry_set = e_policy_hook_add(E_POLICY_HOOK_CLIENT_ROTATION_GEOMETRY_SET, _e_input_panel_rotation_geometry_set, ips);
1138
1139    // base_output_resolution.
1140    e_client_base_output_resolution_update(ec);
1141 }
1142
1143
1144 static const struct wl_input_panel_interface _e_input_panel_implementation = {
1145      _e_input_panel_cb_surface_get
1146 };
1147
1148 static void
1149 _e_input_panel_unbind(struct wl_resource *resource)
1150 {
1151    Eina_List *l;
1152    Eina_List *l_next;
1153    E_Input_Panel_Surface *ips;
1154    E_Input_Panel *input_panel = wl_resource_get_user_data(resource);
1155
1156    LOGD("resource %p input_panel %p", resource, input_panel);
1157
1158    if (!input_panel)
1159      {
1160         WTI_WARNING(resource,
1161                     WL_DISPLAY_ERROR_INVALID_OBJECT,
1162                     "No Input Panel For Resource");
1163         return;
1164      }
1165
1166    input_panel->resource = NULL;
1167
1168    EINA_LIST_FOREACH_SAFE(input_panel->surfaces, l, l_next, ips)
1169      {
1170         LOGD("foreach ips %p resource %p l %p", ips, resource, l);
1171         if (ips && ips->resource == resource)
1172           {
1173              E_Client *ec;
1174              E_Comp_Wl_Client_Data *cdata;
1175
1176              input_panel->surfaces = eina_list_remove_list(input_panel->surfaces, l);
1177              LOGD("Removed surface %p from list %p", l, input_panel->surfaces);
1178
1179              if (!(ec = ips->ec)) continue;
1180              if (e_object_is_del(E_OBJECT(ec))) continue;
1181              if (!(cdata = ec->comp_data)) continue;
1182
1183              cdata->shell.surface = NULL;
1184           }
1185      }
1186 }
1187
1188 static void
1189 _e_input_panel_bind(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
1190 {
1191    E_Input_Panel *input_panel = data;
1192    struct wl_resource *resource;
1193
1194    if (!input_panel) return;
1195
1196    if (input_panel->resource)
1197      _e_input_panel_unbind(input_panel->resource);
1198
1199    resource = wl_resource_create(client, &wl_input_panel_interface, 1, id);
1200    if (!resource) return;
1201
1202    LOGD("client %p input_panel %p resource %p", client, input_panel, resource);
1203
1204    if (input_panel->resource == NULL)
1205      {
1206         wl_resource_set_implementation(resource,
1207                                        &_e_input_panel_implementation,
1208                                        input_panel, _e_input_panel_unbind);
1209
1210         input_panel->resource = resource;
1211
1212         return;
1213      }
1214
1215    WTI_WARNING(resource,
1216                WL_DISPLAY_ERROR_INVALID_OBJECT,
1217                "input_panel object already bound");
1218 }
1219
1220 void
1221 e_input_panel_visibility_change(Eina_Bool visible)
1222 {
1223    E_Input_Panel_Surface *ips;
1224    Eina_List *l;
1225
1226    /* Here, if we are trying to show input panel, we can't guarantee our SHOW request
1227     * will succeed or not at this point (input panel may not have created its surface)
1228     * so set panel_show_need_rerun to TRUE to try showing it again afterwards */
1229    e_input_panel_show_need_rerun_set(visible);
1230
1231    if (!g_input_panel) return;
1232
1233    LOGD("e_input_panel_visibility_change : %d", visible);
1234
1235    vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, visible ? VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW : VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
1236
1237    EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1238      {
1239         if (!ips || !ips->ec) continue;
1240         ips->showing = visible;
1241         _e_input_panel_surface_visible_update(ips);
1242      }
1243
1244    _wait_update_timer_del();
1245 }
1246
1247 Eina_Bool
1248 e_input_panel_client_find(E_Client *ec)
1249 {
1250    E_Input_Panel_Surface *ips;
1251    Eina_List *l;
1252
1253    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1254
1255    if (!g_input_panel) return EINA_FALSE;
1256
1257    EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1258      {
1259         if (!ips || !ips->ec) continue;
1260         if (ips->ec == ec) return EINA_TRUE;
1261      }
1262
1263    return EINA_FALSE;
1264 }
1265
1266 /* If ec is NULL, it will check the very first item that is found in our surfaces list */
1267 Eina_Bool
1268 e_input_panel_client_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
1269 {
1270     E_Input_Panel_Surface *ips;
1271     Eina_List *l;
1272     int angle = 0;
1273
1274     if (!g_input_panel) return EINA_FALSE;
1275     if (!x || !y || !w || !h) return EINA_FALSE;
1276
1277     EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1278     {
1279         if (!ips || !ips->ec) continue;
1280         if (ips->ec == ec || !ec)
1281           {
1282             angle = ips->ec->e.state.rot.ang.next < 0 ?
1283                     ips->ec->e.state.rot.ang.curr :
1284                     ips->ec->e.state.rot.ang.next;
1285
1286             switch (angle)
1287               {
1288                case 90:
1289                case 270:
1290                   *x = ips->ec->y;
1291                   *y = ips->ec->x;
1292                   *w = ips->ec->h;
1293                   *h = ips->ec->w;
1294                   break;
1295                default:
1296                   *x = ips->ec->x;
1297                   *y = ips->ec->y;
1298                   *w = ips->ec->w;
1299                   *h = ips->ec->h;
1300                   break;
1301               }
1302
1303             return EINA_TRUE;
1304         }
1305     }
1306
1307     return EINA_FALSE;
1308 }
1309
1310 static Eina_Bool
1311 _e_input_panel_idle_enter(void *data)
1312 {
1313    E_Input_Panel_Surface *ips;
1314    Eina_List *l;
1315
1316    EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1317      {
1318         if (!ips) continue;
1319
1320         if (ips->need_show)
1321           {
1322              if (!_e_input_panel_is_effect_running(ips->ec))
1323                {
1324                   if (ips->resizing)
1325                     continue;
1326                   _ips_show(ips->ec);
1327                   ips->need_show = EINA_FALSE;
1328                }
1329           }
1330      }
1331
1332    return ECORE_CALLBACK_RENEW;
1333 }
1334
1335 Eina_Bool
1336 e_input_panel_init(void)
1337 {
1338    if (!e_comp_wl) return EINA_FALSE;
1339
1340    if (!(g_input_panel = E_NEW(E_Input_Panel, 1)))
1341      {
1342         /* ERR("Failed to allocate space for E_Input_Panel"); */
1343         return EINA_FALSE;
1344      }
1345
1346    g_input_panel->global = wl_global_create(e_comp_wl->wl.disp,
1347                                             &wl_input_panel_interface, 1,
1348                                             g_input_panel, _e_input_panel_bind);
1349
1350    if (!g_input_panel->global)
1351      {
1352         free(g_input_panel);
1353         g_input_panel = NULL;
1354         /* ERR("Failed to create global of wl_input_panel"); */
1355         return EINA_FALSE;
1356      }
1357
1358    g_input_panel->idle_enter = ecore_idle_enterer_add(_e_input_panel_idle_enter, NULL);
1359    g_floating_info = E_NEW(E_Input_Panel_Floating_Info, 1);
1360
1361    return EINA_TRUE;
1362 }
1363
1364 void
1365 e_input_panel_shutdown(void)
1366 {
1367     if (g_input_panel)
1368       {
1369          if (g_input_panel->resource)
1370            {
1371               wl_resource_destroy(g_input_panel->resource);
1372               g_input_panel->resource = NULL;
1373            }
1374
1375          if (g_input_panel->global)
1376            {
1377               wl_global_destroy(g_input_panel->global);
1378               g_input_panel->global = NULL;
1379            }
1380
1381          E_FREE_FUNC(g_input_panel->idle_enter, ecore_idle_enterer_del);
1382       }
1383
1384     if (g_floating_info)
1385       E_FREE(g_floating_info);
1386 }
1387
1388 static void
1389 _ips_client_frame_flush(E_Input_Panel_Surface  *ips)
1390 {
1391    if (!ips->ec)
1392      return;
1393
1394    if (e_object_is_del(E_OBJECT(ips->ec)))
1395      return;
1396
1397    LOGD("IPS::FRAME::FLUSH ec %p\n", ips->ec);
1398    e_pixmap_image_clear(ips->ec->pixmap, EINA_TRUE);
1399 }
1400
1401 static Eina_Bool
1402 _ip_cb_e_buf_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
1403 {
1404    E_Event_Client *ev;
1405    E_Input_Panel_Surface *ips;
1406    Eina_List *l;
1407
1408    ev = event;
1409    if (EINA_UNLIKELY(!ev))
1410      goto end;
1411
1412    if (EINA_UNLIKELY(!g_input_panel))
1413      goto end;
1414
1415    EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1416      {
1417         if (!ips || ips->ec != ev->ec) continue;
1418         _ips_client_frame_flush(ips);
1419      }
1420
1421 end:
1422    return ECORE_CALLBACK_PASS_ON;
1423 }
1424
1425 EINTERN void
1426 e_input_panel_wait_update_set(Eina_Bool wait_update)
1427 {
1428    E_Input_Panel_Surface *ips;
1429    Eina_List *l;
1430
1431    if (!g_input_panel)
1432      return;
1433
1434    g_input_panel->wait_update = wait_update;
1435
1436    /* If we are in wait_update mode, the input panel surfaces have to be updated forcibly */
1437    if (wait_update)
1438      {
1439         LOGD("Registering wait_update_timer");
1440         _wait_update_timer_del();
1441         g_timer_wait_update = ecore_timer_add(WAIT_UPDATE_TIMER_INTERVAL,
1442                                               _wait_update_timer_handler, NULL);
1443
1444         EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1445           {
1446              if (!ips || !ips->ec) continue;
1447              _ips_client_frame_flush(ips);
1448           }
1449
1450         if (!g_input_panel->buf_change_handler)
1451           {
1452              LOGD("IPS::WAIT::UPDATE::SET (add buf change handler)\n");
1453              g_input_panel->buf_change_handler = ecore_event_handler_add(E_EVENT_CLIENT_BUFFER_CHANGE,
1454                                                                          _ip_cb_e_buf_change, NULL);
1455           }
1456      }
1457    else
1458      E_FREE_FUNC(g_input_panel->buf_change_handler, ecore_event_handler_del);
1459 }
1460
1461 EINTERN void
1462 e_input_panel_transient_for_set(E_Client *parent)
1463 {
1464    LOGD("TRANSIENT_FOR::transient_for_set : %p\n", parent);
1465    E_Input_Panel_Surface *ips;
1466    Eina_List *l;
1467    E_Client *ec_parent = parent;
1468
1469    /* finding the actual parent window that contains the remote surface. */
1470    if (ec_parent)
1471      {
1472         if (!e_object_is_del(E_OBJECT(ec_parent)) &&
1473             (ec_parent->comp_data) && (ec_parent->comp_data->remote_surface.onscreen_parent))
1474           {
1475              ec_parent = ec_parent->comp_data->remote_surface.onscreen_parent;
1476           }
1477      }
1478
1479    EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1480      {
1481         if (!ips) continue;
1482         E_Client *child = ips->ec;
1483
1484         if (!child) continue;
1485         if (e_object_is_del(E_OBJECT(child)))
1486           {
1487              LOGE("child is deleted");
1488              continue;
1489           }
1490
1491         /* If the child already has a parent, remove it */
1492         if (child->parent)
1493           {
1494              if (e_object_is_del(E_OBJECT(child->parent)))
1495                {
1496                   LOGE("child->parent is deleted");
1497                   continue;
1498                }
1499
1500              LOGD("TRANSIENT_FOR::The child already has a parent : %p\n", child->parent);
1501              if (ec_parent != child->parent)
1502                {
1503                   child->parent->transients =
1504                      eina_list_remove(child->parent->transients, child);
1505                   if (child->parent->modal == child) child->parent->modal = NULL;
1506                   child->parent = NULL;
1507                   LOGD("TRANSIENT_FOR::reset parent %p for : %p\n", child->parent, child);
1508                }
1509           }
1510
1511         /* Append our child into parent's transients list */
1512         if ((ec_parent != child) && (ec_parent != child->parent))
1513           {
1514              if ((ec_parent) && (eina_list_data_find(parent->transients, child) != child))
1515                {
1516                   LOGD("TRANSIENT_FOR::Adding %p into parent %p's transients list\n", child, ec_parent);
1517                   ec_parent->transients = eina_list_append(ec_parent->transients, child);
1518                }
1519              child->parent = ec_parent;
1520           }
1521
1522         if (ec_parent)
1523           {
1524              child->icccm.fetch.transient_for = EINA_TRUE;
1525              child->icccm.transient_for = e_client_util_win_get(ec_parent);
1526           }
1527         else
1528           {
1529               child->icccm.fetch.transient_for = EINA_FALSE;
1530               child->icccm.transient_for = 0;
1531           }
1532         EC_CHANGED(child);
1533      }
1534 }
1535
1536 void
1537 e_input_panel_show_need_rerun_set(Eina_Bool need_rerun)
1538 {
1539    panel_show_need_rerun = need_rerun;
1540 }
1541
1542 void
1543 e_input_panel_floating_position_set(int x, int y)
1544 {
1545    int cur_angle;
1546    E_Client *floating_ec = NULL;
1547    E_Input_Panel_Surface *floating_ips;
1548    E_Input_Panel_Surface *ips;
1549    Eina_List *l;
1550    Eina_List *l_next;
1551
1552    EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
1553      {
1554         if (!ips || !ips->ec) continue;
1555         if (ips->ec->frame && ips->ec->vkbd.floating)
1556           {
1557              floating_ec = ips->ec;
1558              floating_ips = ips;
1559              break;
1560           }
1561      }
1562
1563    if (!floating_ec || !floating_ips || !g_floating_info) return;
1564
1565    if(floating_ips->showing)
1566       cur_angle = floating_ec->e.state.rot.ang.curr;
1567    else
1568       cur_angle = floating_ec->zone->rot.curr;
1569
1570    LOGD("current angle : %d", cur_angle);
1571    switch (cur_angle)
1572      {
1573         case 90:
1574         case 270:
1575            g_floating_info->start_position.landscape_x = x;
1576            g_floating_info->start_position.landscape_y = y;
1577            g_floating_info->init_landscape_position = EINA_TRUE;
1578            break;
1579         case 0:
1580         case 180:
1581         default:
1582            g_floating_info->start_position.portrait_x = x;
1583            g_floating_info->start_position.portrait_y = y;
1584            g_floating_info->init_portrait_position = EINA_TRUE;
1585            break;
1586      }
1587
1588    if(floating_ips->showing)
1589       _e_input_panel_position_set(floating_ec, floating_ec->client.w, floating_ec->client.h);
1590 }
1591
1592 Eina_Bool
1593 e_input_panel_surface_destroy(E_Client *ec)
1594 {
1595    LOGD("");
1596    E_Input_Panel_Surface *ips;
1597    Eina_List *l;
1598    Eina_List *l_next;
1599
1600    if (!g_input_panel) return EINA_FALSE;
1601
1602    EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
1603      {
1604         if (!ips || !ips->ec) continue;
1605         if (ips->ec == ec)
1606           {
1607              g_input_panel->surfaces = eina_list_remove_list(g_input_panel->surfaces, l);
1608              if (ips->resizing)
1609                {
1610                   LOGD("Destroyed Waiting Resize Window. Starting Drawing Again");
1611                   _e_input_panel_start_drawing(ips);
1612                }
1613           }
1614      }
1615
1616    return EINA_TRUE;
1617 }
1618
1619 /* check whether the keyboard effect is running or not
1620    - 0         : effect is not running,
1621    - otherwise : effect is running                    */
1622 int e_input_panel_is_effect_running(void)
1623 {
1624    E_Input_Panel_Surface *ips = NULL;
1625    Eina_List *l = NULL;
1626    int run_type = 0;
1627
1628    EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1629      {
1630         if (!ips || !ips->ec) continue;
1631         if (_e_input_panel_is_effect_running(ips->ec))
1632           {
1633              /*
1634                 Do we need to check currently effect type?
1635                 then what flag do we check? ips->ec->visible or ips->showing?
1636              */
1637              if (ips->ec->visible)
1638                run_type = 1; // show effect is running
1639              else
1640                run_type = 2; // hide effect is running
1641
1642              break;
1643           }
1644      }
1645
1646    return run_type;
1647 }