From: Doyoun Kang Date: Mon, 1 Apr 2024 10:20:31 +0000 (+0900) Subject: support modal feature X-Git-Tag: accepted/tizen/8.0/unified/20240402.151511~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f4b543a7c20c5e9ab2b13b709c1da474b131b639;p=platform%2Fupstream%2Fenlightenment.git support modal feature We add the modal feature for transient_for child. If the child set the modal state, then the parent of it cannot get focus and input event. FYI, this feature is supported since tizen_policy version 13. Change-Id: Ibedf7aeb32dc55533de518500aa2a8c81e14ed25 --- diff --git a/src/bin/e_client.c b/src/bin/e_client.c index 694ed491cd..a5bd8a6bea 100644 --- a/src/bin/e_client.c +++ b/src/bin/e_client.c @@ -80,6 +80,8 @@ struct _E_Client_Private Eina_Bool hide_by_request; Eina_Bool focus_check; + + E_Client *modal; }; static int _e_client_hooks_delete = 0; @@ -1063,6 +1065,8 @@ _e_client_del(E_Client *ec) if (ec->parent) { + if (e_client_modal_child_get(ec->parent) == ec) + e_client_modal_child_set(ec->parent, NULL); ec->parent->transients = eina_list_remove(ec->parent->transients, ec); ec->parent = NULL; } @@ -3012,6 +3016,49 @@ e_client_mapped_set(E_Client *ec, Eina_Bool set) cdata->mapped = set; } +EINTERN void +e_client_modal_child_set(E_Client *ec, E_Client *modal) +{ + API_ENTRY; + + E_Client *old_modal = priv->modal; + if (old_modal == modal) return; + + ELOGF("E_CLIENT", "SET modal. new(ec:%p, win:0x%08zx), old(ec:%p, win:0x%08zx)", ec, + modal, e_client_util_win_get(modal), old_modal, e_client_util_win_get(old_modal)); + + // TODO: if ec has a modal window already, then how does we do? + priv->modal = modal; +} + +EINTERN E_Client * +e_client_modal_child_get(E_Client *ec) +{ + API_ENTRY_VAL(NULL); + return priv->modal; +} + +EINTERN void +e_client_modal_state_set(E_Client *ec, Eina_Bool modal) +{ + if (!ec) return; + ec->netwm.state.modal = modal; + + if (ec->parent) + { + if (ec->netwm.state.modal) + e_client_modal_child_set(ec->parent, ec); + else + e_client_modal_child_set(ec->parent, NULL); + } +} + +EINTERN Eina_Bool +e_client_is_modal_state(E_Client *ec) +{ + if (!ec) return EINA_FALSE; + return ec->netwm.state.modal; +} //////////////////////////////////////////////// EINTERN Eina_Bool diff --git a/src/bin/e_client.h b/src/bin/e_client.h index 5013769585..c19da87b6c 100644 --- a/src/bin/e_client.h +++ b/src/bin/e_client.h @@ -1180,6 +1180,10 @@ E_API void e_client_post_raise_lower_set(E_Client *ec, Eina_Bool raise_set, E_API Eina_Bool e_client_first_mapped_get(E_Client *ec); EINTERN Eina_Bool e_client_mapped_get(E_Client *ec); EINTERN void e_client_mapped_set(E_Client *ec, Eina_Bool set); +EINTERN void e_client_modal_child_set(E_Client *ec, E_Client *modal_child); +EINTERN E_Client *e_client_modal_child_get(E_Client *ec); +EINTERN void e_client_modal_state_set(E_Client *ec, Eina_Bool modal); +EINTERN Eina_Bool e_client_is_modal_state(E_Client *ec); E_API void e_client_transform_update(E_Client *ec); EINTERN void e_client_transform_apply(E_Client *ec, double degree, double zoom, int cx, int cy); diff --git a/src/bin/e_comp_object.c b/src/bin/e_comp_object.c index 902b53de26..d0b2e82da1 100644 --- a/src/bin/e_comp_object.c +++ b/src/bin/e_comp_object.c @@ -2793,6 +2793,20 @@ _e_comp_intercept_focus(void *data, Evas_Object *obj, Eina_Bool focus) if (focus) { + /* check for modal child and set focus to modal child */ + E_Client *modal_child = e_client_modal_child_get(ec); + if ((modal_child) && (modal_child != ec) && + (!e_client_is_iconified_by_client(modal_child)) && + (modal_child->visible) && (!e_object_is_del(E_OBJECT(modal_child)))) + { + // add ec to latest focus stack + e_client_focus_latest_set(ec); + + ELOGF("FOCUS", "FOCUS SET to MODAL (ec:%p, win:0x%08zx, frame:%p)", ec, modal_child, e_client_util_win_get(modal_child), modal_child->frame); + //e_client_focused_set(modal_child); + evas_object_focus_set(modal_child->frame, focus); + return; + } if (!cw->visible) { /* not yet visible, wait till the next time... */ diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index 7728a6a042..fe04a78000 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -1244,6 +1244,22 @@ _e_comp_wl_check_cursor_timer_needed(E_Client *ec) return EINA_TRUE; } +static Eina_Bool +_e_comp_wl_check_block_input(E_Client *ec) +{ + E_Client *modal_child = e_client_modal_child_get(ec); + if (modal_child) + { + if (modal_child->visible && !modal_child->iconic && (modal_child->visibility.obscured == E_VISIBILITY_UNOBSCURED)) + { + ELOGF("Touch", "Block touch by Modal child(ec:%p, win:0x%08zx)", ec, modal_child, e_client_util_win_get(modal_child)); + return EINA_TRUE; + } + } + + return EINA_FALSE; +} + static void _e_comp_wl_evas_cb_mouse_in(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event) { @@ -1374,6 +1390,8 @@ _e_comp_wl_send_touch(E_Client *ec, int idx, int canvas_x, int canvas_y, uint32_ if (!ec) return; if (e_object_is_del(E_OBJECT(ec))) return; + if (_e_comp_wl_check_block_input(ec)) return; + struct wl_resource *surface = e_comp_wl_client_surface_get(ec); if (!surface) return; @@ -1422,6 +1440,8 @@ _e_comp_wl_send_touch_move(E_Client *ec, int idx, int canvas_x, int canvas_y, ui if (!ec) return; if (ec->cur_mouse_action) return; if (e_object_is_del(E_OBJECT(ec))) return; + if (_e_comp_wl_check_block_input(ec)) return; + struct wl_resource *surface = e_comp_wl_client_surface_get(ec); if (!surface) return; @@ -1584,6 +1604,7 @@ _e_comp_wl_evas_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *o if (!ec) return; if (e_object_is_del(E_OBJECT(ec))) return; + if (_e_comp_wl_check_block_input(ec)) return; dev = ev->dev; dev_name = evas_device_description_get(dev); @@ -1642,6 +1663,7 @@ _e_comp_wl_evas_cb_mouse_up(void *data, Evas *evas, Evas_Object *obj, void *even if (!ec) return; if (ec->cur_mouse_action) return; if (e_object_is_del(E_OBJECT(ec))) return; + if (_e_comp_wl_check_block_input(ec)) return; if (!need_send_released) { @@ -1778,6 +1800,8 @@ _e_comp_wl_evas_cb_multi_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *o if (!ec) return; if (e_object_is_del(E_OBJECT(ec))) return; + if (_e_comp_wl_check_block_input(ec)) return; + struct wl_resource *surface = e_comp_wl_client_surface_get(ec); if (!surface) return; @@ -1822,6 +1846,8 @@ _e_comp_wl_evas_cb_multi_up(void *data, Evas *evas, Evas_Object *obj EINA_UNUSED if (!ec) return; if (e_object_is_del(E_OBJECT(ec))) return; + if (_e_comp_wl_check_block_input(ec)) return; + struct wl_resource *surface = e_comp_wl_client_surface_get(ec); if (!surface) return; diff --git a/src/bin/e_focus_policy_history.c b/src/bin/e_focus_policy_history.c index 82fbbe7b47..594a05cfe5 100644 --- a/src/bin/e_focus_policy_history.c +++ b/src/bin/e_focus_policy_history.c @@ -577,6 +577,12 @@ _focus_policy_history_cb_client_focus_set(struct wl_listener *listener, void *da } } + if (ec->parent && !e_object_is_del(E_OBJECT(ec->parent))) + { + if (e_client_modal_child_get(ec->parent) == ec) + _focus_policy_history_focus_stack_latest_set(history_policy, ec->parent); + } + _focus_policy_history_focus_stack_latest_set(history_policy, ec); // assign the focused_ec diff --git a/src/bin/e_info_server.c b/src/bin/e_info_server.c index d021d0c1af..d63a343a3f 100644 --- a/src/bin/e_info_server.c +++ b/src/bin/e_info_server.c @@ -7511,6 +7511,10 @@ _e_info_server_prop_set(E_Client *ec, const char *property, int set) { e_client_pinned_set(ec, set); } + else if (!e_util_strcmp("modal", property)) + { + e_client_modal_state_set(ec, set); + } else { ERR("Not supported operation (%s)", property); diff --git a/src/bin/e_info_shared_types.h b/src/bin/e_info_shared_types.h index ea93cd1b55..488ffe0183 100644 --- a/src/bin/e_info_shared_types.h +++ b/src/bin/e_info_shared_types.h @@ -334,9 +334,10 @@ typedef enum /* PROPERTY_SET */ /* -------------------------------------------------------------------------- */ #define USAGE_PROPERTY_SET \ - "-prop_set {window id} ( pin ) ( 1 | 0) \n" \ + "-prop_set {window id} ( pin | modal ) ( 1 | 0) \n" \ "Example:\n" \ - "\twinfo -prop_set 0x12345678 pin 1\n" + "\twinfo -prop_set 0x12345678 pin 1\n" \ + "\twinfo -prop_set 0x12345678 modal 1\n" /* -------------------------------------------------------------------------- */ /* QUICKPANEL CONTROL */ diff --git a/src/bin/e_policy_stack.c b/src/bin/e_policy_stack.c index 9b7fc77248..378d3547b3 100644 --- a/src/bin/e_policy_stack.c +++ b/src/bin/e_policy_stack.c @@ -313,6 +313,8 @@ _e_policy_stack_transient_for_set(E_Client *ec, E_Client *parent, Eina_Bool tran { ec->parent->transients = eina_list_remove(ec->parent->transients, ec); + if (e_client_modal_child_get(ec->parent) == ec) + e_client_modal_child_set(ec->parent, NULL); ec->parent = NULL; ec->icccm.fetch.transient_for = EINA_TRUE; @@ -340,6 +342,8 @@ _e_policy_stack_transient_for_set(E_Client *ec, E_Client *parent, Eina_Bool tran { ec->parent->transients = eina_list_remove(ec->parent->transients, ec); + if (e_client_modal_child_get(ec->parent) == ec) + e_client_modal_child_set(ec->parent, NULL); ec->parent = NULL; } @@ -351,6 +355,8 @@ _e_policy_stack_transient_for_set(E_Client *ec, E_Client *parent, Eina_Bool tran else parent->transients = eina_list_append(parent->transients, ec); ec->parent = parent; + if (e_client_is_modal_state(ec)) + e_client_modal_child_set(ec->parent, ec); } if (ec->parent) diff --git a/src/bin/e_policy_wl.c b/src/bin/e_policy_wl.c index 554f0e68c9..fef1f5116e 100644 --- a/src/bin/e_policy_wl.c +++ b/src/bin/e_policy_wl.c @@ -3704,6 +3704,34 @@ _tzpol_iface_cb_set_layout(struct wl_client *client EINA_UNUSED, struct wl_resou } } +static void +_e_policy_set_modal(E_Client *ec, Eina_Bool modal) +{ + EINA_SAFETY_ON_NULL_RETURN(ec); + EINA_SAFETY_ON_NULL_RETURN(ec->frame); + + ELOGF("TZPOL", "Set modal to %d", ec, modal); + e_client_modal_state_set(ec, modal); +} + +static void +_tzpol_iface_cb_set_modal(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf) +{ + E_Client *ec; + + ec = e_client_from_surface_resource(surf); + _e_policy_set_modal(ec, EINA_TRUE); +} + +static void +_tzpol_iface_cb_unset_modal(struct wl_client *client EINA_UNUSED, struct wl_resource *res_tzpol EINA_UNUSED, struct wl_resource *surf) +{ + E_Client *ec; + + ec = e_client_from_surface_resource(surf); + _e_policy_set_modal(ec, EINA_FALSE); +} + // -------------------------------------------------------- // tizen_policy_interface // -------------------------------------------------------- @@ -3756,7 +3784,9 @@ static const struct tizen_policy_interface _tzpol_iface = _tzpol_iface_cb_set_maximize_direction, _tzpol_iface_cb_set_pin_mode, _tzpol_iface_cb_unset_pin_mode, - _tzpol_iface_cb_set_layout + _tzpol_iface_cb_set_layout, + _tzpol_iface_cb_set_modal, + _tzpol_iface_cb_unset_modal, }; static void @@ -8745,7 +8775,7 @@ e_policy_wl_init(void) /* create globals */ global = wl_global_create(e_comp_wl->wl.disp, &tizen_policy_interface, - 12, + 13, NULL, _tzpol_cb_bind); EINA_SAFETY_ON_NULL_GOTO(global, err);