From 49258829209347a7aef65f2e38d3eea29a9d45e0 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 29 May 2019 16:08:48 +0200 Subject: [PATCH] Use parent get_root_coords in subsurfaces Subsurfaces need access to the parent get_root_coords impl for positioning in popups. To do this, we store a reference to the parent view_child where applicable. Fixes #4191. --- include/sway/tree/view.h | 3 ++ sway/tree/view.c | 60 ++++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index bdd8960cd..4ce487fca 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -192,8 +192,11 @@ struct sway_view_child_impl { */ struct sway_view_child { const struct sway_view_child_impl *impl; + struct wl_list link; struct sway_view *view; + struct sway_view_child *parent; + struct wl_list children; // sway_view_child::link struct wlr_surface *surface; bool mapped; diff --git a/sway/tree/view.c b/sway/tree/view.c index e8f5a2999..4fd3a65ae 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -728,15 +728,23 @@ static void subsurface_get_root_coords(struct sway_view_child *child, *root_sx = -child->view->geometry.x; *root_sy = -child->view->geometry.y; - while (surface && wlr_surface_is_subsurface(surface)) { - struct wlr_subsurface *subsurface = - wlr_subsurface_from_wlr_surface(surface); - if (subsurface == NULL) { - break; + if (child->parent && child->parent->impl && + child->parent->impl->get_root_coords) { + int sx, sy; + child->parent->impl->get_root_coords(child->parent, &sx, &sy); + *root_sx += sx; + *root_sy += sy; + } else { + while (surface && wlr_surface_is_subsurface(surface)) { + struct wlr_subsurface *subsurface = + wlr_subsurface_from_wlr_surface(surface); + if (subsurface == NULL) { + break; + } + *root_sx += subsurface->current.x; + *root_sy += subsurface->current.y; + surface = subsurface->parent; } - *root_sx += subsurface->current.x; - *root_sy += subsurface->current.y; - surface = subsurface->parent; } } @@ -780,6 +788,28 @@ static void view_subsurface_create(struct sway_view *view, subsurface->destroy.notify = subsurface_handle_destroy; subsurface->child.mapped = true; + + view_child_damage(&subsurface->child, true); +} + +static void view_child_subsurface_create(struct sway_view_child *child, + struct wlr_subsurface *wlr_subsurface) { + struct sway_subsurface *subsurface = + calloc(1, sizeof(struct sway_subsurface)); + if (subsurface == NULL) { + sway_log(SWAY_ERROR, "Allocation failed"); + return; + } + subsurface->child.parent = child; + wl_list_insert(&child->children, &subsurface->child.link); + view_child_init(&subsurface->child, &subsurface_impl, child->view, + wlr_subsurface->surface); + + wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); + subsurface->destroy.notify = subsurface_handle_destroy; + + subsurface->child.mapped = true; + view_child_damage(&subsurface->child, true); } @@ -806,7 +836,7 @@ static void view_child_handle_surface_new_subsurface( struct sway_view_child *child = wl_container_of(listener, child, surface_new_subsurface); struct wlr_subsurface *subsurface = data; - view_subsurface_create(child->view, subsurface); + view_child_subsurface_create(child, subsurface); } static void view_child_handle_surface_destroy(struct wl_listener *listener, @@ -854,6 +884,7 @@ void view_child_init(struct sway_view_child *child, child->impl = impl; child->view = view; child->surface = surface; + wl_list_init(&child->children); wl_signal_add(&surface->events.commit, &child->surface_commit); child->surface_commit.notify = view_child_handle_surface_commit; @@ -882,6 +913,17 @@ void view_child_destroy(struct sway_view_child *child) { view_child_damage(child, true); } + if (child->parent != NULL) { + wl_list_remove(&child->link); + child->parent = NULL; + } + + struct sway_view_child *subchild, *tmpchild; + wl_list_for_each_safe(subchild, tmpchild, &child->children, link) { + wl_list_remove(&subchild->link); + subchild->parent = NULL; + } + wl_list_remove(&child->surface_commit.link); wl_list_remove(&child->surface_destroy.link); wl_list_remove(&child->view_unmap.link);