aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@osg.samsung.com>2017-08-11 18:43:15 -0400
committerMike Blumenkrantz <zmike@osg.samsung.com>2017-08-11 18:43:13 -0400
commit2d1e5da35dcbe0c913ec19170dd59fa9f2f378cc (patch)
treede27b9540f89ab35761319dcbc20e6d519dbf028
parentefl-wl: add EFL_WL_DEBUG env variable for enabling wayland debug (diff)
downloadefl-2d1e5da35dcbe0c913ec19170dd59fa9f2f378cc.tar.gz
efl-wl: add functionality for extracting surfaces for external use
@feature
-rw-r--r--src/lib/efl_wl/Efl_Wl.h12
-rw-r--r--src/lib/efl_wl/efl_wl.c86
2 files changed, 91 insertions, 7 deletions
diff --git a/src/lib/efl_wl/Efl_Wl.h b/src/lib/efl_wl/Efl_Wl.h
index 818cc39cd4..d4385d2a59 100644
--- a/src/lib/efl_wl/Efl_Wl.h
+++ b/src/lib/efl_wl/Efl_Wl.h
@@ -131,6 +131,18 @@ EAPI void efl_wl_minmax_set(Evas_Object *obj, Eina_Bool set);
* @since 1.21
*/
EAPI void *efl_wl_global_add(Evas_Object *obj, const void *interface, uint32_t version, void *data, void *bind_cb);
+
+/**
+ * Extract a child surface from the compositor
+ *
+ * An extracted surface can be freely manipulated by external code.
+ * @note size hints must be respected, and the extracted object must not be externally deleted
+ *
+ * @param surface The surface to extract
+ * @return True if the surface was successfully extracted
+ * @since 1.21
+ */
+EAPI Eina_Bool efl_wl_surface_extract(Evas_Object *surface);
#endif
#endif
diff --git a/src/lib/efl_wl/efl_wl.c b/src/lib/efl_wl/efl_wl.c
index 5c4fb32c04..213d295a66 100644
--- a/src/lib/efl_wl/efl_wl.c
+++ b/src/lib/efl_wl/efl_wl.c
@@ -325,6 +325,7 @@ struct Comp_Surface
Eina_Bool post_render_queue : 1;
Eina_Bool dead : 1;
Eina_Bool commit : 1;
+ Eina_Bool extracted : 1;
};
struct Comp_Subsurface
@@ -463,19 +464,22 @@ static inline void
comp_surface_reparent(Comp_Surface *cs, Comp_Surface *pcs)
{
if (cs->parent == pcs) return;
- evas_object_smart_member_del(cs->obj);
+ if (!cs->extracted)
+ evas_object_smart_member_del(cs->obj);
if (cs->parent)
cs->parent->children = eina_inlist_remove(cs->parent->children, EINA_INLIST_GET(cs));
if (pcs)
{
cs->c->surfaces = eina_inlist_remove(cs->c->surfaces, EINA_INLIST_GET(cs));
cs->c->surfaces_count--;
- evas_object_smart_member_add(cs->obj, pcs->obj);
+ if (!cs->extracted)
+ evas_object_smart_member_add(cs->obj, pcs->obj);
pcs->children = eina_inlist_append(pcs->children, EINA_INLIST_GET(cs));
}
else
{
- evas_object_smart_member_add(cs->obj, cs->c->obj);
+ if (!cs->extracted)
+ evas_object_smart_member_add(cs->obj, cs->c->obj);
cs->c->surfaces = eina_inlist_append(cs->c->surfaces, EINA_INLIST_GET(cs));
cs->c->surfaces_count++;
}
@@ -1175,6 +1179,7 @@ shell_surface_minmax_update(Comp_Surface *cs)
if (!cs) return;
if (!cs->c->minmax) return;
+ if (cs->extracted) return;
evas_object_size_hint_min_get(cs->obj, &w, &h);
evas_object_size_hint_min_set(cs->c->obj, w, h);
evas_object_size_hint_max_get(cs->obj, &w, &h);
@@ -1189,6 +1194,7 @@ shell_surface_aspect_update(Comp_Surface *cs)
if (!cs) return;
if (!cs->c->aspect) return;
+ if (cs->extracted) return;
evas_object_size_hint_aspect_get(cs->obj, &aspect, &w, &h);
evas_object_size_hint_aspect_set(cs->c->obj, aspect, w, h);
}
@@ -1218,7 +1224,8 @@ shell_surface_send_configure(Comp_Surface *cs)
{
s = wl_array_add(&states, sizeof(uint32_t));
*s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED;
- evas_object_raise(cs->obj);
+ if (!cs->extracted)
+ evas_object_raise(cs->obj);
if (cs->parent)
cs->parent->children = eina_inlist_demote(cs->parent->children, EINA_INLIST_GET(cs));
else
@@ -1226,7 +1233,10 @@ shell_surface_send_configure(Comp_Surface *cs)
shell_surface_activate_recurse(cs);
}
serial = wl_display_next_serial(cs->c->display);
- evas_object_geometry_get(cs->c->clip, NULL, NULL, &w, &h);
+ if (cs->extracted)
+ evas_object_geometry_get(cs->obj, NULL, NULL, &w, &h);
+ else
+ evas_object_geometry_get(cs->c->clip, NULL, NULL, &w, &h);
zxdg_toplevel_v6_send_configure(cs->role, w, h, &states);
zxdg_surface_v6_send_configure(cs->shell.surface, serial);
wl_array_release(&states);
@@ -1398,6 +1408,11 @@ comp_surface_commit_state(Comp_Surface *cs, Comp_Buffer_State *state)
{
evas_object_move(cs->img, x + buffer->x, y + buffer->y);
evas_object_resize(cs->obj, buffer->w, buffer->h);
+ if (cs->shell.popup)
+ {
+ evas_object_size_hint_min_set(cs->obj, buffer->w, buffer->h);
+ evas_object_size_hint_max_set(cs->obj, buffer->w, buffer->h);
+ }
}
else if (cs->shell.new)
shell_surface_init(cs);
@@ -2349,7 +2364,7 @@ comp_surface_smart_hide(Evas_Object *obj)
if (!evas_object_visible_get(lcs->obj)) continue;
if ((!lcs->shell.surface) || (!lcs->role)) continue;
lcs->shell.activated = 1;
- if (lcs->shell.popup)
+ if (lcs->shell.popup && (!lcs->extracted))
evas_object_raise(lcs->obj);
else
shell_surface_send_configure(lcs);
@@ -3071,6 +3086,7 @@ shell_surface_toplevel_set_parent(struct wl_client *client EINA_UNUSED, struct w
if (parent_resource) pcs = wl_resource_get_user_data(parent_resource);
comp_surface_reparent(cs, pcs);
+ evas_object_smart_callback_call(cs->c->obj, "child_added", cs->obj);
}
static void
@@ -3256,6 +3272,7 @@ shell_surface_popup_create(struct wl_client *client, struct wl_resource *resourc
comp_surface_reparent(cs, wl_resource_get_user_data(parent_resource));
cs->shell.positioner = wl_resource_get_user_data(positioner_resource);
_apply_positioner(cs, cs->shell.positioner);
+ evas_object_smart_callback_call(cs->c->obj, "popup_added", cs->obj);
}
static void
@@ -5135,7 +5152,7 @@ comp_smart_resize(Evas_Object *obj, int w, int h)
output_resize(c, res);
//fprintf(stderr, "COMP %dx%d\n", w, h);
EINA_INLIST_FOREACH(c->surfaces, cs)
- if (cs->shell.surface && cs->role)
+ if (cs->shell.surface && cs->role && (!cs->extracted))
shell_surface_send_configure(cs);
}
@@ -5457,3 +5474,58 @@ efl_wl_global_add(Evas_Object *obj, const void *interface, uint32_t version, voi
c = evas_object_smart_data_get(obj);
return wl_global_create(c->display, interface, version, data, bind_cb);
}
+
+static void
+extracted_focus(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Comp_Surface *cs = data;
+
+ if (cs->dead) return;
+ if (!cs->shell.popup)
+ {
+ cs->shell.activated = 1;
+ shell_surface_send_configure(data);
+ }
+ evas_object_focus_set(cs->c->obj, 1);
+}
+
+static void
+extracted_unfocus(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+ Comp_Surface *cs = data;
+ Evas_Object *focus;
+
+ if (cs->dead) return;
+ focus = evas_focus_get(cs->c->evas);
+ if ((!focus) || (focus == cs->c->obj)) return;
+ cs->shell.activated = 0;
+ shell_surface_send_configure(data);
+}
+
+static void
+extracted_changed(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+ Comp_Surface *cs = data;
+
+ if (cs->dead) return;
+ shell_surface_send_configure(data);
+}
+
+EAPI Eina_Bool
+efl_wl_surface_extract(Evas_Object *surface)
+{
+ Comp_Surface *cs;
+ if (!eina_streq(evas_object_type_get(surface), "comp_surface")) abort();
+ cs = evas_object_smart_data_get(surface);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(cs->extracted, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(cs->dead, EINA_FALSE);
+ cs->extracted = 1;
+ if (!cs->shell.popup)
+ {
+ evas_object_event_callback_add(cs->obj, EVAS_CALLBACK_RESIZE, extracted_changed, cs);
+ evas_object_event_callback_add(cs->obj, EVAS_CALLBACK_FOCUS_OUT, extracted_unfocus, cs);
+ }
+ evas_object_event_callback_add(cs->obj, EVAS_CALLBACK_FOCUS_IN, extracted_focus, cs);
+ evas_object_smart_member_del(surface);
+ return EINA_TRUE;
+}