[mutter/wayland] wayland: Make wl_subsurface.place_(above|below) properly synchronized
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wayland] wayland: Make wl_subsurface.place_(above|below) properly synchronized
- Date: Thu, 30 Jan 2014 20:14:03 +0000 (UTC)
commit 9348c9bd4bfbd1081c4d1324068a964041c07e43
Author: Jonas Ådahl <jadahl gmail com>
Date: Sun Jan 12 23:24:00 2014 +0100
wayland: Make wl_subsurface.place_(above|below) properly synchronized
The placement set by either wl_subsurface.place_above or
wl_subsurface.place_below should be applied when the parent surface
invokes wl_surface.commit.
Signed-off-by: Jonas Ådahl <jadahl gmail com>
https://bugzilla.gnome.org/show_bug.cgi?id=705502
src/wayland/meta-wayland-surface.c | 97 +++++++++++++++++++++++++++++++-----
src/wayland/meta-wayland-surface.h | 1 +
2 files changed, 86 insertions(+), 12 deletions(-)
---
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index bd1feea..f3455bc 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -58,6 +58,19 @@
#include "meta-idle-monitor-private.h"
#include "monitor-private.h"
+typedef enum
+{
+ META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE,
+ META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW
+} MetaWaylandSubsurfacePlacement;
+
+typedef struct
+{
+ MetaWaylandSubsurfacePlacement placement;
+ MetaWaylandSurface *sibling;
+ struct wl_listener sibling_destroy_listener;
+} MetaWaylandSubsurfacePlacementOp;
+
static void
surface_process_damage (MetaWaylandSurface *surface,
cairo_region_t *region)
@@ -1012,6 +1025,44 @@ wl_subsurface_parent_surface_committed (gpointer data, gpointer user_data)
surface->sub.pending_y);
surface->sub.pending_pos = FALSE;
}
+
+ if (surface->sub.pending_placement_ops)
+ {
+ GSList *it;
+ for (it = surface->sub.pending_placement_ops; it; it = it->next)
+ {
+ MetaWaylandSubsurfacePlacementOp *op = it->data;
+ ClutterActor *surface_actor;
+ ClutterActor *parent_actor;
+ ClutterActor *sibling_actor;
+
+ if (!op->sibling)
+ {
+ g_slice_free (MetaWaylandSubsurfacePlacementOp, op);
+ continue;
+ }
+
+ surface_actor = CLUTTER_ACTOR (surface->surface_actor);
+ parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->sub.parent));
+ sibling_actor = CLUTTER_ACTOR (op->sibling->surface_actor);
+
+ switch (op->placement)
+ {
+ case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE:
+ clutter_actor_set_child_above_sibling (parent_actor, surface_actor, sibling_actor);
+ break;
+ case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW:
+ clutter_actor_set_child_below_sibling (parent_actor, surface_actor, sibling_actor);
+ break;
+ }
+
+ wl_list_remove (&op->sibling_destroy_listener.link);
+ g_slice_free (MetaWaylandSubsurfacePlacementOp, op);
+ }
+
+ g_slist_free (surface->sub.pending_placement_ops);
+ surface->sub.pending_placement_ops = NULL;
+ }
}
static void
@@ -1063,11 +1114,38 @@ is_valid_sibling (MetaWaylandSurface *surface, MetaWaylandSurface *sibling)
}
static void
+subsurface_handle_pending_sibling_destroyed (struct wl_listener *listener, void *data)
+{
+ MetaWaylandSubsurfacePlacementOp *op =
+ wl_container_of (listener, op, sibling_destroy_listener);
+
+ op->sibling = NULL;
+}
+
+static void
+queue_subsurface_placement (MetaWaylandSurface *surface,
+ MetaWaylandSurface *sibling,
+ MetaWaylandSubsurfacePlacement placement)
+{
+ MetaWaylandSubsurfacePlacementOp *op =
+ g_slice_new (MetaWaylandSubsurfacePlacementOp);
+
+ op->placement = placement;
+ op->sibling = sibling;
+ op->sibling_destroy_listener.notify =
+ subsurface_handle_pending_sibling_destroyed;
+ wl_resource_add_destroy_listener (sibling->resource,
+ &op->sibling_destroy_listener);
+
+ surface->sub.pending_placement_ops =
+ g_slist_append (surface->sub.pending_placement_ops, op);
+}
+
+static void
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);
@@ -1081,11 +1159,9 @@ wl_subsurface_place_above (struct wl_client *client,
return;
}
- 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));
+ queue_subsurface_placement (surface,
+ sibling,
+ META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE);
}
static void
@@ -1093,7 +1169,6 @@ 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);
@@ -1107,11 +1182,9 @@ wl_subsurface_place_below (struct wl_client *client,
return;
}
- 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));
+ queue_subsurface_placement (surface,
+ sibling,
+ META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW);
}
static void
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 32fa0fd..c7b617d 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -94,6 +94,7 @@ struct _MetaWaylandSurface
int32_t pending_x;
int32_t pending_y;
gboolean pending_pos;
+ GSList *pending_placement_ops;
} sub;
/* All the pending state, that wl_surface.commit will apply. */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]