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