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;
54 E_Client_Hook *hook_del;
55 E_Policy_Hook *hook_rotation_geometry_set;
58 struct _E_Input_Panel_Floating_Info
61 Eina_Bool mouse_pressed;
62 Eina_Bool init_portrait_position;
63 Eina_Bool init_landscape_position;
76 E_Input_Panel *g_input_panel = NULL;
77 E_Input_Panel_Floating_Info *g_floating_info = NULL;
78 Eina_List *handlers = NULL;
79 static Eina_Bool panel_show_need_rerun = EINA_FALSE;
80 static Ecore_Timer *g_timer_wait_update = NULL;
82 static E_Input_Panel_Surface *
83 _e_input_panel_surface_get(E_Client *ec)
85 E_Input_Panel_Surface *ips;
89 if (!g_input_panel) return NULL;
91 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
93 if (!ips || !ips->ec) continue;
104 _e_input_panel_start_drawing(E_Input_Panel_Surface *ips)
107 if (!ips->resizing) return;
109 if (ips->resize_timer)
111 ecore_timer_del(ips->resize_timer);
112 ips->resize_timer = NULL;
115 LOGD("Norender pop by resizing keyboard");
116 e_comp_canvas_norender_pop();
117 ips->resizing = EINA_FALSE;
121 _resize_timeout_cb(void *data)
123 E_Input_Panel_Surface *ips = NULL;
125 LOGE("TIMED OUT while waiting for resizing keyboard");
128 if (!ips) return ECORE_CALLBACK_CANCEL;
130 LOGD("Norender pop by resizing keyboard timeout");
131 e_comp_canvas_norender_pop();
132 ips->resizing = EINA_FALSE;
134 return ECORE_CALLBACK_CANCEL;
138 _e_input_panel_stop_drawing(E_Input_Panel_Surface *ips)
141 if (ips->resizing) return;
143 LOGD("Norender push by resizing keyboard");
144 e_comp_canvas_norender_push();
145 ips->resizing = EINA_TRUE;
147 if (!ips->resize_timer)
149 ips->resize_timer = ecore_timer_add(WAIT_UPDATE_TIMER_INTERVAL,
150 _resize_timeout_cb, ips);
155 _e_input_panel_log_show(struct wl_resource *resource, uint32_t code, const char *msg, const char *warning_msg)
157 LOGW("%s() is failed\n", warning_msg);
158 wl_resource_post_error(resource, code, "%s", msg);
162 _e_input_panel_is_effect_running(E_Client *ec)
164 if ((e_comp_object_is_animating(ec->frame)) ||
165 (evas_object_data_get(ec->frame, "effect_running")))
171 _e_input_panel_surface_append(E_Input_Panel *input_panel, E_Input_Panel_Surface *ips, struct wl_resource *resource)
173 if (!input_panel || !ips) return;
175 E_Client *client_surface = e_text_input_client_surface_get();
176 ips->resource = resource;
177 input_panel->surfaces = eina_list_append(input_panel->surfaces, ips);
178 LOGD("input_panel %p ips %p resource %p client surface %p", input_panel, ips, resource, client_surface);
181 e_input_panel_transient_for_set(client_surface);
183 /* When a new input panel surface is created and if we have failed
184 * showing input panel previously, try to show it again here */
185 if (input_panel->surfaces && panel_show_need_rerun)
186 e_input_panel_visibility_change(EINA_TRUE);
190 _e_input_panel_surface_cb_toplevel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *output_resource EINA_UNUSED, uint32_t position EINA_UNUSED)
192 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
193 E_Input_Panel *input_panel = NULL;
197 WTI_WARNING(resource,
198 WL_DISPLAY_ERROR_INVALID_OBJECT,
199 "No Input Panel Surface For Surface");
203 if (!(input_panel = ips->input_panel)) return;
205 /* Do not append duplicated surface - And need to check if the surface really needs to be appended here,
206 * since the newly created surface is already being appended at function _e_input_panel_cb_surface_get() */
207 if (eina_list_data_find(input_panel->surfaces, ips) != ips)
209 _e_input_panel_surface_append(input_panel, ips, resource);
211 ips->panel = EINA_FALSE;
215 _e_input_panel_surface_cb_overlay_panel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
217 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
218 E_Input_Panel *input_panel = NULL;
222 WTI_WARNING(resource,
223 WL_DISPLAY_ERROR_INVALID_OBJECT,
224 "No Input Panel Surface For Surface");
228 if (!(input_panel = ips->input_panel)) return;
230 /* Do not append duplicated surface - And need to check if the surface really needs to be appended here,
231 * since the newly created surface is already being appended at function _e_input_panel_cb_surface_get() */
232 if (eina_list_data_find(input_panel->surfaces, ips) != ips)
234 _e_input_panel_surface_append(input_panel, ips, resource);
236 ips->panel = EINA_TRUE;
240 _e_input_panel_surface_show(E_Input_Panel_Surface *ips)
243 E_Input_Panel_Surface *surface = NULL;
244 E_Client *focused_ec = NULL;
246 if (!g_input_panel) return;
248 /* When NULL passed, find the most appropriate surface */
251 EINA_LIST_FOREACH(g_input_panel->surfaces, l, surface)
253 if (surface && surface->ec)
255 if (surface->ec->parent == e_client_focused_get())
265 LOGD("parent:%p, focus:%p, wait_update %d\n",
266 ips->ec ? ips->ec->parent : NULL, e_client_focused_get(), g_input_panel->wait_update);
268 if (g_input_panel->wait_update)
270 focused_ec = e_client_focused_get();
271 e_input_panel_wait_update_set(EINA_FALSE);
274 if (ips->ec->parent == focused_ec)
276 e_policy_conformant_part_update(ips->ec);
277 e_input_panel_visibility_change(EINA_TRUE);
279 e_text_input_update_input_panel_state(EINA_TRUE);
282 e_input_panel_visibility_change(EINA_FALSE);
285 e_input_panel_visibility_change(EINA_FALSE);
289 static void _wait_update_timer_del()
291 if (g_timer_wait_update)
293 LOGD("deleting wait_update timer");
294 ecore_timer_del(g_timer_wait_update);
295 g_timer_wait_update = NULL;
300 _wait_update_timer_handler(void *data)
302 LOGE("TIMED OUT while waiting for ready_set");
304 _e_input_panel_surface_show(NULL);
306 g_timer_wait_update = NULL;
308 return ECORE_CALLBACK_CANCEL;
312 _e_input_panel_surface_cb_ready_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t state EINA_UNUSED)
314 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
316 if (!g_input_panel) return;
320 WTI_WARNING(resource,
321 WL_DISPLAY_ERROR_INVALID_OBJECT,
322 "No Input Panel Surface For Surface");
326 LOGD("IPS::SHOW::READY\n");
328 // base_output_resolution
329 e_client_base_output_resolution_transform_adjust(ips->ec);
331 _e_input_panel_surface_show(ips);
335 _e_input_panel_surface_cb_floating_panel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t state)
337 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
341 WTI_WARNING(resource,
342 WL_DISPLAY_ERROR_INVALID_OBJECT,
343 "No Input Panel Surface For Surface");
347 if (!ips->ec) return;
349 if (ips->ec->vkbd.floating == state) return;
351 ips->ec->vkbd.floating = !!state;
353 if (ips->ec->vkbd.floating)
354 e_policy_conformant_part_del(ips->ec);
356 e_policy_conformant_part_add(ips->ec);
360 _e_input_panel_surface_cb_floating_drag_enabled_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t enabled)
362 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
366 WTI_WARNING(resource,
367 WL_DISPLAY_ERROR_INVALID_OBJECT,
368 "No Input Panel Surface For Surface");
372 g_floating_info->moving_req = !!enabled;
375 static const struct wl_input_panel_surface_interface _e_input_panel_surface_implementation = {
376 _e_input_panel_surface_cb_toplevel_set,
377 _e_input_panel_surface_cb_overlay_panel_set,
378 _e_input_panel_surface_cb_ready_set,
379 _e_input_panel_surface_cb_floating_panel_set,
380 _e_input_panel_surface_cb_floating_drag_enabled_set
384 _e_input_panel_surface_resource_destroy(struct wl_resource *resource)
387 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
388 E_Input_Panel *input_panel = NULL;
393 WTI_WARNING(resource,
394 WL_DISPLAY_ERROR_INVALID_OBJECT,
395 "No Input Panel Surface For Surface");
399 if (!(input_panel = ips->input_panel)) return;
402 if (ec && (!e_object_is_del(E_OBJECT(ec))))
406 if (ec->comp_data->mapped)
408 if ((ec->comp_data->shell.surface) &&
409 (ec->comp_data->shell.unmap))
410 ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
414 ec->parent->transients =
415 eina_list_remove(ec->parent->transients, ec);
417 ec->comp_data->shell.surface = NULL;
423 LOGD("Destroyed Waiting Resize Input Surface. Starting Drawing Again");
424 _e_input_panel_start_drawing(ips);
427 LOGD("Removing ips %p from input panel %p", ips, input_panel);
428 input_panel->surfaces = eina_list_remove(input_panel->surfaces, ips);
429 E_FREE_FUNC(ips->eh.rot_geometry_set, ecore_event_handler_del);
430 E_FREE_FUNC(ips->eh.rot_change_end, ecore_event_handler_del);
431 E_FREE_FUNC(ips->eh.buf_change, ecore_event_handler_del);
432 E_FREE_FUNC(ips->hook_del, e_client_hook_del);
433 E_FREE_FUNC(ips->hook_rotation_geometry_set, e_policy_hook_del);
438 _e_input_panel_init_floating_position(E_Client *ec)
442 if (!ec || !g_floating_info) return;
444 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
446 switch (ec->e.state.rot.ang.curr)
450 if (!g_floating_info->init_landscape_position)
452 g_floating_info->start_position.landscape_x = (zh - ec->client.h) / 2;
453 g_floating_info->start_position.landscape_y = (zw - ec->client.w) / 2;
454 g_floating_info->init_landscape_position = EINA_TRUE;
460 if (!g_floating_info->init_portrait_position)
462 g_floating_info->start_position.portrait_x = (zw - ec->client.w) / 2;
463 g_floating_info->start_position.portrait_y = (zh - ec->client.h) / 2;
464 g_floating_info->init_portrait_position = EINA_TRUE;
471 _e_input_panel_stay_within_screen(E_Client *ec, int x, int y, int *new_x, int *new_y)
475 if (!ec || !g_floating_info) return;
477 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
479 switch (ec->e.state.rot.ang.curr)
485 else if (x > zh - ec->client.h)
486 *new_x = zh - ec->client.h;
492 else if (y > zw - ec->client.w)
493 *new_y = zw - ec->client.w;
502 else if (x > zw - ec->client.w)
503 *new_x = zw - ec->client.w;
509 else if (y > zh - ec->client.h)
510 *new_y = zh - ec->client.h;
518 _e_input_panel_convert_floating_position(E_Client *ec, int x, int y, int *new_x, int *new_y, E_Input_Panel_Coordinate_Type cur_type)
523 if (!ec || !g_floating_info) return;
525 cur_angle = ec->e.state.rot.ang.curr;
526 if ((!g_floating_info->init_portrait_position && (cur_angle == 0 || cur_angle == 180)) ||
527 (!g_floating_info->init_landscape_position && (cur_angle == 90 || cur_angle == 270)))
528 _e_input_panel_init_floating_position(ec);
530 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
535 if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
537 *new_x = zh - y - ec->client.h;
540 else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
543 *new_y = zh - x - ec->client.h;
547 if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
549 *new_x = zh - y - ec->client.h;
550 *new_y = zw - x - ec->client.w;
552 else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
554 *new_x = zw - x - ec->client.w;
555 *new_y = zh - y - ec->client.h;
559 if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
562 *new_y = zw - x - ec->client.w;
564 else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
566 *new_x = zw - y - ec->client.w;
579 _e_input_panel_position_set(E_Client *ec, int w, int h)
583 Eina_Bool is_portrait;
585 if (!ec || !g_floating_info) return;
587 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
589 /* Get the position of center bottom each angles */
590 switch (ec->e.state.rot.ang.curr)
594 ny = zy + (zh - h) / 2;
595 is_portrait = EINA_FALSE;
598 nx = zx + (zw - w) / 2;
600 is_portrait = EINA_TRUE;
604 ny = zy + (zh - h) / 2;
605 is_portrait = EINA_FALSE;
609 nx = zx + (zw - w) / 2;
611 is_portrait = EINA_TRUE;
615 if (ec->vkbd.floating)
618 if ((is_portrait && !g_floating_info->init_portrait_position) || (!is_portrait && !g_floating_info->init_landscape_position))
619 _e_input_panel_init_floating_position(ec);
622 _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.portrait_x, g_floating_info->start_position.portrait_y, &sx, &sy);
624 _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.landscape_x, g_floating_info->start_position.landscape_y, &sx, &sy);
626 _e_input_panel_convert_floating_position(ec, sx, sy, &nx, &ny, E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL);
629 e_client_util_move_without_frame(ec, nx, ny);
633 _ips_show(E_Client *ec)
640 _e_input_panel_position_set(ec, ec->client.w, ec->client.h);
642 ec->visible = EINA_TRUE;
643 evas_object_geometry_set(ec->frame, ec->x, ec->y, ec->w, ec->h);
644 evas_object_show(ec->frame);
645 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
649 _e_input_panel_surface_visible_update(E_Input_Panel_Surface *ips)
655 if (!(ec = ips->ec)) return;
657 if (e_object_is_del(E_OBJECT(ec))) return;
658 if ((ips->showing) && (e_pixmap_usable_get(ec->pixmap)))
660 /* Now we can assure that previous SHOW request actually succeeded,
661 * no need for trying re-run panel show command */
662 if (panel_show_need_rerun)
663 e_input_panel_show_need_rerun_set(EINA_FALSE);
665 if (_e_input_panel_is_effect_running(ips->ec))
666 ips->need_show = EINA_TRUE;
667 else if (ips->resizing)
669 LOGD("Keyboard is currently resizing. set need_show.");
670 ips->need_show = EINA_TRUE;
675 ips->need_show = EINA_FALSE;
680 LOGD("IPS::DEFER_SHOW::HIDE\n");
681 ec->visible = EINA_FALSE;
682 /* We have to reset the flag of pending_show to prevent showing after
683 * finish the rotation. Directly set this value, since there is no way
684 * to tell it needs to be hidden to rotation module for now. */
685 ec->e.state.rot.pending_show = 0;
686 evas_object_hide(ec->frame);
687 E_FREE_FUNC(ips->eh.buf_change, ecore_event_handler_del);
688 ips->need_show = EINA_FALSE;
693 _e_input_panel_surface_configure(struct wl_resource *resource, Evas_Coord x EINA_UNUSED, Evas_Coord y EINA_UNUSED, Evas_Coord w, Evas_Coord h)
695 E_Input_Panel_Surface *ips;
698 if (!(ips = wl_resource_get_user_data(resource)))
700 WTI_WARNING(resource,
701 WL_DISPLAY_ERROR_INVALID_OBJECT,
702 "No Input Panel Surface For Surface");
708 WTI_WARNING(resource,
709 WL_DISPLAY_ERROR_INVALID_OBJECT,
710 "No Client For Input Panel Surface");
714 e_client_util_resize_without_frame(ec, w, h);
717 _e_input_panel_surface_visible_update(ips);
721 _e_input_panel_surface_map(struct wl_resource *resource)
723 E_Input_Panel_Surface *ips;
726 if (!(ips = wl_resource_get_user_data(resource)))
728 WTI_WARNING(resource,
729 WL_DISPLAY_ERROR_INVALID_OBJECT,
730 "No Input Panel Surface For Surface");
736 WTI_WARNING(resource,
737 WL_DISPLAY_ERROR_INVALID_OBJECT,
738 "No Client For Input Panel Surface");
744 WTI_WARNING(resource,
745 WL_DISPLAY_ERROR_INVALID_OBJECT,
746 "No Data For Client");
750 /* NOTE: we need to set mapped, so that avoid showing evas_object and continue buffer's commit process. */
751 if ((!ec->comp_data->mapped) && (e_pixmap_usable_get(ec->pixmap)))
753 ec->comp_data->mapped = EINA_TRUE;
754 ec->first_mapped = EINA_TRUE;
759 _e_input_panel_surface_unmap(struct wl_resource *resource)
761 E_Input_Panel_Surface *ips = NULL;
764 if (!(ips = wl_resource_get_user_data(resource)))
766 WTI_WARNING(resource,
767 WL_DISPLAY_ERROR_INVALID_OBJECT,
768 "No Input Panel Surface For Surface");
774 WTI_WARNING(resource,
775 WL_DISPLAY_ERROR_INVALID_OBJECT,
776 "No Client For Input Panel Surface");
782 WTI_WARNING(resource,
783 WL_DISPLAY_ERROR_INVALID_OBJECT,
784 "No Data For Client");
788 if (e_object_is_del(E_OBJECT(ec))) return;
790 if (ec->comp_data->mapped)
792 ec->visible = EINA_FALSE;
793 evas_object_hide(ec->frame);
794 ec->comp_data->mapped = EINA_FALSE;
799 _e_input_panel_client_cb_rotation_change_end(void *data, int type, void *event)
802 E_Input_Panel_Surface *ips = data;
803 E_Event_Client_Rotation_Change_End *ev = event;
810 LOGD("current angle : %d", ec->e.state.rot.ang.curr);
811 _e_input_panel_position_set(ec, ec->client.w, ec->client.h);
815 return ECORE_CALLBACK_PASS_ON;
819 _e_input_panel_client_cb_rotation_geometry_set(void *data, int type, void *event)
822 E_Input_Panel_Surface *ips = data;
823 E_Event_Client_Rotation_Geometry_Set *ev = event;
837 if (ev->angle != ec->e.state.rot.ang.curr)
840 evas_object_geometry_get(ec->frame, NULL, NULL, &w, &h);
844 case 0: i = 0; break;
845 case 90: i = 1; break;
846 case 180: i = 2; break;
847 case 270: i = 3; break;
848 default: i = 0; break;
851 if ((w != ec->e.state.rot.geom[i].w) ||
852 (h != ec->e.state.rot.geom[i].h))
854 LOGD("Resizing by Rotation Geometry. Pending Drawing");
855 _e_input_panel_stop_drawing(ips);
859 return ECORE_CALLBACK_PASS_ON;
863 _e_input_panel_client_cb_remove(void *data, E_Client *ec)
865 E_Input_Panel_Surface *ips = data;
869 LOGD("Remove IPS's ec. ips:%p, ips->ec:%p", ips, ips->ec);
875 _e_ips_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
877 E_Input_Panel_Surface *ips = NULL;
884 if (e_object_is_del(E_OBJECT(ec)))
887 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
889 LOGD("current angle : %d", ec->e.state.rot.ang.curr);
890 _e_input_panel_position_set(ec, w, h);
892 ips = _e_input_panel_surface_get(ec);
894 if (!ips->resizing) return;
896 angle = ec->e.state.rot.ang.curr;
899 case 0: i = 0; break;
900 case 90: i = 1; break;
901 case 180: i = 2; break;
902 case 270: i = 3; break;
903 default: i = 0; break;
906 if ((w == ec->e.state.rot.geom[i].w) ||
907 (h == ec->e.state.rot.geom[i].h))
909 LOGD("Resize Done to Rotation Geometry. Starting Drawing Again");
910 _e_input_panel_start_drawing(ips);
915 _e_ips_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
920 if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
923 g_floating_info->mouse_pressed = EINA_FALSE;
924 g_floating_info->moving_req = EINA_FALSE;
928 _e_ips_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
931 Evas_Event_Mouse_Move *ev = event_info;
934 if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
937 g_floating_info->mouse_pressed = EINA_TRUE;
938 g_floating_info->before_canvas_x = ev->cur.canvas.x;
939 g_floating_info->before_canvas_y = ev->cur.canvas.y;
943 _e_ips_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
946 Evas_Event_Mouse_Move *ev = event_info;
947 Evas_Coord x, y, w, h;
948 int b_x = 0, b_y = 0, n_x = 0, n_y = 0;
952 if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
955 if (!g_floating_info->moving_req || !g_floating_info->mouse_pressed)
958 evas_object_geometry_get(obj, &x, &y, &w, &h);
960 d_x = x + (ev->cur.canvas.x - g_floating_info->before_canvas_x);
961 d_y = y + (ev->cur.canvas.y - g_floating_info->before_canvas_y);
963 _e_input_panel_convert_floating_position(ec, d_x, d_y, &b_x, &b_y, E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE);
964 _e_input_panel_stay_within_screen(ec, b_x, b_y, &n_x, &n_y);
966 g_floating_info->before_canvas_x = ev->cur.canvas.x;
967 g_floating_info->before_canvas_y = ev->cur.canvas.y;
969 if (ec->e.state.rot.ang.curr == 90 || ec->e.state.rot.ang.curr == 270)
971 g_floating_info->start_position.landscape_x = n_x;
972 g_floating_info->start_position.landscape_y = n_y;
976 g_floating_info->start_position.portrait_x = n_x;
977 g_floating_info->start_position.portrait_y = n_y;
980 _e_input_panel_convert_floating_position(ec, n_x, n_y, &d_x, &d_y, E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL);
981 evas_object_move(obj, d_x, d_y);
985 _e_input_panel_rotation_geometry_set(void *data, E_Client *ec)
987 E_Input_Panel_Surface *ips;
1001 evas_object_geometry_get(ec->frame, NULL, NULL, &w, &h);
1003 cur_angle = ec->e.state.rot.ang.curr;
1006 case 0: i = 0; break;
1007 case 90: i = 1; break;
1008 case 180: i = 2; break;
1009 case 270: i = 3; break;
1010 default: i = 0; break;
1013 if ((w != ec->e.state.rot.geom[i].w) ||
1014 (h != ec->e.state.rot.geom[i].h))
1016 LOGD("Resizing by Rotation Geometry. Pending Drawing...");
1017 _e_input_panel_stop_drawing(ips);
1022 _e_input_panel_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
1024 E_Input_Panel *input_panel = wl_resource_get_user_data(resource);
1025 E_Client *ec = wl_resource_get_user_data(surface_resource);
1026 E_Input_Panel_Surface *ips = NULL;
1027 E_Comp_Client_Data *cdata = NULL;
1029 LOGD("client %p input_panel %p ec %p resource %p surface_resource %p",
1030 client, input_panel, ec, resource, surface_resource);
1034 WTI_WARNING(resource,
1035 WL_DISPLAY_ERROR_INVALID_OBJECT,
1036 "No Input Panel Surface For Surface");
1042 WTI_WARNING(surface_resource,
1043 WL_DISPLAY_ERROR_INVALID_OBJECT,
1044 "No E_Client Set On Surface");
1048 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL)
1051 if (!(cdata = ec->comp_data))
1053 WTI_WARNING(surface_resource,
1054 WL_DISPLAY_ERROR_INVALID_OBJECT,
1055 "No Data For Client");
1059 /* check for existing shell surface */
1060 if (cdata->shell.surface)
1062 WTI_WARNING(surface_resource,
1063 WL_DISPLAY_ERROR_INVALID_OBJECT,
1064 "Client already has shell surface");
1068 if (!(cdata->shell.surface =
1069 wl_resource_create(client, &wl_input_panel_surface_interface, 1, id)))
1071 wl_resource_post_no_memory(surface_resource);
1072 /* NOTE: Cleanup E_client. */
1077 e_client_unignore(ec);
1079 /* set input panel client properties */
1080 ec->borderless = EINA_TRUE;
1081 ec->argb = EINA_TRUE;
1082 ec->lock_border = EINA_TRUE;
1083 ec->lock_focus_in = ec->lock_focus_out = EINA_TRUE;
1084 ec->netwm.state.skip_taskbar = EINA_TRUE;
1085 ec->netwm.state.skip_pager = EINA_TRUE;
1086 ec->no_shape_cut = EINA_TRUE;
1087 ec->border_size = 0;
1089 ec->icccm.window_role = eina_stringshare_add("input_panel_surface");
1090 if (!ec->icccm.title)
1091 ec->icccm.title = eina_stringshare_add("Keyboard");
1094 ec->exp_iconify.skip_iconify = 1;
1095 evas_object_layer_set(ec->frame, E_LAYER_CLIENT_ABOVE);
1098 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE, _e_ips_cb_evas_resize, ec);
1099 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOUSE_UP, _e_ips_cb_mouse_up, ec);
1100 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOUSE_DOWN, _e_ips_cb_mouse_down, ec);
1101 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOUSE_MOVE, _e_ips_cb_mouse_move, ec);
1103 cdata->surface = surface_resource;
1104 cdata->shell.configure_send = NULL;
1105 cdata->shell.configure = _e_input_panel_surface_configure;
1106 cdata->shell.ping = NULL;
1107 cdata->shell.map = _e_input_panel_surface_map;
1108 cdata->shell.unmap = _e_input_panel_surface_unmap;
1110 if (!(ips = E_NEW(E_Input_Panel_Surface, 1)))
1112 wl_client_post_no_memory(client);
1117 ips->input_panel = input_panel;
1119 LOGD("Create IPS.. ips:%p, input_panel:%p, ec:%p", ips, input_panel, ec);
1121 _e_input_panel_surface_append(input_panel, ips, resource);
1123 wl_resource_set_implementation(cdata->shell.surface,
1124 &_e_input_panel_surface_implementation,
1125 ips, _e_input_panel_surface_resource_destroy);
1127 ips->eh.rot_change_end =
1128 ecore_event_handler_add(E_EVENT_CLIENT_ROTATION_CHANGE_END,
1129 _e_input_panel_client_cb_rotation_change_end, ips);
1131 ips->eh.rot_geometry_set =
1132 ecore_event_handler_add(E_EVENT_CLIENT_ROTATION_GEOMETRY_SET,
1133 _e_input_panel_client_cb_rotation_geometry_set, ips);
1136 ips->hook_del = e_client_hook_add(E_CLIENT_HOOK_DEL, _e_input_panel_client_cb_remove, ips);
1137 ips->hook_rotation_geometry_set = e_policy_hook_add(E_POLICY_HOOK_CLIENT_ROTATION_GEOMETRY_SET, _e_input_panel_rotation_geometry_set, ips);
1139 // base_output_resolution.
1140 e_client_base_output_resolution_update(ec);
1144 static const struct wl_input_panel_interface _e_input_panel_implementation = {
1145 _e_input_panel_cb_surface_get
1149 _e_input_panel_unbind(struct wl_resource *resource)
1153 E_Input_Panel_Surface *ips;
1154 E_Input_Panel *input_panel = wl_resource_get_user_data(resource);
1156 LOGD("resource %p input_panel %p", resource, input_panel);
1160 WTI_WARNING(resource,
1161 WL_DISPLAY_ERROR_INVALID_OBJECT,
1162 "No Input Panel For Resource");
1166 input_panel->resource = NULL;
1168 EINA_LIST_FOREACH_SAFE(input_panel->surfaces, l, l_next, ips)
1170 LOGD("foreach ips %p resource %p l %p", ips, resource, l);
1171 if (ips && ips->resource == resource)
1174 E_Comp_Wl_Client_Data *cdata;
1176 input_panel->surfaces = eina_list_remove_list(input_panel->surfaces, l);
1177 LOGD("Removed surface %p from list %p", l, input_panel->surfaces);
1179 if (!(ec = ips->ec)) continue;
1180 if (e_object_is_del(E_OBJECT(ec))) continue;
1181 if (!(cdata = ec->comp_data)) continue;
1183 cdata->shell.surface = NULL;
1189 _e_input_panel_bind(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
1191 E_Input_Panel *input_panel = data;
1192 struct wl_resource *resource;
1194 if (!input_panel) return;
1196 if (input_panel->resource)
1197 _e_input_panel_unbind(input_panel->resource);
1199 resource = wl_resource_create(client, &wl_input_panel_interface, 1, id);
1200 if (!resource) return;
1202 LOGD("client %p input_panel %p resource %p", client, input_panel, resource);
1204 if (input_panel->resource == NULL)
1206 wl_resource_set_implementation(resource,
1207 &_e_input_panel_implementation,
1208 input_panel, _e_input_panel_unbind);
1210 input_panel->resource = resource;
1215 WTI_WARNING(resource,
1216 WL_DISPLAY_ERROR_INVALID_OBJECT,
1217 "input_panel object already bound");
1221 e_input_panel_visibility_change(Eina_Bool visible)
1223 E_Input_Panel_Surface *ips;
1226 /* Here, if we are trying to show input panel, we can't guarantee our SHOW request
1227 * will succeed or not at this point (input panel may not have created its surface)
1228 * so set panel_show_need_rerun to TRUE to try showing it again afterwards */
1229 e_input_panel_show_need_rerun_set(visible);
1231 if (!g_input_panel) return;
1233 LOGD("e_input_panel_visibility_change : %d", visible);
1235 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, visible ? VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW : VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
1237 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1239 if (!ips || !ips->ec) continue;
1240 ips->showing = visible;
1241 _e_input_panel_surface_visible_update(ips);
1244 _wait_update_timer_del();
1248 e_input_panel_client_find(E_Client *ec)
1250 E_Input_Panel_Surface *ips;
1253 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1255 if (!g_input_panel) return EINA_FALSE;
1257 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1259 if (!ips || !ips->ec) continue;
1260 if (ips->ec == ec) return EINA_TRUE;
1266 /* If ec is NULL, it will check the very first item that is found in our surfaces list */
1268 e_input_panel_client_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
1270 E_Input_Panel_Surface *ips;
1274 if (!g_input_panel) return EINA_FALSE;
1275 if (!x || !y || !w || !h) return EINA_FALSE;
1277 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1279 if (!ips || !ips->ec) continue;
1280 if (ips->ec == ec || !ec)
1282 angle = ips->ec->e.state.rot.ang.next < 0 ?
1283 ips->ec->e.state.rot.ang.curr :
1284 ips->ec->e.state.rot.ang.next;
1311 _e_input_panel_idle_enter(void *data)
1313 E_Input_Panel_Surface *ips;
1316 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1322 if (!_e_input_panel_is_effect_running(ips->ec))
1327 ips->need_show = EINA_FALSE;
1332 return ECORE_CALLBACK_RENEW;
1336 e_input_panel_init(void)
1338 if (!e_comp_wl) return EINA_FALSE;
1340 if (!(g_input_panel = E_NEW(E_Input_Panel, 1)))
1342 /* ERR("Failed to allocate space for E_Input_Panel"); */
1346 g_input_panel->global = wl_global_create(e_comp_wl->wl.disp,
1347 &wl_input_panel_interface, 1,
1348 g_input_panel, _e_input_panel_bind);
1350 if (!g_input_panel->global)
1352 free(g_input_panel);
1353 g_input_panel = NULL;
1354 /* ERR("Failed to create global of wl_input_panel"); */
1358 g_input_panel->idle_enter = ecore_idle_enterer_add(_e_input_panel_idle_enter, NULL);
1359 g_floating_info = E_NEW(E_Input_Panel_Floating_Info, 1);
1365 e_input_panel_shutdown(void)
1369 if (g_input_panel->resource)
1371 wl_resource_destroy(g_input_panel->resource);
1372 g_input_panel->resource = NULL;
1375 if (g_input_panel->global)
1377 wl_global_destroy(g_input_panel->global);
1378 g_input_panel->global = NULL;
1381 E_FREE_FUNC(g_input_panel->idle_enter, ecore_idle_enterer_del);
1384 if (g_floating_info)
1385 E_FREE(g_floating_info);
1389 _ips_client_frame_flush(E_Input_Panel_Surface *ips)
1394 if (e_object_is_del(E_OBJECT(ips->ec)))
1397 LOGD("IPS::FRAME::FLUSH ec %p\n", ips->ec);
1398 e_pixmap_image_clear(ips->ec->pixmap, EINA_TRUE);
1402 _ip_cb_e_buf_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
1405 E_Input_Panel_Surface *ips;
1409 if (EINA_UNLIKELY(!ev))
1412 if (EINA_UNLIKELY(!g_input_panel))
1415 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1417 if (!ips || ips->ec != ev->ec) continue;
1418 _ips_client_frame_flush(ips);
1422 return ECORE_CALLBACK_PASS_ON;
1426 e_input_panel_wait_update_set(Eina_Bool wait_update)
1428 E_Input_Panel_Surface *ips;
1434 g_input_panel->wait_update = wait_update;
1436 /* If we are in wait_update mode, the input panel surfaces have to be updated forcibly */
1439 LOGD("Registering wait_update_timer");
1440 _wait_update_timer_del();
1441 g_timer_wait_update = ecore_timer_add(WAIT_UPDATE_TIMER_INTERVAL,
1442 _wait_update_timer_handler, NULL);
1444 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1446 if (!ips || !ips->ec) continue;
1447 _ips_client_frame_flush(ips);
1450 if (!g_input_panel->buf_change_handler)
1452 LOGD("IPS::WAIT::UPDATE::SET (add buf change handler)\n");
1453 g_input_panel->buf_change_handler = ecore_event_handler_add(E_EVENT_CLIENT_BUFFER_CHANGE,
1454 _ip_cb_e_buf_change, NULL);
1458 E_FREE_FUNC(g_input_panel->buf_change_handler, ecore_event_handler_del);
1462 e_input_panel_transient_for_set(E_Client *parent)
1464 LOGD("TRANSIENT_FOR::transient_for_set : %p\n", parent);
1465 E_Input_Panel_Surface *ips;
1467 E_Client *ec_parent = parent;
1469 /* finding the actual parent window that contains the remote surface. */
1472 if (!e_object_is_del(E_OBJECT(ec_parent)) &&
1473 (ec_parent->comp_data) && (ec_parent->comp_data->remote_surface.onscreen_parent))
1475 ec_parent = ec_parent->comp_data->remote_surface.onscreen_parent;
1479 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1482 E_Client *child = ips->ec;
1484 if (!child) continue;
1485 if (e_object_is_del(E_OBJECT(child)))
1487 LOGE("child is deleted");
1491 /* If the child already has a parent, remove it */
1494 if (e_object_is_del(E_OBJECT(child->parent)))
1496 LOGE("child->parent is deleted");
1500 LOGD("TRANSIENT_FOR::The child already has a parent : %p\n", child->parent);
1501 if (ec_parent != child->parent)
1503 child->parent->transients =
1504 eina_list_remove(child->parent->transients, child);
1505 if (child->parent->modal == child) child->parent->modal = NULL;
1506 child->parent = NULL;
1507 LOGD("TRANSIENT_FOR::reset parent %p for : %p\n", child->parent, child);
1511 /* Append our child into parent's transients list */
1512 if ((ec_parent != child) && (ec_parent != child->parent))
1514 if ((ec_parent) && (eina_list_data_find(parent->transients, child) != child))
1516 LOGD("TRANSIENT_FOR::Adding %p into parent %p's transients list\n", child, ec_parent);
1517 ec_parent->transients = eina_list_append(ec_parent->transients, child);
1519 child->parent = ec_parent;
1524 child->icccm.fetch.transient_for = EINA_TRUE;
1525 child->icccm.transient_for = e_client_util_win_get(ec_parent);
1529 child->icccm.fetch.transient_for = EINA_FALSE;
1530 child->icccm.transient_for = 0;
1537 e_input_panel_show_need_rerun_set(Eina_Bool need_rerun)
1539 panel_show_need_rerun = need_rerun;
1543 e_input_panel_floating_position_set(int x, int y)
1546 E_Client *floating_ec = NULL;
1547 E_Input_Panel_Surface *floating_ips;
1548 E_Input_Panel_Surface *ips;
1552 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
1554 if (!ips || !ips->ec) continue;
1555 if (ips->ec->frame && ips->ec->vkbd.floating)
1557 floating_ec = ips->ec;
1563 if (!floating_ec || !floating_ips || !g_floating_info) return;
1565 if(floating_ips->showing)
1566 cur_angle = floating_ec->e.state.rot.ang.curr;
1568 cur_angle = floating_ec->zone->rot.curr;
1570 LOGD("current angle : %d", cur_angle);
1575 g_floating_info->start_position.landscape_x = x;
1576 g_floating_info->start_position.landscape_y = y;
1577 g_floating_info->init_landscape_position = EINA_TRUE;
1582 g_floating_info->start_position.portrait_x = x;
1583 g_floating_info->start_position.portrait_y = y;
1584 g_floating_info->init_portrait_position = EINA_TRUE;
1588 if(floating_ips->showing)
1589 _e_input_panel_position_set(floating_ec, floating_ec->client.w, floating_ec->client.h);
1593 e_input_panel_surface_destroy(E_Client *ec)
1596 E_Input_Panel_Surface *ips;
1600 if (!g_input_panel) return EINA_FALSE;
1602 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
1604 if (!ips || !ips->ec) continue;
1607 g_input_panel->surfaces = eina_list_remove_list(g_input_panel->surfaces, l);
1610 LOGD("Destroyed Waiting Resize Window. Starting Drawing Again");
1611 _e_input_panel_start_drawing(ips);
1619 /* check whether the keyboard effect is running or not
1620 - 0 : effect is not running,
1621 - otherwise : effect is running */
1622 int e_input_panel_is_effect_running(void)
1624 E_Input_Panel_Surface *ips = NULL;
1625 Eina_List *l = NULL;
1628 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1630 if (!ips || !ips->ec) continue;
1631 if (_e_input_panel_is_effect_running(ips->ec))
1634 Do we need to check currently effect type?
1635 then what flag do we check? ips->ec->visible or ips->showing?
1637 if (ips->ec->visible)
1638 run_type = 1; // show effect is running
1640 run_type = 2; // hide effect is running