[PATCH weston v2 4/4] compositor: popup inherits surface transformation
Pekka Paalanen
ppaalanen at gmail.com
Wed Jan 16 02:40:18 PST 2013
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 0defabd..c1372e4 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 deb8451..f30838b 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -343,6 +343,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;
};
@@ -417,6 +427,7 @@ struct weston_surface {
*/
struct {
int dirty;
+ struct wl_signal dirty_signal;
pixman_region32_t boundingbox;
pixman_region32_t opaque;
@@ -853,6 +864,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 e8cfff3..4cb0eb1 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -156,6 +156,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;
@@ -173,7 +174,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;
@@ -1860,6 +1862,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;
@@ -1869,20 +1881,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);
@@ -1931,6 +1937,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);
@@ -2034,7 +2043,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