Implements surface transform inheritance. A 'parent' pointer is added to weston_surface::geometry, and is automatically used by weston_surface_update_transform(). When updating the transform, the parent transform is updated as needed, too.
shell_map_popup() is converted to use the new weston_surface_set_transform_parent() function. 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 <ppaala...@gmail.com> --- This is a new suggestion for the transform inheritance. Personally I like this a lot better than the weston_matrix_pointer hassle, but I haven't yet ported sub-surfaces on top of this. Seems to work fine with menus. --- src/compositor.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/compositor.h | 18 ++++++++++++++++-- src/shell.c | 28 +--------------------------- 3 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/compositor.c b/src/compositor.c index 8037195..3bc6b11 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -625,6 +625,7 @@ weston_surface_update_transform_disable(struct weston_surface *surface) static int weston_surface_update_transform_enable(struct weston_surface *surface) { + struct weston_surface *parent = surface->geometry.parent; struct weston_matrix *matrix = &surface->transform.matrix; struct weston_matrix *inverse = &surface->transform.inverse; struct weston_transform *tform; @@ -640,6 +641,9 @@ weston_surface_update_transform_enable(struct weston_surface *surface) wl_list_for_each(tform, &surface->geometry.transformation_list, link) weston_matrix_multiply(matrix, &tform->matrix); + if (parent) + weston_matrix_multiply(matrix, &parent->transform.matrix); + if (weston_matrix_invert(inverse, matrix) < 0) { /* Oops, bad total transformation, not invertible */ weston_log("error: weston_surface %p" @@ -654,11 +658,17 @@ weston_surface_update_transform_enable(struct weston_surface *surface) return 0; } -WL_EXPORT void +WL_EXPORT int weston_surface_update_transform(struct weston_surface *surface) { - if (!surface->geometry.dirty) - return; + struct weston_surface *parent = surface->geometry.parent; + int was_dirty = 0; + + if (parent) + was_dirty = weston_surface_update_transform(parent); + + if (!was_dirty && !surface->geometry.dirty) + return 0; surface->geometry.dirty = 0; @@ -672,7 +682,8 @@ weston_surface_update_transform(struct weston_surface *surface) if (surface->geometry.transformation_list.next == &surface->transform.position.link && surface->geometry.transformation_list.prev == - &surface->transform.position.link) { + &surface->transform.position.link && + !parent) { weston_surface_update_transform_disable(surface); } else { if (weston_surface_update_transform_enable(surface) < 0) @@ -682,6 +693,8 @@ weston_surface_update_transform(struct weston_surface *surface) weston_surface_damage_below(surface); weston_surface_assign_output(surface); + + return 1; } WL_EXPORT void @@ -791,6 +804,35 @@ weston_surface_set_position(struct weston_surface *surface, surface->geometry.dirty = 1; } +static void +transform_parent_handle_parent_destroy(struct wl_listener *listener, + void *data) +{ + struct weston_surface *surface = + container_of(listener, struct weston_surface, + geometry.parent_destroy_listener); + + weston_surface_set_transform_parent(surface, NULL); +} + +WL_EXPORT void +weston_surface_set_transform_parent(struct weston_surface *surface, + struct weston_surface *parent) +{ + if (surface->geometry.parent) + wl_list_remove(&surface->geometry.parent_destroy_listener.link); + + surface->geometry.parent = parent; + + surface->geometry.parent_destroy_listener.notify = + transform_parent_handle_parent_destroy; + if (parent) + wl_signal_add(&parent->surface.resource.destroy_signal, + &surface->geometry.parent_destroy_listener); + + surface->geometry.dirty = 1; +} + WL_EXPORT int weston_surface_is_mapped(struct weston_surface *surface) { @@ -967,6 +1009,8 @@ destroy_surface(struct wl_resource *resource) wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link) wl_resource_destroy(&cb->resource); + weston_surface_set_transform_parent(surface, NULL); + free(surface); } diff --git a/src/compositor.h b/src/compositor.h index 00d3b22..4167ef0 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -386,6 +386,11 @@ struct weston_region { * If you want to apply a transformation in local coordinates, add your * weston_transform to the head of the list. If you want to apply a * transformation in global coordinates, add it to the tail of the list. + * + * If surface->geometry.parent is set, the total transformation of this + * surface will be the parent's total transformation and this transformation + * combined: + * Mparent * Mn * ... * M2 * M1 */ struct weston_surface { @@ -404,12 +409,17 @@ struct weston_surface { /* Surface geometry state, mutable. * If you change anything, set dirty = 1. - * That includes the transformations referenced from the list. + * That includes the transformations referenced from the list, + * and the parent pointer, but excludes the parent's state. */ struct { float x, y; /* surface translation on display */ int32_t width, height; + /* If not NULL, inherit transformation, and add to it. */ + struct weston_surface *parent; + struct wl_listener parent_destroy_listener; + /* struct weston_transform */ struct wl_list transformation_list; @@ -494,7 +504,7 @@ enum weston_key_state_update { void weston_version(int *major, int *minor, int *micro); -void +int weston_surface_update_transform(struct weston_surface *surface); void @@ -679,6 +689,10 @@ void weston_surface_set_position(struct weston_surface *surface, float x, float y); +void +weston_surface_set_transform_parent(struct weston_surface *surface, + struct weston_surface *parent); + int weston_surface_is_mapped(struct weston_surface *surface); diff --git a/src/shell.c b/src/shell.c index 3da5321..299c60e 100644 --- a/src/shell.c +++ b/src/shell.c @@ -190,7 +190,6 @@ struct shell_surface { struct { struct wl_pointer_grab grab; int32_t x, y; - struct weston_transform parent_transform; int32_t initial_up; struct wl_seat *seat; uint32_t serial; @@ -1909,35 +1908,11 @@ shell_map_popup(struct shell_surface *shsurf) struct weston_surface *es = shsurf->surface; struct weston_surface *parent = shsurf->parent; - /* Remove the old transform. We don't want to add it twice - * otherwise Weston will go into an infinite loop when going - * through the transforms. */ - if (!wl_list_empty(&shsurf->popup.parent_transform.link)) { - wl_list_remove(&shsurf->popup.parent_transform.link); - wl_list_init(&shsurf->popup.parent_transform.link); - } - 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.type = - WESTON_MATRIX_TRANSFORM_TRANSLATE; - shsurf->popup.parent_transform.matrix.d[12] = - parent->geometry.x; - shsurf->popup.parent_transform.matrix.d[13] = - parent->geometry.y; - } - wl_list_insert(es->geometry.transformation_list.prev, - &shsurf->popup.parent_transform.link); - shsurf->popup.initial_up = 0; + weston_surface_set_transform_parent(es, parent); weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y); weston_surface_update_transform(es); @@ -2087,7 +2062,6 @@ create_shell_surface(void *shell, struct weston_surface *surface, weston_matrix_init(&shsurf->rotation.rotation); wl_list_init(&shsurf->workspace_transform.link); - wl_list_init(&shsurf->popup.parent_transform.link); shsurf->type = SHELL_SURFACE_NONE; shsurf->next_type = SHELL_SURFACE_NONE; -- 1.7.12.4 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel