[PATCH weston 4/4] compositor: popup inherits surface transformation

Pekka Paalanen ppaalanen at gmail.com
Tue Dec 18 03:58:50 PST 2012


Implement the final bits needed to have inheritable surface
transformations:
- add 'parent' to weston_matrix_pointer, so that
  weston_surface_update_transform() knows to update the parent surface
  first
- add 'dirty_signal' to weston_surface, so that when the parent's
  transformation gets dirtied, also the inheriting transformation can be
  marked dirty
These two ensure, that inheriting transformations get updated when the
parent is updated. Update_transform() needs to look at only the
immediate parent surfaces, and not the whole chain every time. The same
applies to making surface geometry dirty: only the immediate children
will need to be signalled.

Implement the popup surface transformation by inheritance instead of
copy. Now, if we moved the popup's parent surface while the popup
is open, the popup surface will stick to the parent properly.

Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
---
 src/compositor.c |    8 ++++++++
 src/compositor.h |   12 ++++++++++++
 src/shell.c      |   38 +++++++++++++++++++++++---------------
 3 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 1533cbc..0a3c4c8 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -301,6 +301,7 @@ weston_surface_create(struct weston_compositor *compositor)
 
 	pixman_region32_init(&surface->transform.boundingbox);
 	surface->transform.dirty = 1;
+	wl_signal_init(&surface->transform.dirty_signal);
 
 	surface->pending.buffer_destroy_listener.notify =
 		surface_handle_pending_buffer_destroy;
@@ -552,6 +553,8 @@ weston_surface_update_transform_enable(struct weston_surface *surface)
 
 	weston_matrix_init(matrix);
 	wl_list_for_each(ptr, &surface->geometry.transformation_list, link) {
+		if (ptr->parent)
+			weston_surface_update_transform(ptr->parent);
 		weston_matrix_multiply(matrix, ptr->matrix);
 	}
 
@@ -602,7 +605,12 @@ weston_surface_update_transform(struct weston_surface *surface)
 WL_EXPORT void
 weston_surface_geometry_dirty(struct weston_surface *surface)
 {
+	int emit = !surface->transform.dirty;
+
 	surface->transform.dirty = 1;
+
+	if (emit)
+		wl_signal_emit(&surface->transform.dirty_signal, surface);
 }
 
 WL_EXPORT void
diff --git a/src/compositor.h b/src/compositor.h
index b681481..68b4400 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -342,6 +342,16 @@ struct weston_compositor {
 
 struct weston_matrix_pointer {
 	struct weston_matrix *matrix;
+
+	/* If non-NULL, assume that the matrix is the complete transformation
+	 * of the parent surface. IOW, update_transform() on the parent first,
+	 * assuming it will make *matrix up-to-date.
+	 */
+	struct weston_surface *parent;
+	/* Setting up a parent destroy listener is left for the user,
+	 * because it usually has to handle parent's destruction anyway.
+	 */
+
 	struct wl_list link;
 };
 
@@ -416,6 +426,7 @@ struct weston_surface {
 	 */
 	struct {
 		int dirty;
+		struct wl_signal dirty_signal;
 
 		pixman_region32_t boundingbox;
 		pixman_region32_t opaque;
@@ -854,6 +865,7 @@ static inline void
 weston_transform_init(struct weston_transform *tform)
 {
 	tform->ptr.matrix = &tform->matrix;
+	tform->ptr.parent = NULL;
 }
 
 #endif
diff --git a/src/shell.c b/src/shell.c
index e25140d..edd009d 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -157,6 +157,7 @@ struct shell_surface {
 	struct weston_surface *surface;
 	struct wl_listener surface_destroy_listener;
 	struct weston_surface *parent;
+	/* XXX: missing parent_destroy_listener */
 	struct desktop_shell *shell;
 
 	enum shell_surface_type type, next_type;
@@ -174,7 +175,8 @@ struct shell_surface {
 	struct {
 		struct wl_pointer_grab grab;
 		int32_t x, y;
-		struct weston_transform parent_transform;
+		struct weston_matrix_pointer parent_transform;
+		struct wl_listener parent_dirty_listener;
 		int32_t initial_up;
 		struct wl_seat *seat;
 		uint32_t serial;
@@ -1859,6 +1861,16 @@ popup_grab_end(struct wl_pointer *pointer)
 }
 
 static void
+popup_notify_parent_geometry_dirty(struct wl_listener *listener, void *data)
+{
+	struct shell_surface *shsurf =
+		container_of(listener, struct shell_surface,
+			     popup.parent_dirty_listener);
+
+	weston_surface_geometry_dirty(shsurf->surface);
+}
+
+static void
 shell_map_popup(struct shell_surface *shsurf)
 {
 	struct wl_seat *seat = shsurf->popup.seat;
@@ -1868,20 +1880,14 @@ shell_map_popup(struct shell_surface *shsurf)
 	es->output = parent->output;
 	shsurf->popup.grab.interface = &popup_grab_interface;
 
-	weston_surface_update_transform(parent);
-	if (parent->transform.enabled) {
-		shsurf->popup.parent_transform.matrix =
-			parent->transform.matrix;
-	} else {
-		/* construct x, y translation matrix */
-		weston_matrix_init(&shsurf->popup.parent_transform.matrix);
-		shsurf->popup.parent_transform.matrix.d[12] =
-			parent->geometry.x;
-		shsurf->popup.parent_transform.matrix.d[13] =
-			parent->geometry.y;
-	}
+	shsurf->popup.parent_transform.matrix = &parent->transform.matrix;
+	shsurf->popup.parent_transform.parent = parent;
+	shsurf->popup.parent_dirty_listener.notify =
+		popup_notify_parent_geometry_dirty;
+	wl_signal_add(&parent->transform.dirty_signal,
+		      &shsurf->popup.parent_dirty_listener);
 	wl_list_insert(es->geometry.transformation_list.prev,
-		       &shsurf->popup.parent_transform.ptr.link);
+		       &shsurf->popup.parent_transform.link);
 
 	shsurf->popup.initial_up = 0;
 	weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
@@ -1930,6 +1936,9 @@ static const struct wl_shell_surface_interface shell_surface_implementation = {
 static void
 destroy_shell_surface(struct shell_surface *shsurf)
 {
+	if (shsurf->popup.parent_transform.parent)
+		wl_list_remove(&shsurf->popup.parent_dirty_listener.link);
+
 	if (shsurf->popup.grab.pointer)
 		wl_pointer_end_grab(shsurf->popup.grab.pointer);
 
@@ -2033,7 +2042,6 @@ create_shell_surface(void *shell, struct weston_surface *surface,
 	weston_transform_init(&shsurf->rotation.transform);
 	weston_matrix_init(&shsurf->rotation.rotation);
 
-	weston_transform_init(&shsurf->popup.parent_transform);
 	weston_transform_init(&shsurf->fullscreen.transform);
 
 	wl_list_init(&shsurf->workspace_transform.ptr.link);
-- 
1.7.8.6



More information about the wayland-devel mailing list