static void _e_comp_wl_subsurface_place_below(E_Client *parent, E_Client *subc, E_Client *below);
static void _e_comp_wl_subsurface_stack_update(E_Client *ec);
-static E_Subsurface *_e_comp_wl_subsurface_create(void);
+static E_Subsurface *_e_comp_wl_subsurface_create(struct wl_resource *resource, E_Client *ec, E_Client *epc, E_Client *offscreen_parent);
static void _e_comp_wl_subsurface_destroy(E_Subsurface *sub);
static void _e_comp_wl_subsurface_ec_link(E_Subsurface *sub, E_Client *ec);
static void _e_comp_wl_subsurface_parent_link(E_Subsurface *sub, E_Client *parent);
}
static void
-_e_comp_wl_subcompositor_cb_subsurface_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource)
+_e_comp_wl_subcompositor_cb_subsurface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, struct wl_resource *parent_surface)
{
- E_Client *ec, *epc = NULL;
- static const char where[] = "get_subsurface: wl_subsurface@";
-
- if (!(ec = wl_resource_get_user_data(surface_resource))) return;
- if (!(epc = wl_resource_get_user_data(parent_resource))) return;
+ Eina_Bool res;
- if (ec == epc)
- {
- wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
- "%s%d: wl_surface@%d cannot be its own parent",
- where, id, wl_resource_get_id(surface_resource));
- return;
- }
-
- if (e_object_is_del(E_OBJECT(ec))) return;
- if (e_object_is_del(E_OBJECT(epc))) return;
-
- /* check if this surface is already a sub-surface */
- if ((ec->comp_data) && (ec->comp_data->sub.data))
- {
- wl_resource_post_error(resource,
- WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
- "%s%d: wl_surface@%d is already a sub-surface",
- where, id, wl_resource_get_id(surface_resource));
- return;
- }
-
- /* try to create a new subsurface */
- if (!e_comp_wl_subsurface_create(ec, epc, id, surface_resource))
+ res = e_comp_wl_subsurface_add(client, resource, id,
+ surface, parent_surface);
+ if (!res)
{
- if (_e_comp_wl_subsurface_circular_reference_check(ec, epc))
- {
- wl_resource_post_error(resource,
- WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
- "%s%d: wl_surface@%d is an ancestor of parent",
- where, id, wl_resource_get_id(surface_resource));
- }
-
- ERR("Failed to create subsurface for surface %d",
- wl_resource_get_id(surface_resource));
+ ERR("Failed to add subsurface for surface %d",
+ wl_resource_get_id(surface));
}
}
* to not post error to wl_client. */
e_comp_wl_surface_role_set(ec, e_comp_wl_subsurface_role_name, NULL, 0);
- sub = _e_comp_wl_subsurface_create();
+ sub = E_NEW(E_Subsurface, 1);
if (!sub)
{
ERR("Could not allocate space for E_Subsurface");
}
sub->base.resource = res;
+ sub->base.cached_buffer_ref.buffer = NULL;
+ sub->base.synchronized = EINA_TRUE;
/* set resource implementation */
wl_resource_set_implementation(res, &_e_subsurface_interface, sub,
if (offscreen_parent)
ELOGF("COMP", " |offscreen_parent:%p", ec, offscreen_parent);
- /* Delete 'below_obj' if it was created before 'E_Client' becomes subsurface.
- * It's not for subsurface. */
- E_FREE_FUNC(ec->comp_data->sub.below_obj, evas_object_del);
-
e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_CREATE, ec);
return EINA_TRUE;
}
+EINTERN Eina_Bool
+e_comp_wl_subsurface_add(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, struct wl_resource *parent_surface)
+{
+ E_Subsurface *sub;
+ E_Client *ec, *epc = NULL;
+ E_Client *offscreen_parent = NULL;
+ struct wl_resource *subsurf_res;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(client, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(resource, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
+
+ ec = wl_resource_get_user_data(surface);
+
+ if (parent_surface)
+ epc = wl_resource_get_user_data(parent_surface);
+
+ if ((!epc) ||
+ (e_object_is_del(E_OBJECT(epc))))
+ {
+ ELOGF("SUBSURFACE", "Create with invalid parent(%p)", ec, epc);
+ subsurf_res = wl_resource_create(client, &wl_subsurface_interface,
+ 1, id);
+ if (!subsurf_res)
+ {
+ wl_resource_post_no_memory(resource);
+ return EINA_FALSE;
+ }
+
+ _e_comp_wl_subsurface_invalid_parent_handle(ec, subsurf_res);
+ return EINA_FALSE;
+ }
+
+ if (ec == epc)
+ {
+ wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+ "%d: wl_surface@%d cannot be its own parent",
+ id, wl_resource_get_id(surface));
+ return EINA_FALSE;
+ }
+
+ if (e_comp_wl_subsurface_check(ec))
+ {
+ wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+ "%d: wl_surface@%d is already a sub-surface",
+ id, wl_resource_get_id(surface));
+ return EINA_FALSE;
+ }
+
+ // reparent remote surface provider's subsurfaces
+ if ((epc->comp_data) &&
+ (epc->comp_data->remote_surface.onscreen_parent))
+ {
+ offscreen_parent = epc;
+ epc = epc->comp_data->remote_surface.onscreen_parent;
+ }
+
+ if (_e_comp_wl_subsurface_circular_reference_check(ec, epc))
+ {
+ ERR("Subsurface parent relationship is a cycle : "
+ "[child win : %zx, %s], [parent win : %zx, %s]",
+ e_client_util_win_get(ec), e_client_util_name_get(ec),
+ e_client_util_win_get(epc), e_client_util_name_get(epc));
+ wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+ "%d: wl_surface@%d is an ancestor of parent",
+ id, wl_resource_get_id(surface));
+ return EINA_FALSE;
+ }
+
+ if (!e_comp_wl_surface_role_set(ec, e_comp_wl_subsurface_role_name,
+ resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE))
+ {
+ return EINA_FALSE;
+ }
+
+ subsurf_res = wl_resource_create(client, &wl_subsurface_interface, 1, id);
+ if (!subsurf_res)
+ {
+ wl_resource_post_no_memory(resource);
+ return EINA_FALSE;
+ }
+
+ sub = _e_comp_wl_subsurface_create(subsurf_res, ec, epc, offscreen_parent);
+ if (!sub)
+ {
+ wl_resource_destroy(subsurf_res);
+ wl_resource_post_no_memory(resource);
+ return EINA_FALSE;
+ }
+
+ wl_resource_set_implementation(subsurf_res, &_e_subsurface_interface, sub,
+ _e_comp_wl_subsurface_cb_resource_destroy);
+
+ ELOGF("SUBSURFACE", "Create with parent(%p)", ec, epc);
+
+ return EINA_TRUE;
+}
+
EINTERN void
e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized)
{
}
static E_Subsurface *
-_e_comp_wl_subsurface_create(void)
+_e_comp_wl_subsurface_create(struct wl_resource *resource, E_Client *ec, E_Client *epc, E_Client *offscreen_parent)
{
E_Subsurface *sub;
if (!sub)
return NULL;
+ sub->base.resource = resource;
sub->base.cached_buffer_ref.buffer = NULL;
sub->base.synchronized = EINA_TRUE;
+ sub->base.remote_surface.offscreen_parent = offscreen_parent;
+ if (offscreen_parent)
+ ELOGF("SUBSURFACE", " |offscreen_parent:%p", ec, offscreen_parent);
+
+ _e_comp_wl_subsurface_ec_link(sub, ec);
+ _e_comp_wl_subsurface_parent_link(sub, epc);
+
+ e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_CREATE, ec);
return sub;
}
ec->new_client = ec->netwm.ping = EINA_TRUE;
e_comp->new_clients++;
e_client_unignore(ec);
+
+ /* Delete 'below_obj' if it was created before 'E_Client' becomes subsurface.
+ * It's not for subsurface. */
+ E_FREE_FUNC(ec->comp_data->sub.below_obj, evas_object_del);
}
static void
{
E_Client *ec, *epc;
E_Comp_Wl_Client_Data *cdata;
+ struct wl_resource *parent_surface = NULL;
+ Eina_Bool res;
ELOGF("TZPOL",
"SUBSURF |wl_surface@%d|parent_id:%d",
NULL, wl_resource_get_id(surface), parent_id);
ec = wl_resource_get_user_data(surface);
- if (!ec)
- {
- wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
- "tizen_policy failed: wrong wl_surface@%d resource",
- wl_resource_get_id(surface));
- return;
- }
-
- if (e_object_is_del(E_OBJECT(ec))) return;
-
- /* check if this surface is already a sub-surface */
- if (e_comp_wl_subsurface_check(ec))
- {
- wl_resource_post_error(resource,
- WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
- "wl_surface@%d is already a sub-surface",
- wl_resource_get_id(surface));
- return;
- }
-
epc = e_pixmap_find_client_by_res_id(parent_id);
/* This check code is for detecting an error case which tries to create
* sub-surface relationship with invalid parent. */
if ((epc) &&
(!e_object_is_del(E_OBJECT(epc))) &&
- (!epc->comp_data))
- {
- /* Another error case is handled by e_comp_wl_subsurface_create()
- * at the time this code is written. */
+ ((!epc->comp_data) || (!epc->comp_data->wl_surface)))
+ {
ELOGF("TZPOL", "Parent(%p internal? %s) doesn't have comp_data. "
"Possibly it's not the surface created by client. "
"Cannot be the parent of sub-surface.",
return;
}
+ if ((epc) && (epc->comp_data))
+ parent_surface = epc->comp_data->wl_surface;
+
/* try to create a new subsurface */
- if (!e_comp_wl_subsurface_create(ec, epc, id, surface))
+ res = e_comp_wl_subsurface_add(client, resource, id, surface,
+ parent_surface);
+ if (!res)
{
- ERR("Failed to create subsurface for surface@%d", wl_resource_get_id(surface));
+ ERR("Failed to add subsurface for surface@%d", wl_resource_get_id(surface));
return;
}