3 #include "e_mod_main.h"
5 #include <vconf-keys.h>
6 #include <input-method-server-protocol.h>
8 #define WTI_WARNING(resource, code, msg) (_e_input_panel_log_show((resource), (code), (msg), __func__))
9 #define WAIT_UPDATE_TIMER_INTERVAL 2.0f
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;
17 E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE,
18 E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL,
19 } E_Input_Panel_Coordinate_Type;
23 struct wl_global *global;
24 struct wl_resource *resource;
27 Ecore_Event_Handler *buf_change_handler;
28 Ecore_Idle_Enterer *idle_enter;
30 Eina_Bool wait_update; /* wait update state for global input panel object */
33 struct _E_Input_Panel_Surface
35 struct wl_resource *resource;
37 E_Input_Panel *input_panel;
42 Ecore_Event_Handler *rot_change_end;
43 Ecore_Event_Handler *buf_change;
44 Ecore_Event_Handler *rot_geometry_set;
52 Ecore_Timer *resize_timer;
56 E_Client_Hook *hook_del;
57 E_Policy_Hook *hook_rotation_geometry_set;
60 struct _E_Input_Panel_Floating_Info
63 Eina_Bool mouse_pressed;
64 Eina_Bool init_portrait_position;
65 Eina_Bool init_landscape_position;
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;
84 static E_Input_Panel_Surface *
85 _e_input_panel_surface_get(E_Client *ec)
87 E_Input_Panel_Surface *ips;
91 if (!g_input_panel) return NULL;
93 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
95 if (!ips || !ips->ec) continue;
106 _e_input_panel_start_drawing(E_Input_Panel_Surface *ips)
109 if (!ips->resizing) return;
111 if (ips->resize_timer)
113 ecore_timer_del(ips->resize_timer);
114 ips->resize_timer = NULL;
117 LOGI("Norender pop by resizing keyboard");
118 e_comp_canvas_norender_pop();
119 ips->resizing = EINA_FALSE;
123 _resize_timeout_cb(void *data)
125 E_Input_Panel_Surface *ips = NULL;
127 LOGE("TIMED OUT while waiting for resizing keyboard");
130 if (!ips) return ECORE_CALLBACK_CANCEL;
132 LOGI("Norender pop by resizing keyboard timeout");
133 e_comp_canvas_norender_pop();
134 ips->resizing = EINA_FALSE;
136 return ECORE_CALLBACK_CANCEL;
140 _e_input_panel_stop_drawing(E_Input_Panel_Surface *ips)
143 if (ips->resizing) return;
145 LOGI("Norender push by resizing keyboard");
146 e_comp_canvas_norender_push();
147 ips->resizing = EINA_TRUE;
149 if (!ips->resize_timer)
151 ips->resize_timer = ecore_timer_add(WAIT_UPDATE_TIMER_INTERVAL,
152 _resize_timeout_cb, ips);
157 _e_input_panel_log_show(struct wl_resource *resource, uint32_t code, const char *msg, const char *warning_msg)
159 LOGW("%s() is failed\n", warning_msg);
160 wl_resource_post_error(resource, code, "%s", msg);
164 _e_input_panel_is_effect_running(E_Client *ec)
166 if ((e_comp_object_is_animating(ec->frame)) ||
167 (evas_object_data_get(ec->frame, "effect_running")))
173 _e_input_panel_surface_append(E_Input_Panel *input_panel, E_Input_Panel_Surface *ips, struct wl_resource *resource)
175 if (!input_panel || !ips) return;
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);
183 e_input_panel_transient_for_set(client_surface);
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);
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)
194 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
195 E_Input_Panel *input_panel = NULL;
199 WTI_WARNING(resource,
200 WL_DISPLAY_ERROR_INVALID_OBJECT,
201 "No Input Panel Surface For Surface");
205 if (!(input_panel = ips->input_panel)) return;
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)
211 _e_input_panel_surface_append(input_panel, ips, resource);
213 ips->panel = EINA_FALSE;
217 _e_input_panel_surface_cb_overlay_panel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
219 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
220 E_Input_Panel *input_panel = NULL;
224 WTI_WARNING(resource,
225 WL_DISPLAY_ERROR_INVALID_OBJECT,
226 "No Input Panel Surface For Surface");
230 if (!(input_panel = ips->input_panel)) return;
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)
236 _e_input_panel_surface_append(input_panel, ips, resource);
238 ips->panel = EINA_TRUE;
242 _e_input_panel_surface_show(E_Input_Panel_Surface *ips)
245 E_Input_Panel_Surface *surface = NULL;
246 E_Client *focused_ec = NULL;
248 if (!g_input_panel) return;
250 /* When NULL passed, find the most appropriate surface */
253 EINA_LIST_FOREACH(g_input_panel->surfaces, l, surface)
255 if (surface && surface->ec)
257 if (surface->ec->parent == e_client_focused_get())
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);
270 if (g_input_panel->wait_update)
272 focused_ec = e_client_focused_get();
273 e_input_panel_wait_update_set(EINA_FALSE);
276 if (ips->ec->parent == focused_ec)
278 e_policy_conformant_part_update(ips->ec);
279 e_input_panel_visibility_change(EINA_TRUE);
281 e_text_input_update_input_panel_state(EINA_TRUE);
284 e_input_panel_visibility_change(EINA_FALSE);
287 e_input_panel_visibility_change(EINA_FALSE);
291 static void _wait_update_timer_del()
293 if (g_timer_wait_update)
295 LOGI("deleting wait_update timer");
296 ecore_timer_del(g_timer_wait_update);
297 g_timer_wait_update = NULL;
302 _wait_update_timer_handler(void *data)
304 LOGE("TIMED OUT while waiting for ready_set");
306 _e_input_panel_surface_show(NULL);
308 g_timer_wait_update = NULL;
310 return ECORE_CALLBACK_CANCEL;
314 _e_input_panel_surface_cb_ready_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t state EINA_UNUSED)
316 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
318 if (!g_input_panel) return;
322 WTI_WARNING(resource,
323 WL_DISPLAY_ERROR_INVALID_OBJECT,
324 "No Input Panel Surface For Surface");
328 LOGI("IPS::SHOW::READY\n");
330 // base_output_resolution
331 e_client_base_output_resolution_transform_adjust(ips->ec);
333 _e_input_panel_surface_show(ips);
337 _e_input_panel_surface_cb_floating_panel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t state)
339 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
343 WTI_WARNING(resource,
344 WL_DISPLAY_ERROR_INVALID_OBJECT,
345 "No Input Panel Surface For Surface");
349 if (!ips->ec) return;
351 if (ips->ec->vkbd.floating == state) return;
353 ips->ec->vkbd.floating = !!state;
355 if (ips->ec->vkbd.floating)
356 e_policy_conformant_part_del(ips->ec);
358 e_policy_conformant_part_add(ips->ec);
362 _e_input_panel_surface_cb_floating_drag_enabled_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t enabled)
364 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
368 WTI_WARNING(resource,
369 WL_DISPLAY_ERROR_INVALID_OBJECT,
370 "No Input Panel Surface For Surface");
374 g_floating_info->moving_req = !!enabled;
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
386 _e_input_panel_surface_resource_destroy(struct wl_resource *resource)
389 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
390 E_Input_Panel *input_panel = NULL;
395 WTI_WARNING(resource,
396 WL_DISPLAY_ERROR_INVALID_OBJECT,
397 "No Input Panel Surface For Surface");
401 if (!(input_panel = ips->input_panel)) return;
404 if (ec && (!e_object_is_del(E_OBJECT(ec))))
408 if (ec->comp_data->mapped)
410 if ((ec->comp_data->shell.surface) &&
411 (ec->comp_data->shell.unmap))
412 ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
416 ec->parent->transients =
417 eina_list_remove(ec->parent->transients, ec);
419 ec->comp_data->shell.surface = NULL;
425 LOGI("Destroyed Waiting Resize Input Surface. Starting Drawing Again");
426 _e_input_panel_start_drawing(ips);
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);
441 _e_input_panel_init_floating_position(E_Client *ec)
445 if (!ec || !g_floating_info) return;
447 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
449 switch (ec->e.state.rot.ang.curr)
453 if (!g_floating_info->init_landscape_position)
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;
463 if (!g_floating_info->init_portrait_position)
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;
474 _e_input_panel_stay_within_screen(E_Client *ec, int x, int y, int *new_x, int *new_y)
478 if (!ec || !g_floating_info) return;
480 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
482 switch (ec->e.state.rot.ang.curr)
488 else if (x > zh - ec->client.h)
489 *new_x = zh - ec->client.h;
495 else if (y > zw - ec->client.w)
496 *new_y = zw - ec->client.w;
505 else if (x > zw - ec->client.w)
506 *new_x = zw - ec->client.w;
512 else if (y > zh - ec->client.h)
513 *new_y = zh - ec->client.h;
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)
526 if (!ec || !g_floating_info) return;
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);
533 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
538 if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
540 *new_x = zh - y - ec->client.h;
543 else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
546 *new_y = zh - x - ec->client.h;
550 if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
552 *new_x = zh - y - ec->client.h;
553 *new_y = zw - x - ec->client.w;
555 else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
557 *new_x = zw - x - ec->client.w;
558 *new_y = zh - y - ec->client.h;
562 if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
565 *new_y = zw - x - ec->client.w;
567 else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
569 *new_x = zw - y - ec->client.w;
582 _e_input_panel_position_set(E_Client *ec, int w, int h)
586 Eina_Bool is_portrait;
588 if (!ec || !g_floating_info) return;
590 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
592 /* Get the position of center bottom each angles */
593 switch (ec->e.state.rot.ang.curr)
597 ny = zy + (zh - h) / 2;
598 is_portrait = EINA_FALSE;
601 nx = zx + (zw - w) / 2;
603 is_portrait = EINA_TRUE;
607 ny = zy + (zh - h) / 2;
608 is_portrait = EINA_FALSE;
612 nx = zx + (zw - w) / 2;
614 is_portrait = EINA_TRUE;
618 if (ec->vkbd.floating)
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);
625 _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.portrait_x, g_floating_info->start_position.portrait_y, &sx, &sy);
627 _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.landscape_x, g_floating_info->start_position.landscape_y, &sx, &sy);
629 _e_input_panel_convert_floating_position(ec, sx, sy, &nx, &ny, E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL);
632 e_client_util_move_without_frame(ec, nx, ny);
636 _ips_show(E_Client *ec)
643 _e_input_panel_position_set(ec, ec->client.w, ec->client.h);
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);
652 _e_input_panel_surface_visible_update(E_Input_Panel_Surface *ips)
658 if (!(ec = ips->ec)) return;
660 if (e_object_is_del(E_OBJECT(ec))) return;
661 if ((ips->showing) && (e_pixmap_usable_get(ec->pixmap)))
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);
668 if (_e_input_panel_is_effect_running(ips->ec))
669 ips->need_show = EINA_TRUE;
670 else if (ips->resizing)
672 LOGI("Keyboard is currently resizing. set need_show.");
673 ips->need_show = EINA_TRUE;
678 ips->need_show = EINA_FALSE;
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;
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)
698 E_Input_Panel_Surface *ips;
701 if (!(ips = wl_resource_get_user_data(resource)))
703 WTI_WARNING(resource,
704 WL_DISPLAY_ERROR_INVALID_OBJECT,
705 "No Input Panel Surface For Surface");
711 WTI_WARNING(resource,
712 WL_DISPLAY_ERROR_INVALID_OBJECT,
713 "No Client For Input Panel Surface");
717 e_client_util_resize_without_frame(ec, w, h);
720 _e_input_panel_surface_visible_update(ips);
724 _e_input_panel_surface_map(struct wl_resource *resource)
726 E_Input_Panel_Surface *ips;
729 if (!(ips = wl_resource_get_user_data(resource)))
731 WTI_WARNING(resource,
732 WL_DISPLAY_ERROR_INVALID_OBJECT,
733 "No Input Panel Surface For Surface");
739 WTI_WARNING(resource,
740 WL_DISPLAY_ERROR_INVALID_OBJECT,
741 "No Client For Input Panel Surface");
747 WTI_WARNING(resource,
748 WL_DISPLAY_ERROR_INVALID_OBJECT,
749 "No Data For Client");
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)))
756 ec->comp_data->mapped = EINA_TRUE;
757 ec->first_mapped = EINA_TRUE;
762 _e_input_panel_surface_unmap(struct wl_resource *resource)
764 E_Input_Panel_Surface *ips = NULL;
767 if (!(ips = wl_resource_get_user_data(resource)))
769 WTI_WARNING(resource,
770 WL_DISPLAY_ERROR_INVALID_OBJECT,
771 "No Input Panel Surface For Surface");
777 WTI_WARNING(resource,
778 WL_DISPLAY_ERROR_INVALID_OBJECT,
779 "No Client For Input Panel Surface");
785 WTI_WARNING(resource,
786 WL_DISPLAY_ERROR_INVALID_OBJECT,
787 "No Data For Client");
791 if (e_object_is_del(E_OBJECT(ec))) return;
793 if (ec->comp_data->mapped)
795 ec->visible = EINA_FALSE;
796 evas_object_hide(ec->frame);
797 ec->comp_data->mapped = EINA_FALSE;
802 _e_input_panel_client_cb_rotation_change_end(void *data, int type, void *event)
805 E_Input_Panel_Surface *ips = data;
806 E_Event_Client_Rotation_Change_End *ev = event;
813 LOGI("current angle : %d", ec->e.state.rot.ang.curr);
814 _e_input_panel_position_set(ec, ec->client.w, ec->client.h);
818 return ECORE_CALLBACK_PASS_ON;
822 _e_input_panel_client_cb_rotation_geometry_set(void *data, int type, void *event)
825 E_Input_Panel_Surface *ips = data;
826 E_Event_Client_Rotation_Geometry_Set *ev = event;
840 if (ev->angle != ec->e.state.rot.ang.curr)
843 evas_object_geometry_get(ec->frame, NULL, NULL, &w, &h);
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;
854 if ((w != ec->e.state.rot.geom[i].w) ||
855 (h != ec->e.state.rot.geom[i].h))
857 LOGI("Resizing by Rotation Geometry. Pending Drawing");
858 _e_input_panel_stop_drawing(ips);
862 return ECORE_CALLBACK_PASS_ON;
866 _e_input_panel_client_cb_remove(void *data, E_Client *ec)
868 E_Input_Panel_Surface *ips = data;
872 LOGI("Remove IPS's ec. ips:%p, ips->ec:%p", ips, ips->ec);
878 _e_ips_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
880 E_Input_Panel_Surface *ips = NULL;
887 if (e_object_is_del(E_OBJECT(ec)))
890 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
892 LOGI("current angle : %d", ec->e.state.rot.ang.curr);
893 _e_input_panel_position_set(ec, w, h);
895 ips = _e_input_panel_surface_get(ec);
897 if (!ips->resizing) return;
899 angle = ec->e.state.rot.ang.curr;
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;
909 if ((w == ec->e.state.rot.geom[i].w) ||
910 (h == ec->e.state.rot.geom[i].h))
912 LOGI("Resize Done to Rotation Geometry. Starting Drawing Again");
913 _e_input_panel_start_drawing(ips);
918 _e_input_panel_effect_end(void *data, E_Client *ec)
920 E_Input_Panel_Surface *ips = data;
921 if (!ips) return EINA_TRUE;
923 LOGI("Effect end IPS's ec. ips:%p, ips->ec:%p", ips, ips->ec);
926 vconf_set_int(VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_DID_HIDE);
932 _e_ips_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
937 if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
940 g_floating_info->mouse_pressed = EINA_FALSE;
941 g_floating_info->moving_req = EINA_FALSE;
943 LOGI("[Mouse up] Send input panel geometry");
944 e_text_input_update_input_panel_geometry(ec);
948 _e_ips_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
951 Evas_Event_Mouse_Move *ev = event_info;
954 if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
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;
963 _e_ips_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
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;
972 if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
975 if (!g_floating_info->moving_req || !g_floating_info->mouse_pressed)
978 evas_object_geometry_get(obj, &x, &y, &w, &h);
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);
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);
986 g_floating_info->before_canvas_x = ev->cur.canvas.x;
987 g_floating_info->before_canvas_y = ev->cur.canvas.y;
989 if (ec->e.state.rot.ang.curr == 90 || ec->e.state.rot.ang.curr == 270)
991 g_floating_info->start_position.landscape_x = n_x;
992 g_floating_info->start_position.landscape_y = n_y;
996 g_floating_info->start_position.portrait_x = n_x;
997 g_floating_info->start_position.portrait_y = n_y;
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);
1005 _e_input_panel_rotation_geometry_set(void *data, E_Client *ec)
1007 E_Input_Panel_Surface *ips;
1021 evas_object_geometry_get(ec->frame, NULL, NULL, &w, &h);
1023 cur_angle = ec->e.state.rot.ang.curr;
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;
1033 if ((w != ec->e.state.rot.geom[i].w) ||
1034 (h != ec->e.state.rot.geom[i].h))
1036 LOGI("Resizing by Rotation Geometry. Pending Drawing...");
1037 _e_input_panel_stop_drawing(ips);
1042 _e_input_panel_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
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;
1049 LOGI("client %p input_panel %p ec %p resource %p surface_resource %p",
1050 client, input_panel, ec, resource, surface_resource);
1054 WTI_WARNING(resource,
1055 WL_DISPLAY_ERROR_INVALID_OBJECT,
1056 "No Input Panel Surface For Surface");
1062 WTI_WARNING(surface_resource,
1063 WL_DISPLAY_ERROR_INVALID_OBJECT,
1064 "No E_Client Set On Surface");
1068 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL)
1071 if (!(cdata = ec->comp_data))
1073 WTI_WARNING(surface_resource,
1074 WL_DISPLAY_ERROR_INVALID_OBJECT,
1075 "No Data For Client");
1079 /* check for existing shell surface */
1080 if (cdata->shell.surface)
1082 WTI_WARNING(surface_resource,
1083 WL_DISPLAY_ERROR_INVALID_OBJECT,
1084 "Client already has shell surface");
1088 if (!(cdata->shell.surface =
1089 wl_resource_create(client, &wl_input_panel_surface_interface, 1, id)))
1091 wl_resource_post_no_memory(surface_resource);
1092 /* NOTE: Cleanup E_client. */
1097 e_client_unignore(ec);
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;
1109 ec->icccm.window_role = eina_stringshare_add("input_panel_surface");
1110 if (!ec->icccm.title)
1111 ec->icccm.title = eina_stringshare_add("Keyboard");
1114 ec->exp_iconify.skip_iconify = 1;
1115 e_client_layer_set(ec, E_LAYER_CLIENT_ABOVE);
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);
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;
1130 if (!(ips = E_NEW(E_Input_Panel_Surface, 1)))
1132 wl_client_post_no_memory(client);
1137 ips->input_panel = input_panel;
1139 LOGI("Create IPS.. ips:%p, input_panel:%p, ec:%p", ips, input_panel, ec);
1141 _e_input_panel_surface_append(input_panel, ips, resource);
1143 wl_resource_set_implementation(cdata->shell.surface,
1144 &_e_input_panel_surface_implementation,
1145 ips, _e_input_panel_surface_resource_destroy);
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);
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);
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);
1158 E_COMP_COMP_HOOK_APPEND(ips->cp_hooks, E_COMP_OBJECT_HOOK_EFFECT_END, _e_input_panel_effect_end, ips);
1160 // base_output_resolution.
1161 e_client_base_output_resolution_update(ec);
1164 static const struct wl_input_panel_interface _e_input_panel_implementation = {
1165 _e_input_panel_cb_surface_get
1169 _e_input_panel_unbind(struct wl_resource *resource)
1173 E_Input_Panel_Surface *ips;
1174 E_Input_Panel *input_panel = wl_resource_get_user_data(resource);
1176 LOGI("resource %p input_panel %p", resource, input_panel);
1180 WTI_WARNING(resource,
1181 WL_DISPLAY_ERROR_INVALID_OBJECT,
1182 "No Input Panel For Resource");
1186 input_panel->resource = NULL;
1188 EINA_LIST_FOREACH_SAFE(input_panel->surfaces, l, l_next, ips)
1190 LOGI("foreach ips %p resource %p l %p", ips, resource, l);
1191 if (ips && ips->resource == resource)
1194 E_Comp_Wl_Client_Data *cdata;
1196 input_panel->surfaces = eina_list_remove_list(input_panel->surfaces, l);
1197 LOGI("Removed surface %p from list %p", l, input_panel->surfaces);
1199 if (!(ec = ips->ec)) continue;
1200 if (e_object_is_del(E_OBJECT(ec))) continue;
1201 if (!(cdata = ec->comp_data)) continue;
1203 cdata->shell.surface = NULL;
1209 _e_input_panel_bind(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
1211 E_Input_Panel *input_panel = data;
1212 struct wl_resource *resource;
1214 if (!input_panel) return;
1216 if (input_panel->resource)
1217 _e_input_panel_unbind(input_panel->resource);
1219 resource = wl_resource_create(client, &wl_input_panel_interface, 1, id);
1220 if (!resource) return;
1222 LOGI("client %p input_panel %p resource %p", client, input_panel, resource);
1224 if (input_panel->resource == NULL)
1226 wl_resource_set_implementation(resource,
1227 &_e_input_panel_implementation,
1228 input_panel, _e_input_panel_unbind);
1230 input_panel->resource = resource;
1235 WTI_WARNING(resource,
1236 WL_DISPLAY_ERROR_INVALID_OBJECT,
1237 "input_panel object already bound");
1241 e_input_panel_visibility_change(Eina_Bool visible)
1243 E_Input_Panel_Surface *ips;
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);
1251 if (!g_input_panel) return;
1253 LOGI("e_input_panel_visibility_change : %d", visible);
1255 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, visible ? VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW : VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
1257 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1259 if (!ips || !ips->ec) continue;
1260 ips->showing = visible;
1261 _e_input_panel_surface_visible_update(ips);
1264 _wait_update_timer_del();
1268 e_input_panel_client_find(E_Client *ec)
1270 E_Input_Panel_Surface *ips;
1273 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1275 if (!g_input_panel) return EINA_FALSE;
1277 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1279 if (!ips || !ips->ec) continue;
1280 if (ips->ec == ec) return EINA_TRUE;
1286 /* If ec is NULL, it will check the very first item that is found in our surfaces list */
1288 e_input_panel_client_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
1290 E_Input_Panel_Surface *ips;
1295 if (!g_input_panel) return EINA_FALSE;
1296 if (!x || !y || !w || !h) return EINA_FALSE;
1298 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1300 if (!ips || !ips->ec) continue;
1301 if (ips->ec == ec || !ec)
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;
1307 e_client_base_output_resolution_useful_geometry_get(ips->ec, &zx, &zy, &zw, &zh);
1311 *x = zh - ips->ec->y - ips->ec->client.h;
1317 *x = zh - ips->ec->y - ips->ec->client.h;
1318 *y = zw - ips->ec->x - ips->ec->client.w;
1324 *y = zw - ips->ec->x - ips->ec->client.w;
1345 _e_input_panel_idle_enter(void *data)
1347 E_Input_Panel_Surface *ips;
1350 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1356 if (!_e_input_panel_is_effect_running(ips->ec))
1361 ips->need_show = EINA_FALSE;
1366 return ECORE_CALLBACK_RENEW;
1370 e_input_panel_init(void)
1372 if (!e_comp_wl) return EINA_FALSE;
1374 if (!(g_input_panel = E_NEW(E_Input_Panel, 1)))
1376 /* ERR("Failed to allocate space for E_Input_Panel"); */
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);
1384 if (!g_input_panel->global)
1386 free(g_input_panel);
1387 g_input_panel = NULL;
1388 /* ERR("Failed to create global of wl_input_panel"); */
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);
1399 e_input_panel_shutdown(void)
1403 if (g_input_panel->resource)
1405 wl_resource_destroy(g_input_panel->resource);
1406 g_input_panel->resource = NULL;
1409 if (g_input_panel->global)
1411 wl_global_destroy(g_input_panel->global);
1412 g_input_panel->global = NULL;
1415 E_FREE_FUNC(g_input_panel->idle_enter, ecore_idle_enterer_del);
1418 if (g_floating_info)
1419 E_FREE(g_floating_info);
1423 _ips_client_frame_flush(E_Input_Panel_Surface *ips)
1428 if (e_object_is_del(E_OBJECT(ips->ec)))
1431 LOGI("IPS::FRAME::FLUSH ec %p\n", ips->ec);
1432 e_pixmap_image_clear(ips->ec->pixmap, EINA_TRUE);
1436 _ip_cb_e_buf_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
1439 E_Input_Panel_Surface *ips;
1443 if (EINA_UNLIKELY(!ev))
1446 if (EINA_UNLIKELY(!g_input_panel))
1449 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1451 if (!ips || ips->ec != ev->ec) continue;
1452 _ips_client_frame_flush(ips);
1456 return ECORE_CALLBACK_PASS_ON;
1460 e_input_panel_wait_update_set(Eina_Bool wait_update)
1462 E_Input_Panel_Surface *ips;
1468 g_input_panel->wait_update = wait_update;
1470 /* If we are in wait_update mode, the input panel surfaces have to be updated forcibly */
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);
1478 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1480 if (!ips || !ips->ec) continue;
1481 _ips_client_frame_flush(ips);
1484 if (!g_input_panel->buf_change_handler)
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);
1492 E_FREE_FUNC(g_input_panel->buf_change_handler, ecore_event_handler_del);
1496 e_input_panel_transient_for_set(E_Client *parent)
1498 LOGI("TRANSIENT_FOR::transient_for_set : %p\n", parent);
1499 E_Input_Panel_Surface *ips;
1501 E_Client *ec_parent = parent;
1503 /* finding the actual parent window that contains the remote surface. */
1506 if (!e_object_is_del(E_OBJECT(ec_parent)) &&
1507 (ec_parent->comp_data) && (ec_parent->comp_data->remote_surface.onscreen_parent))
1509 ec_parent = ec_parent->comp_data->remote_surface.onscreen_parent;
1513 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1516 E_Client *child = ips->ec;
1518 if (!child) continue;
1519 if (e_object_is_del(E_OBJECT(child)))
1521 LOGE("child is deleted");
1525 /* If the child already has a parent, remove it */
1528 if (e_object_is_del(E_OBJECT(child->parent)))
1530 LOGE("child->parent is deleted");
1534 LOGI("TRANSIENT_FOR::The child already has a parent : %p\n", child->parent);
1535 if (ec_parent != child->parent)
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);
1545 /* Append our child into parent's transients list */
1546 if ((ec_parent != child) && (ec_parent != child->parent))
1548 if ((ec_parent) && (eina_list_data_find(parent->transients, child) != child))
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);
1553 child->parent = ec_parent;
1558 child->icccm.fetch.transient_for = EINA_TRUE;
1559 child->icccm.transient_for = e_client_util_win_get(ec_parent);
1563 child->icccm.fetch.transient_for = EINA_FALSE;
1564 child->icccm.transient_for = 0;
1571 e_input_panel_show_need_rerun_set(Eina_Bool need_rerun)
1573 panel_show_need_rerun = need_rerun;
1577 e_input_panel_floating_position_set(int x, int y)
1580 E_Client *floating_ec = NULL;
1581 E_Input_Panel_Surface *floating_ips = NULL;
1582 E_Input_Panel_Surface *ips = NULL;
1586 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
1588 if (!ips || !ips->ec) continue;
1589 if (ips->ec->frame && ips->ec->vkbd.floating)
1591 floating_ec = ips->ec;
1597 if (!floating_ec || !floating_ips || !g_floating_info) return;
1599 if(floating_ips->showing)
1600 cur_angle = floating_ec->e.state.rot.ang.curr;
1602 cur_angle = floating_ec->zone->rot.curr;
1604 LOGI("current angle : %d", cur_angle);
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;
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;
1622 if(floating_ips->showing)
1623 _e_input_panel_position_set(floating_ec, floating_ec->client.w, floating_ec->client.h);
1627 e_input_panel_surface_destroy(E_Client *ec)
1630 E_Input_Panel_Surface *ips;
1634 if (!g_input_panel) return EINA_FALSE;
1636 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
1638 if (!ips || !ips->ec) continue;
1641 g_input_panel->surfaces = eina_list_remove_list(g_input_panel->surfaces, l);
1644 LOGI("Destroyed Waiting Resize Window. Starting Drawing Again");
1645 _e_input_panel_start_drawing(ips);
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)
1658 E_Input_Panel_Surface *ips = NULL;
1659 Eina_List *l = NULL;
1662 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1664 if (!ips || !ips->ec) continue;
1665 if (_e_input_panel_is_effect_running(ips->ec))
1668 Do we need to check currently effect type?
1669 then what flag do we check? ips->ec->visible or ips->showing?
1671 if (ips->ec->visible)
1672 run_type = 1; // show effect is running
1674 run_type = 2; // hide effect is running