From e78c1843ae37a6448e5cc440481e7c6d4eb94629 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 3 Jan 2018 18:45:06 -0500 Subject: [PATCH] handle tooltips in sandboxed gadgets fix T6335 --- src/bin/e_gadget_loader.c | 17 +++++ src/bin/e_gadget_runner.c | 142 +++++++++++++++++++++++++++++++++----- src/protocol/e-gadget.xml | 3 + 3 files changed, 145 insertions(+), 17 deletions(-) diff --git a/src/bin/e_gadget_loader.c b/src/bin/e_gadget_loader.c index 1b32304f5..99b75e0a4 100644 --- a/src/bin/e_gadget_loader.c +++ b/src/bin/e_gadget_loader.c @@ -13,6 +13,7 @@ static Eina_Hash *wins; static Eina_Hash *gadget_globals; static Eina_Hash *ar_globals; static Eina_Hash *display_actions; +static Eina_List *tooltips; typedef struct Gadget_Action { @@ -70,9 +71,14 @@ static const struct e_gadget_listener _gadget_listener = static void _gadget_global_bind(Ecore_Wl2_Display *d, uint32_t id) { + Eina_List *l; + Evas_Object *tt; + struct e_gadget *gadget_global = wl_registry_bind(ecore_wl2_display_registry_get(d), id, &e_gadget_interface, 1); e_gadget_add_listener(gadget_global, &_gadget_listener, d); eina_hash_add(gadget_globals, &d, gadget_global); + EINA_LIST_FOREACH(tooltips, l, tt) + e_gadget_set_tooltip(gadget_global, ecore_wl2_window_surface_get(elm_win_wl_window_get(tt))); } static void @@ -256,6 +262,7 @@ win_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *eve { Ecore_Wl2_Display *d = win_display_get(obj); eina_hash_list_remove(wins, &d, obj); + tooltips = eina_list_remove(tooltips, obj); } static Evas_Object * @@ -265,6 +272,16 @@ win_add(Evas_Object *win) if (!win) return NULL; d = win_display_get(win); _gadget_init(d); + if (elm_win_type_get(win) == ELM_WIN_TOOLTIP) + { + tooltips = eina_list_append(tooltips, win); + if (eina_hash_population(gadget_globals)) + { + struct e_gadget *gadget_global = eina_hash_find(gadget_globals, &d); + if (gadget_global) + e_gadget_set_tooltip(gadget_global, ecore_wl2_window_surface_get(elm_win_wl_window_get(win))); + } + } if (!wins) wins = eina_hash_pointer_new(NULL); eina_hash_list_append(wins, &d, win); diff --git a/src/bin/e_gadget_runner.c b/src/bin/e_gadget_runner.c index eb11b6ecb..d6fbeb76d 100644 --- a/src/bin/e_gadget_runner.c +++ b/src/bin/e_gadget_runner.c @@ -43,6 +43,14 @@ typedef struct Config_Item Eina_Bool cmd_changed E_BITFIELD; } Config_Item; +typedef struct Tooltip +{ + Evas_Object *obj; + Evas_Object *content; + Evas_Object *tooltip_content; + struct wl_resource *tooltip_surface; +} Tooltip; + typedef struct Instance { Evas_Object *box; @@ -50,9 +58,9 @@ typedef struct Instance Ecore_Exe *exe; Config_Item *ci; Eina_Hash *allowed_pids; + Eina_List *tooltip_surfaces; void *gadget_resource; - Evas_Object *popup; - Evas_Object *ctxpopup; + Tooltip popup, ctxpopup, base; Eina_List *extracted; } Instance; @@ -379,6 +387,7 @@ runner_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info E E_FREE_FUNC(inst->exe, ecore_exe_terminate); instances = eina_list_remove(instances, inst); eina_hash_free(inst->allowed_pids); + eina_list_free(inst->tooltip_surfaces); free(inst); } @@ -415,9 +424,18 @@ gadget_open_uri(struct wl_client *client EINA_UNUSED, struct wl_resource *resour e_util_open(uri, NULL); } +static void +gadget_set_tooltip(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *surface) +{ + Instance *inst = wl_resource_get_user_data(resource); + + inst->tooltip_surfaces = eina_list_append(inst->tooltip_surfaces, surface); +} + static const struct e_gadget_interface _gadget_interface = { .open_uri = gadget_open_uri, + .set_tooltip = gadget_set_tooltip, }; static void @@ -476,7 +494,8 @@ child_close(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info Instance *inst = data; Evas_Object *ext; - inst->popup = NULL; + inst->popup.obj = NULL; + inst->popup.content = NULL; ext = evas_object_data_get(obj, "extracted"); elm_box_unpack_all(obj); inst->extracted = eina_list_remove(inst->extracted, ext); @@ -492,6 +511,7 @@ child_added(void *data, Evas_Object *obj, void *event_info) if (!efl_wl_surface_extract(event_info)) return; inst->extracted = eina_list_append(inst->extracted, event_info); + inst->popup.content = event_info; popup = elm_popup_add(e_comp->elm); e_comp_object_util_del_list_append(event_info, popup); @@ -508,7 +528,7 @@ child_added(void *data, Evas_Object *obj, void *event_info) elm_box_pack_end(bx, event_info); elm_object_content_set(popup, bx); - inst->popup = popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE); + inst->popup.obj = popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE); evas_object_layer_set(popup, E_LAYER_POPUP); evas_object_move(popup, zone->x, zone->y); evas_object_resize(popup, zone->w / 4, zone->h / 3); @@ -521,17 +541,24 @@ child_added(void *data, Evas_Object *obj, void *event_info) evas_object_focus_set(event_info, 1); } +static void +extracted_del(Instance *inst, Evas_Object *ext) +{ + inst->extracted = eina_list_remove(inst->extracted, ext); + evas_object_hide(ext); +} + static void popup_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { Instance *inst = data; Evas_Object *ext; - inst->ctxpopup = NULL; + inst->ctxpopup.obj = NULL; + inst->ctxpopup.content = NULL; ext = evas_object_data_get(obj, "extracted"); elm_box_unpack_all(obj); - inst->extracted = eina_list_remove(inst->extracted, ext); - evas_object_hide(ext); + extracted_del(inst, ext); } static void @@ -544,8 +571,8 @@ static void popup_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Instance *inst = data; - elm_ctxpopup_dismiss(inst->ctxpopup); - evas_object_del(elm_object_content_get(inst->ctxpopup)); + elm_ctxpopup_dismiss(inst->ctxpopup.obj); + evas_object_del(elm_object_content_get(inst->ctxpopup.obj)); } static void @@ -580,6 +607,46 @@ popup_hints(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, popup_hints, data); } +static void +tooltip_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Tooltip *tt = data; + Instance *inst = evas_object_data_get(tt->tooltip_content, "instance"); + + tt->tooltip_content = NULL; + inst->tooltip_surfaces = eina_list_remove(inst->tooltip_surfaces, tt->tooltip_surface); + tt->tooltip_surface = NULL; + elm_object_tooltip_unset(tt->obj); + extracted_del(inst, obj); +} + +static void +tooltip_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Tooltip *tt = data; + + elm_box_unpack_all(obj); + tt->tooltip_content = NULL; + tt->tooltip_surface = NULL; + evas_object_hide(data); +} + +static Evas_Object * +tooltip_content_cb(void *data, Evas_Object *obj EINA_UNUSED, Evas_Object *tooltip) +{ + Evas_Object *bx; + Tooltip *tt = data; + + bx = elm_box_add(tooltip); + evas_object_pass_events_set(bx, 1); + evas_object_event_callback_add(bx, EVAS_CALLBACK_DEL, tooltip_hide, tt->tooltip_content); + elm_box_pack_end(bx, tt->tooltip_content); + evas_object_show(tt->tooltip_content); + elm_box_recalculate(bx); + evas_object_show(bx); + return bx; +} + static void popup_added(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) { @@ -588,13 +655,54 @@ popup_added(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) if (!efl_wl_surface_extract(event_info)) return; inst->extracted = eina_list_append(inst->extracted, event_info); + if (inst->tooltip_surfaces) + { + Eina_List *l; + struct wl_resource *surface; + + EINA_LIST_FOREACH(inst->tooltip_surfaces, l, surface) + if (event_info == efl_wl_extracted_surface_object_find(surface)) + { + Evas_Object *base = efl_wl_extracted_surface_extracted_parent_get(event_info); + Tooltip *tt; + + //FIXME: if (inst->tooltip_content) error + if (base) + { + if (base == inst->popup.content) + tt = &inst->popup; + else if (base == inst->ctxpopup.content) + tt = &inst->ctxpopup; + } + else // base tooltip + tt = &inst->base; + if (tt) + { + tt->tooltip_surface = surface; + tt->tooltip_content = event_info; + evas_object_data_set(event_info, "instance", inst); + evas_object_pass_events_set(event_info, 1); + evas_object_event_callback_add(event_info, EVAS_CALLBACK_DEL, tooltip_del, tt); + elm_object_tooltip_content_cb_set(tt->obj, tooltip_content_cb, tt, NULL); + } + else + { + inst->extracted = eina_list_remove(inst->extracted, event_info); + evas_object_hide(event_info); + } + return; + } + } + + //FIXME: if (inst->ctxpopup.obj) error - inst->ctxpopup = elm_ctxpopup_add(inst->box); - elm_object_style_set(inst->ctxpopup, "noblock"); - evas_object_smart_callback_add(inst->ctxpopup, "dismissed", popup_dismissed, inst); + inst->ctxpopup.obj = elm_ctxpopup_add(inst->box); + inst->ctxpopup.content = event_info; + elm_object_style_set(inst->ctxpopup.obj, "noblock"); + evas_object_smart_callback_add(inst->ctxpopup.obj, "dismissed", popup_dismissed, inst); evas_object_event_callback_add(event_info, EVAS_CALLBACK_DEL, popup_hide, inst); - bx = elm_box_add(inst->ctxpopup); + bx = elm_box_add(inst->ctxpopup.obj); popup_hints_update(event_info); E_FILL(event_info); evas_object_event_callback_add(event_info, EVAS_CALLBACK_CHANGED_SIZE_HINTS, popup_hints, inst); @@ -603,10 +711,10 @@ popup_added(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) elm_box_recalculate(bx); evas_object_data_set(bx, "extracted", event_info); evas_object_event_callback_add(bx, EVAS_CALLBACK_DEL, popup_del, inst); - elm_object_content_set(inst->ctxpopup, bx); + elm_object_content_set(inst->ctxpopup.obj, bx); - e_gadget_util_ctxpopup_place(inst->box, inst->ctxpopup, NULL); - evas_object_show(inst->ctxpopup); + e_gadget_util_ctxpopup_place(inst->box, inst->ctxpopup.obj, NULL); + evas_object_show(inst->ctxpopup.obj); evas_object_focus_set(event_info, 1); } @@ -657,7 +765,7 @@ gadget_create(Evas_Object *parent, Config_Item *ci, int *id, E_Gadget_Site_Orien evas_object_smart_callback_add(parent, "gadget_site_gravity", runner_site_gravity, inst); runner_run(inst); ecore_exe_data_set(inst->exe, inst); - inst->box = elm_box_add(e_comp->elm); + inst->base.obj = inst->box = elm_box_add(e_comp->elm); evas_object_event_callback_add(inst->box, EVAS_CALLBACK_DEL, runner_del, inst); evas_object_event_callback_add(inst->obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, runner_hints, inst); elm_box_homogeneous_set(inst->box, 1); diff --git a/src/protocol/e-gadget.xml b/src/protocol/e-gadget.xml index 837c2606b..eb0e65626 100644 --- a/src/protocol/e-gadget.xml +++ b/src/protocol/e-gadget.xml @@ -33,6 +33,9 @@ + + +