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: Ibd8cee7134515b62c7dcd191fc47482e7297496c
Eina_Bool hide_by_request;
Eina_Bool focus_check;
+
+ E_Client *modal;
};
static int _e_client_hooks_delete = 0;
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;
}
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
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);
+
EINTERN void e_client_transform_apply(E_Client *ec, double degree, double zoom, int cx, int cy);
EINTERN void e_client_transform_clear(E_Client *ec);
EINTERN void e_client_transform_core_input_inv_rect_transform(E_Client *ec, int x, int y, int *out_x, int *out_y);
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... */
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)
{
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;
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;
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);
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)
{
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;
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;
}
#endif
+ 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
{
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);
{
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;
{
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;
}
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)
e_client_shell_configure_send(ec, 0, w, h);
}
+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
// --------------------------------------------------------
_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
/* 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);
/* NetWM Window state */
struct
{
- EINA_DEPRECATED unsigned char modal : 1;
+ unsigned char modal : 1;
EINA_DEPRECATED unsigned char sticky : 1;
EINA_DEPRECATED unsigned char maximized_v : 1;
EINA_DEPRECATED unsigned char maximized_h : 1;
/* 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 */