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