diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index 37b87b03a..9e49e4e77 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -24,6 +24,8 @@ struct _MetaSurfaceActorPrivate { MetaShapedTexture *texture; MetaWaylandBuffer *buffer; + + GSList *ops; }; static void cullable_iface_init (MetaCullableInterface *iface); @@ -31,9 +33,23 @@ static void cullable_iface_init (MetaCullableInterface *iface); G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR, G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); +static void meta_surface_actor_free_ops (MetaSurfaceActor *self); + +static void +meta_surface_actor_dispose (GObject *object) +{ + MetaSurfaceActor *self = META_SURFACE_ACTOR (object); + + meta_surface_actor_free_ops (self); +} + static void meta_surface_actor_class_init (MetaSurfaceActorClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = meta_surface_actor_dispose; + g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate)); } @@ -181,3 +197,127 @@ meta_surface_actor_new (void) { return g_object_new (META_TYPE_SURFACE_ACTOR, NULL); } + +typedef enum { + OP_SET_POSITION, + OP_PLACE_ABOVE, + OP_PLACE_BELOW, +} MetaSurfaceActorOpType; + +typedef struct { + MetaSurfaceActorOpType type; +} MetaSurfaceActorOp; + +typedef struct { + MetaSurfaceActorOpType type; + ClutterActor *subsurface; + int32_t x; + int32_t y; +} MetaSurfaceActorOp_SetPosition; + +typedef struct { + MetaSurfaceActorOpType type; + ClutterActor *subsurface; + ClutterActor *sibling; +} MetaSurfaceActorOp_Stack; + +void +meta_surface_actor_subsurface_set_position (MetaSurfaceActor *self, + MetaSurfaceActor *subsurface, + int32_t x, + int32_t y) +{ + MetaSurfaceActorPrivate *priv = self->priv; + MetaSurfaceActorOp_SetPosition *op = g_slice_new0 (MetaSurfaceActorOp_SetPosition); + + op->type = OP_SET_POSITION; + op->subsurface = CLUTTER_ACTOR (subsurface); + op->x = x; + op->y = y; + + priv->ops = g_slist_append (priv->ops, op); +} + +static void +meta_surface_actor_stack_op (MetaSurfaceActor *self, + MetaSurfaceActorOpType type, + MetaSurfaceActor *subsurface, + MetaSurfaceActor *sibling) +{ + MetaSurfaceActorPrivate *priv = self->priv; + MetaSurfaceActorOp_Stack *op = g_slice_new0 (MetaSurfaceActorOp_Stack); + + op->type = type; + op->subsurface = CLUTTER_ACTOR (subsurface); + op->sibling = CLUTTER_ACTOR (sibling); + + priv->ops = g_slist_append (priv->ops, op); +} + +void +meta_surface_actor_subsurface_place_above (MetaSurfaceActor *self, + MetaSurfaceActor *subsurface, + MetaSurfaceActor *sibling) +{ + meta_surface_actor_stack_op (self, OP_PLACE_ABOVE, subsurface, sibling); +} + +void +meta_surface_actor_subsurface_place_below (MetaSurfaceActor *self, + MetaSurfaceActor *subsurface, + MetaSurfaceActor *sibling) +{ + meta_surface_actor_stack_op (self, OP_PLACE_BELOW, subsurface, sibling); +} + +static void +meta_surface_actor_do_op (MetaSurfaceActor *self, + MetaSurfaceActorOp *op) +{ + MetaSurfaceActorOp_SetPosition *op_pos = (MetaSurfaceActorOp_SetPosition *) op; + MetaSurfaceActorOp_Stack *op_stack = (MetaSurfaceActorOp_Stack *) op; + + switch (op->type) + { + case OP_SET_POSITION: + clutter_actor_set_position (op_pos->subsurface, op_pos->x, op_pos->y); + break; + case OP_PLACE_ABOVE: + clutter_actor_set_child_above_sibling (CLUTTER_ACTOR (self), op_stack->subsurface, op_stack->sibling); + break; + case OP_PLACE_BELOW: + clutter_actor_set_child_below_sibling (CLUTTER_ACTOR (self), op_stack->subsurface, op_stack->sibling); + break; + } +} + +static void +meta_surface_actor_op_free (MetaSurfaceActorOp *op) +{ + g_slice_free (MetaSurfaceActorOp, op); +} + +static void +meta_surface_actor_free_ops (MetaSurfaceActor *self) +{ + MetaSurfaceActorPrivate *priv = self->priv; + + g_slist_free_full (priv->ops, (GDestroyNotify) meta_surface_actor_op_free); + priv->ops = NULL; +} + +static void +meta_surface_actor_do_ops (MetaSurfaceActor *self) +{ + MetaSurfaceActorPrivate *priv = self->priv; + GSList *l; + + for (l = priv->ops; l; l = l->next) + meta_surface_actor_do_op (self, ((MetaSurfaceActorOp *) l->data)); +} + +void +meta_surface_actor_commit (MetaSurfaceActor *self) +{ + meta_surface_actor_do_ops (self); +} diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h index 484877b73..5dd1d09b4 100644 --- a/src/compositor/meta-surface-actor.h +++ b/src/compositor/meta-surface-actor.h @@ -62,6 +62,18 @@ void meta_surface_actor_set_input_region (MetaSurfaceActor *self, void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, cairo_region_t *region); +void meta_surface_actor_subsurface_set_position (MetaSurfaceActor *self, + MetaSurfaceActor *subsurface, + int32_t x, + int32_t y); +void meta_surface_actor_subsurface_place_above (MetaSurfaceActor *self, + MetaSurfaceActor *subsurface, + MetaSurfaceActor *sibling); +void meta_surface_actor_subsurface_place_below (MetaSurfaceActor *self, + MetaSurfaceActor *subsurface, + MetaSurfaceActor *sibling); +void meta_surface_actor_commit (MetaSurfaceActor *self); + G_END_DECLS #endif /* META_SURFACE_ACTOR_PRIVATE_H */ diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 1ca38e564..ad647bc0b 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -339,6 +339,8 @@ meta_wayland_surface_commit (struct wl_client *client, compositor = surface->compositor; + meta_surface_actor_commit (surface->surface_actor); + if (surface == compositor->seat->sprite) cursor_surface_commit (surface); else if (surface->window) @@ -1010,6 +1012,12 @@ wl_subsurface_destroy (struct wl_client *client, wl_resource_destroy (resource); } +static MetaSurfaceActor * +get_parent (MetaWaylandSurface *surface) +{ + return META_SURFACE_ACTOR (clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor))); +} + static void wl_subsurface_set_position (struct wl_client *client, struct wl_resource *resource, @@ -1019,7 +1027,7 @@ wl_subsurface_set_position (struct wl_client *client, MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface); - clutter_actor_set_position (CLUTTER_ACTOR (surface->surface_actor), x, y); + meta_surface_actor_subsurface_set_position (get_parent (surface), surface->surface_actor, x, y); } static void @@ -1027,16 +1035,11 @@ wl_subsurface_place_above (struct wl_client *client, struct wl_resource *resource, struct wl_resource *sibling_resource) { - ClutterActor *parent_actor; MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface); MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource); - parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor)); - - clutter_actor_set_child_above_sibling (parent_actor, - CLUTTER_ACTOR (surface->surface_actor), - CLUTTER_ACTOR (sibling->surface_actor)); + meta_surface_actor_subsurface_place_above (get_parent (surface), surface->surface_actor, sibling->surface_actor); } static void @@ -1044,16 +1047,11 @@ wl_subsurface_place_below (struct wl_client *client, struct wl_resource *resource, struct wl_resource *sibling_resource) { - ClutterActor *parent_actor; MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource); MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface); MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource); - parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor)); - - clutter_actor_set_child_below_sibling (parent_actor, - CLUTTER_ACTOR (surface->surface_actor), - CLUTTER_ACTOR (sibling->surface_actor)); + meta_surface_actor_subsurface_place_below (get_parent (surface), surface->surface_actor, sibling->surface_actor); } static void