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 #define CHECK_INPUT_PANEL_SURFACE(ips) \
14 WTI_WARNING(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "No Input Panel Surface For Surface"); \
18 #define CHECK_ECLIENT(ec, resource) \
21 WTI_WARNING(resource, \
22 WL_DISPLAY_ERROR_INVALID_OBJECT, \
23 "No Client For Input Panel Surface"); \
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;
33 E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE,
34 E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL,
35 } E_Input_Panel_Coordinate_Type;
39 struct wl_global *global;
40 struct wl_resource *resource;
43 Ecore_Event_Handler *buf_change_handler;
44 Ecore_Idle_Enterer *idle_enter;
46 Eina_Bool wait_update; /* wait update state for global input panel object */
49 struct _E_Input_Panel_Surface
51 struct wl_resource *resource;
53 E_Input_Panel *input_panel;
58 Ecore_Event_Handler *rot_change_end;
59 Ecore_Event_Handler *buf_change;
60 Ecore_Event_Handler *rot_geometry_set;
68 Ecore_Timer *resize_timer;
72 E_Client_Hook *hook_del;
73 E_Policy_Hook *hook_rotation_geometry_set;
76 struct _E_Input_Panel_Floating_Info
79 Eina_Bool mouse_pressed;
80 Eina_Bool init_portrait_position;
81 Eina_Bool init_landscape_position;
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;
99 static E_Input_Panel_Surface *
100 _e_input_panel_surface_get(E_Client *ec)
102 E_Input_Panel_Surface *ips;
106 if (!g_input_panel) return NULL;
108 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
110 if (!ips || !ips->ec) continue;
121 _e_input_panel_start_drawing(E_Input_Panel_Surface *ips)
124 if (!ips->resizing) return;
126 if (ips->resize_timer)
128 ecore_timer_del(ips->resize_timer);
129 ips->resize_timer = NULL;
132 LOGI("Norender pop by resizing keyboard");
133 e_comp_canvas_norender_pop();
134 ips->resizing = EINA_FALSE;
138 _resize_timeout_cb(void *data)
140 E_Input_Panel_Surface *ips = NULL;
142 LOGE("TIMED OUT while waiting for resizing keyboard");
145 if (!ips) return ECORE_CALLBACK_CANCEL;
147 LOGI("Norender pop by resizing keyboard timeout");
148 e_comp_canvas_norender_pop();
149 ips->resizing = EINA_FALSE;
150 ips->resize_timer = NULL;
152 return ECORE_CALLBACK_CANCEL;
156 _e_input_panel_stop_drawing(E_Input_Panel_Surface *ips)
159 if (ips->resizing) return;
161 LOGI("Norender push by resizing keyboard");
162 e_comp_canvas_norender_push();
163 ips->resizing = EINA_TRUE;
165 if (!ips->resize_timer)
167 ips->resize_timer = ecore_timer_add(WAIT_UPDATE_TIMER_INTERVAL,
168 _resize_timeout_cb, ips);
173 _e_input_panel_log_show(struct wl_resource *resource, uint32_t code, const char *msg, const char *warning_msg)
175 LOGW("%s() is failed\n", warning_msg);
176 wl_resource_post_error(resource, code, "%s", msg);
180 _e_input_panel_is_effect_running(E_Client *ec)
182 if ((e_comp_object_is_animating(ec->frame)) ||
183 (evas_object_data_get(ec->frame, "effect_running")))
189 _e_input_panel_surface_append(E_Input_Panel *input_panel, E_Input_Panel_Surface *ips, struct wl_resource *resource)
191 if (!input_panel || !ips) return;
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);
199 e_input_panel_transient_for_set(client_surface);
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);
208 append_input_panel_surface(struct wl_resource *resource)
210 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
211 E_Input_Panel *input_panel = NULL;
213 CHECK_INPUT_PANEL_SURFACE(ips);
215 if (!(input_panel = ips->input_panel)) return;
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)
221 _e_input_panel_surface_append(input_panel, ips, resource);
223 ips->panel = EINA_FALSE;
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)
229 append_input_panel_surface(resource);
233 _e_input_panel_surface_cb_overlay_panel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
235 append_input_panel_surface(resource);
239 _e_input_panel_surface_show(E_Input_Panel_Surface *ips)
242 E_Input_Panel_Surface *surface = NULL;
243 E_Client *focused_ec = NULL;
245 if (!g_input_panel) return;
247 /* When NULL passed, find the most appropriate surface */
250 EINA_LIST_FOREACH(g_input_panel->surfaces, l, surface)
252 if (surface && surface->ec)
254 if (surface->ec->parent == e_client_focused_get())
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);
267 if (g_input_panel->wait_update)
269 focused_ec = e_client_focused_get();
270 e_input_panel_wait_update_set(EINA_FALSE);
271 if (ips->ec && ips->ec->parent)
273 if (ips->ec->parent == focused_ec)
275 e_policy_conformant_part_update(ips->ec);
276 e_input_panel_visibility_change(EINA_TRUE);
278 e_text_input_update_input_panel_state(EINA_TRUE);
282 LOGW("parent does not have focus");
283 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 > 0)
295 LOGI("deleting wait_update timer");
296 g_source_remove(g_timer_wait_update);
297 g_timer_wait_update = 0;
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 = 0;
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;
320 CHECK_INPUT_PANEL_SURFACE(ips);
322 LOGI("IPS::SHOW::READY\n");
324 // base_output_resolution
325 e_client_base_output_resolution_transform_adjust(ips->ec);
327 _e_input_panel_surface_show(ips);
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,
337 _e_input_panel_surface_resource_destroy(struct wl_resource *resource)
340 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
341 E_Input_Panel *input_panel = NULL;
344 CHECK_INPUT_PANEL_SURFACE(ips);
346 if (!(input_panel = ips->input_panel)) return;
349 if (ec && (!e_object_is_del(E_OBJECT(ec))))
353 if (ec->comp_data->mapped)
355 if ((ec->comp_data->shell.surface) &&
356 (ec->comp_data->shell.unmap))
357 ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
361 ec->parent->transients =
362 eina_list_remove(ec->parent->transients, ec);
364 ec->comp_data->shell.surface = NULL;
370 LOGI("Destroyed Waiting Resize Input Surface. Starting Drawing Again");
371 _e_input_panel_start_drawing(ips);
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);
386 _e_input_panel_init_floating_position(E_Client *ec)
390 if (!ec || !g_floating_info) return;
392 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
394 switch (ec->e.state.rot.ang.curr)
398 if (!g_floating_info->init_landscape_position)
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;
408 if (!g_floating_info->init_portrait_position)
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;
419 _e_input_panel_stay_within_screen(E_Client *ec, int x, int y, int *new_x, int *new_y)
423 if (!ec || !g_floating_info) return;
425 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
427 switch (ec->e.state.rot.ang.curr)
433 else if (x > zh - ec->client.h)
434 *new_x = zh - ec->client.h;
440 else if (y > zw - ec->client.w)
441 *new_y = zw - ec->client.w;
450 else if (x > zw - ec->client.w)
451 *new_x = zw - ec->client.w;
457 else if (y > zh - ec->client.h)
458 *new_y = zh - ec->client.h;
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)
471 if (!ec || !g_floating_info) return;
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);
478 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
483 if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
485 *new_x = zh - y - ec->client.h;
488 else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
491 *new_y = zh - x - ec->client.h;
495 if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
497 *new_x = zh - y - ec->client.h;
498 *new_y = zw - x - ec->client.w;
500 else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
502 *new_x = zw - x - ec->client.w;
503 *new_y = zh - y - ec->client.h;
507 if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_ABSOLUTE)
510 *new_y = zw - x - ec->client.w;
512 else if (cur_type == E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL)
514 *new_x = zw - y - ec->client.w;
527 _e_input_panel_position_set(E_Client *ec, int w, int h)
531 Eina_Bool is_portrait;
533 if (!ec || !g_floating_info) return;
535 e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
537 /* Get the position of center bottom each angles */
538 switch (ec->e.state.rot.ang.curr)
542 ny = zy + (zh - h) / 2;
543 is_portrait = EINA_FALSE;
546 nx = zx + (zw - w) / 2;
548 is_portrait = EINA_TRUE;
552 ny = zy + (zh - h) / 2;
553 is_portrait = EINA_FALSE;
557 nx = zx + (zw - w) / 2;
559 is_portrait = EINA_TRUE;
563 if (ec->vkbd.floating)
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);
570 _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.portrait_x, g_floating_info->start_position.portrait_y, &sx, &sy);
572 _e_input_panel_stay_within_screen(ec, g_floating_info->start_position.landscape_x, g_floating_info->start_position.landscape_y, &sx, &sy);
574 _e_input_panel_convert_floating_position(ec, sx, sy, &nx, &ny, E_INPUT_PANEL_COORDINATE_TYPE_LOGICAL);
577 e_client_util_move_without_frame(ec, nx, ny);
581 _ips_show(E_Client *ec)
588 _e_input_panel_position_set(ec, ec->client.w, ec->client.h);
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);
597 _e_input_panel_surface_visible_update(E_Input_Panel_Surface *ips)
603 if (!(ec = ips->ec)) return;
605 if (e_object_is_del(E_OBJECT(ec))) return;
606 if ((ips->showing) && (e_pixmap_usable_get(ec->pixmap)))
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);
613 if (_e_input_panel_is_effect_running(ips->ec))
614 ips->need_show = EINA_TRUE;
615 else if (ips->resizing)
617 LOGI("Keyboard is currently resizing. set need_show.");
618 ips->need_show = EINA_TRUE;
623 ips->need_show = EINA_FALSE;
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;
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)
643 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
646 CHECK_INPUT_PANEL_SURFACE(ips);
650 WTI_WARNING(resource,
651 WL_DISPLAY_ERROR_INVALID_OBJECT,
652 "No Client For Input Panel Surface");
656 e_client_util_resize_without_frame(ec, w, h);
659 _e_input_panel_surface_visible_update(ips);
663 _e_input_panel_surface_map(struct wl_resource *resource)
665 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
668 CHECK_INPUT_PANEL_SURFACE(ips);
672 WTI_WARNING(resource,
673 WL_DISPLAY_ERROR_INVALID_OBJECT,
674 "No Client For Input Panel Surface");
680 WTI_WARNING(resource,
681 WL_DISPLAY_ERROR_INVALID_OBJECT,
682 "No Data For Client");
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)))
689 ec->comp_data->mapped = EINA_TRUE;
690 ec->first_mapped = EINA_TRUE;
695 _e_input_panel_surface_unmap(struct wl_resource *resource)
697 E_Input_Panel_Surface *ips = wl_resource_get_user_data(resource);
700 CHECK_INPUT_PANEL_SURFACE(ips);
702 CHECK_ECLIENT(ec, resource);
706 WTI_WARNING(resource,
707 WL_DISPLAY_ERROR_INVALID_OBJECT,
708 "No Data For Client");
712 if (e_object_is_del(E_OBJECT(ec))) return;
714 if (ec->comp_data->mapped)
716 ec->visible = EINA_FALSE;
717 evas_object_hide(ec->frame);
718 ec->comp_data->mapped = EINA_FALSE;
723 _e_input_panel_client_cb_rotation_change_end(void *data, int type, void *event)
726 E_Input_Panel_Surface *ips = data;
727 E_Event_Client_Rotation_Change_End *ev = event;
734 LOGI("current angle : %d", ec->e.state.rot.ang.curr);
735 _e_input_panel_position_set(ec, ec->client.w, ec->client.h);
739 return ECORE_CALLBACK_PASS_ON;
742 static bool check_rotation_size(E_Client *ec, int angle, int w, int h)
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;
754 if ((w != ec->e.state.rot.geom[i].w) ||
755 (h != ec->e.state.rot.geom[i].h))
762 _e_input_panel_client_cb_rotation_geometry_set(void *data, int type, void *event)
765 E_Input_Panel_Surface *ips = data;
766 E_Event_Client_Rotation_Geometry_Set *ev = event;
779 if (ev->angle != ec->e.state.rot.ang.curr)
782 evas_object_geometry_get(ec->frame, NULL, NULL, &w, &h);
784 if (!check_rotation_size(ec, ev->angle, w, h))
786 LOGI("Resizing by Rotation Geometry. Pending Drawing");
787 _e_input_panel_stop_drawing(ips);
791 return ECORE_CALLBACK_PASS_ON;
795 _e_input_panel_client_cb_remove(void *data, E_Client *ec)
797 E_Input_Panel_Surface *ips = data;
801 LOGI("Remove IPS's ec. ips:%p, ips->ec:%p", ips, ips->ec);
807 _e_ips_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
809 E_Input_Panel_Surface *ips = NULL;
816 if (e_object_is_del(E_OBJECT(ec)))
819 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
821 LOGI("current angle : %d", ec->e.state.rot.ang.curr);
822 _e_input_panel_position_set(ec, w, h);
824 ips = _e_input_panel_surface_get(ec);
826 if (!ips->resizing) return;
828 angle = ec->e.state.rot.ang.curr;
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;
838 if ((w == ec->e.state.rot.geom[i].w) ||
839 (h == ec->e.state.rot.geom[i].h))
841 LOGI("Resize Done to Rotation Geometry. Starting Drawing Again");
842 _e_input_panel_start_drawing(ips);
847 _e_input_panel_effect_end(void *data, E_Client *ec)
849 E_Input_Panel_Surface *ips = data;
850 if (!ips) return EINA_TRUE;
852 LOGI("Effect end IPS's ec. ips:%p, ips->ec:%p", ips, ips->ec);
855 vconf_set_int(VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_DID_HIDE);
861 _e_ips_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
866 if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
869 g_floating_info->mouse_pressed = EINA_FALSE;
871 if (g_floating_info->moving_req)
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;
880 _e_ips_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
883 Evas_Event_Mouse_Move *ev = event_info;
886 if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
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;
895 _e_ips_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
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;
904 if (e_object_is_del(E_OBJECT(ec)) || !ec->vkbd.floating || !g_floating_info)
907 if (!g_floating_info->moving_req || !g_floating_info->mouse_pressed)
910 evas_object_geometry_get(obj, &x, &y, &w, &h);
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);
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);
918 g_floating_info->before_canvas_x = ev->cur.canvas.x;
919 g_floating_info->before_canvas_y = ev->cur.canvas.y;
921 if (ec->e.state.rot.ang.curr == 90 || ec->e.state.rot.ang.curr == 270)
923 g_floating_info->start_position.landscape_x = n_x;
924 g_floating_info->start_position.landscape_y = n_y;
928 g_floating_info->start_position.portrait_x = n_x;
929 g_floating_info->start_position.portrait_y = n_y;
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);
937 _e_input_panel_rotation_geometry_set(void *data, E_Client *ec)
939 E_Input_Panel_Surface *ips;
952 evas_object_geometry_get(ec->frame, NULL, NULL, &w, &h);
954 cur_angle = ec->e.state.rot.ang.curr;
956 if (!check_rotation_size(ec, cur_angle, w, h) && (e_text_input_activation_state_get() || ips->showing))
958 LOGI("Resizing by Rotation Geometry. Pending Drawing...");
959 _e_input_panel_stop_drawing(ips);
964 _e_input_panel_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
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;
971 LOGI("client %p input_panel %p ec %p resource %p surface_resource %p",
972 client, input_panel, ec, resource, surface_resource);
976 WTI_WARNING(resource,
977 WL_DISPLAY_ERROR_INVALID_OBJECT,
978 "No Input Panel For Surface");
982 CHECK_ECLIENT(ec, surface_resource);
984 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL)
987 if (!(cdata = ec->comp_data))
989 WTI_WARNING(surface_resource,
990 WL_DISPLAY_ERROR_INVALID_OBJECT,
991 "No Data For Client");
995 /* check for existing shell surface */
996 if (cdata->shell.surface)
998 WTI_WARNING(surface_resource,
999 WL_DISPLAY_ERROR_INVALID_OBJECT,
1000 "Client already has shell surface");
1004 if (!(cdata->shell.surface =
1005 wl_resource_create(client, &zwp_input_panel_surface_v1_interface, 1, id)))
1007 wl_resource_post_no_memory(surface_resource);
1008 /* NOTE: Cleanup E_client. */
1013 e_client_unignore(ec);
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;
1025 ec->icccm.window_role = eina_stringshare_add("input_panel_surface");
1026 if (!ec->icccm.title)
1027 ec->icccm.title = eina_stringshare_add("Keyboard");
1030 ec->exp_iconify.skip_iconify = 1;
1031 e_client_layer_set(ec, E_LAYER_CLIENT_ABOVE);
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);
1039 g_mutex_lock(&cdata->surface_mutex);
1040 cdata->surface = surface_resource;
1041 g_mutex_unlock(&cdata->surface_mutex);
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;
1049 if (!(ips = E_NEW(E_Input_Panel_Surface, 1)))
1051 wl_client_post_no_memory(client);
1056 ips->input_panel = input_panel;
1058 LOGI("Create IPS.. ips:%p, input_panel:%p, ec:%p", ips, input_panel, ec);
1060 _e_input_panel_surface_append(input_panel, ips, resource);
1062 wl_resource_set_implementation(cdata->shell.surface,
1063 &_e_input_panel_surface_implementation,
1064 ips, _e_input_panel_surface_resource_destroy);
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);
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);
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);
1077 E_COMP_COMP_HOOK_APPEND(ips->cp_hooks, E_COMP_OBJECT_HOOK_EFFECT_END, _e_input_panel_effect_end, ips);
1079 // base_output_resolution.
1080 e_client_base_output_resolution_update(ec);
1083 static const struct zwp_input_panel_v1_interface _e_input_panel_implementation = {
1084 _e_input_panel_cb_surface_get
1088 _e_input_panel_unbind(struct wl_resource *resource)
1092 E_Input_Panel_Surface *ips;
1093 E_Input_Panel *input_panel = wl_resource_get_user_data(resource);
1095 LOGI("resource %p input_panel %p", resource, input_panel);
1099 WTI_WARNING(resource,
1100 WL_DISPLAY_ERROR_INVALID_OBJECT,
1101 "No Input Panel For Resource");
1105 input_panel->resource = NULL;
1107 EINA_LIST_FOREACH_SAFE(input_panel->surfaces, l, l_next, ips)
1109 LOGI("foreach ips %p resource %p l %p", ips, resource, l);
1110 if (ips && ips->resource == resource)
1113 E_Comp_Wl_Client_Data *cdata;
1115 input_panel->surfaces = eina_list_remove_list(input_panel->surfaces, l);
1116 LOGI("Removed surface %p from list %p", l, input_panel->surfaces);
1118 if (!(ec = ips->ec)) continue;
1119 if (e_object_is_del(E_OBJECT(ec))) continue;
1120 if (!(cdata = ec->comp_data)) continue;
1122 cdata->shell.surface = NULL;
1128 _e_input_panel_bind(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id)
1130 E_Input_Panel *input_panel = data;
1131 struct wl_resource *resource;
1133 if (!input_panel) return;
1135 if (input_panel->resource)
1136 _e_input_panel_unbind(input_panel->resource);
1138 resource = wl_resource_create(client, &zwp_input_panel_v1_interface, 1, id);
1139 if (!resource) return;
1141 LOGI("client %p input_panel %p resource %p", client, input_panel, resource);
1143 if (input_panel->resource == NULL)
1145 wl_resource_set_implementation(resource,
1146 &_e_input_panel_implementation,
1147 input_panel, _e_input_panel_unbind);
1149 input_panel->resource = resource;
1154 WTI_WARNING(resource,
1155 WL_DISPLAY_ERROR_INVALID_OBJECT,
1156 "input_panel object already bound");
1160 e_input_panel_visibility_change(Eina_Bool visible)
1162 E_Input_Panel_Surface *ips;
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);
1170 if (!g_input_panel) return;
1172 LOGI("e_input_panel_visibility_change : %d", visible);
1174 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, visible ? VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW : VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
1176 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1178 if (!ips || !ips->ec) continue;
1179 ips->showing = visible;
1180 _e_input_panel_surface_visible_update(ips);
1183 _wait_update_timer_del();
1187 e_input_panel_client_find(E_Client *ec)
1189 E_Input_Panel_Surface *ips;
1192 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1194 if (!g_input_panel) return EINA_FALSE;
1196 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1198 if (!ips || !ips->ec) continue;
1199 if (ips->ec == ec) return EINA_TRUE;
1205 /* If ec is NULL, it will check the very first item that is found in our surfaces list */
1207 e_input_panel_client_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
1209 E_Input_Panel_Surface *ips;
1214 if (!g_input_panel) return EINA_FALSE;
1215 if (!x || !y || !w || !h) return EINA_FALSE;
1217 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1219 if (!ips || !ips->ec) continue;
1220 if (ips->ec == ec || !ec)
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;
1226 e_client_base_output_resolution_useful_geometry_get(ips->ec, &zx, &zy, &zw, &zh);
1230 *x = zh - ips->ec->y - ips->ec->client.h;
1236 *x = zh - ips->ec->y - ips->ec->client.h;
1237 *y = zw - ips->ec->x - ips->ec->client.w;
1243 *y = zw - ips->ec->x - ips->ec->client.w;
1264 _e_input_panel_idle_enter(void *data)
1266 E_Input_Panel_Surface *ips;
1269 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1271 if (!ips || !ips->ec) continue;
1275 if (!_e_input_panel_is_effect_running(ips->ec))
1280 ips->need_show = EINA_FALSE;
1285 return ECORE_CALLBACK_RENEW;
1289 e_input_panel_init(void)
1291 if (!e_comp_wl) return EINA_FALSE;
1293 if (!(g_input_panel = E_NEW(E_Input_Panel, 1)))
1295 /* ERR("Failed to allocate space for E_Input_Panel"); */
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);
1303 if (!g_input_panel->global)
1305 free(g_input_panel);
1306 g_input_panel = NULL;
1307 /* ERR("Failed to create global of wl_input_panel"); */
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);
1318 e_input_panel_shutdown(void)
1322 if (g_input_panel->resource)
1324 wl_resource_destroy(g_input_panel->resource);
1325 g_input_panel->resource = NULL;
1328 if (g_input_panel->global)
1330 wl_global_destroy(g_input_panel->global);
1331 g_input_panel->global = NULL;
1334 E_FREE_FUNC(g_input_panel->idle_enter, ecore_idle_enterer_del);
1337 if (g_floating_info)
1338 E_FREE(g_floating_info);
1342 _ips_client_frame_flush(E_Input_Panel_Surface *ips)
1347 if (e_object_is_del(E_OBJECT(ips->ec)))
1350 LOGI("IPS::FRAME::FLUSH ec %p\n", ips->ec);
1351 e_pixmap_image_clear(ips->ec->pixmap, EINA_TRUE);
1355 _ip_cb_e_buf_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
1358 E_Input_Panel_Surface *ips;
1362 if (EINA_UNLIKELY(!ev))
1365 if (EINA_UNLIKELY(!g_input_panel))
1368 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1370 if (!ips || ips->ec != ev->ec) continue;
1371 _ips_client_frame_flush(ips);
1375 return ECORE_CALLBACK_PASS_ON;
1379 e_input_panel_wait_update_set(Eina_Bool wait_update)
1381 E_Input_Panel_Surface *ips;
1387 g_input_panel->wait_update = wait_update;
1389 /* If we are in wait_update mode, the input panel surfaces have to be updated forcibly */
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);
1397 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1399 if (!ips || !ips->ec) continue;
1400 _ips_client_frame_flush(ips);
1403 if (!g_input_panel->buf_change_handler)
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);
1411 E_FREE_FUNC(g_input_panel->buf_change_handler, ecore_event_handler_del);
1415 e_input_panel_transient_for_set(E_Client *parent)
1417 LOGI("TRANSIENT_FOR::transient_for_set : %p\n", parent);
1418 E_Input_Panel_Surface *ips;
1420 E_Client *ec_parent = parent;
1422 /* finding the actual parent window that contains the remote surface. */
1425 if (!e_object_is_del(E_OBJECT(ec_parent)) &&
1426 (ec_parent->comp_data) && (ec_parent->comp_data->remote_surface.onscreen_parent))
1428 ec_parent = ec_parent->comp_data->remote_surface.onscreen_parent;
1432 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1435 E_Client *child = ips->ec;
1437 if (!child) continue;
1438 if (e_object_is_del(E_OBJECT(child)))
1440 LOGE("child is deleted");
1444 /* If the child already has a parent, remove it */
1447 if (e_object_is_del(E_OBJECT(child->parent)))
1449 LOGE("child->parent is deleted");
1453 LOGI("TRANSIENT_FOR::The child already has a parent : %p\n", child->parent);
1454 if (ec_parent != child->parent)
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);
1462 /* Append our child into parent's transients list */
1463 if ((ec_parent != child) && (ec_parent != child->parent))
1465 if ((ec_parent) && (eina_list_data_find(parent->transients, child) != child))
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);
1470 child->parent = ec_parent;
1475 child->icccm.fetch.transient_for = EINA_TRUE;
1476 child->icccm.transient_for = e_client_util_win_get(ec_parent);
1480 child->icccm.fetch.transient_for = EINA_FALSE;
1481 child->icccm.transient_for = 0;
1488 e_input_panel_show_need_rerun_set(Eina_Bool need_rerun)
1490 panel_show_need_rerun = need_rerun;
1494 e_input_panel_floating_position_set(int x, int y)
1497 E_Client *floating_ec = NULL;
1498 E_Input_Panel_Surface *floating_ips = NULL;
1499 E_Input_Panel_Surface *ips = NULL;
1503 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
1505 if (!ips || !ips->ec) continue;
1506 if (ips->ec->frame && ips->ec->vkbd.floating)
1508 floating_ec = ips->ec;
1514 if (!floating_ec || !floating_ips || !g_floating_info) return;
1516 if (floating_ips->showing)
1517 cur_angle = floating_ec->e.state.rot.ang.curr;
1519 cur_angle = floating_ec->zone->rot.curr;
1521 LOGI("current angle : %d", cur_angle);
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;
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;
1539 if (floating_ips->showing)
1540 _e_input_panel_position_set(floating_ec, floating_ec->client.w, floating_ec->client.h);
1544 e_input_panel_surface_destroy(E_Client *ec)
1547 E_Input_Panel_Surface *ips;
1551 if (!g_input_panel) return EINA_FALSE;
1553 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
1555 if (!ips || !ips->ec) continue;
1558 g_input_panel->surfaces = eina_list_remove_list(g_input_panel->surfaces, l);
1561 LOGI("Destroyed Waiting Resize Window. Starting Drawing Again");
1562 _e_input_panel_start_drawing(ips);
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)
1575 E_Input_Panel_Surface *ips = NULL;
1576 Eina_List *l = NULL;
1579 EINA_LIST_FOREACH(g_input_panel->surfaces, l, ips)
1581 if (!ips || !ips->ec) continue;
1582 if (_e_input_panel_is_effect_running(ips->ec))
1585 Do we need to check currently effect type?
1586 then what flag do we check? ips->ec->visible or ips->showing?
1588 if (ips->ec->visible)
1589 run_type = 1; // show effect is running
1591 run_type = 2; // hide effect is running
1600 void e_input_panel_floating_panel_set(Eina_Bool state)
1602 E_Input_Panel_Surface *ips;
1606 if (!g_input_panel) return;
1608 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
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);
1617 e_policy_conformant_part_add(ips->ec);
1622 void e_input_panel_floating_drag_enabled(Eina_Bool enabled)
1624 g_floating_info->moving_req = enabled;
1627 Eina_Bool e_input_panel_floating_mode_get()
1629 E_Input_Panel_Surface *ips;
1632 Eina_Bool ret = EINA_FALSE;
1634 if (!g_input_panel) return ret;
1636 EINA_LIST_FOREACH_SAFE(g_input_panel->surfaces, l, l_next, ips)
1640 ret = ips->ec->vkbd.floating;