aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenny Levinsen <kl@kl.wtf>2019-05-29 16:08:48 +0200
committerBrian Ashworth <bosrsf04@gmail.com>2019-05-30 14:25:07 -0400
commit49258829209347a7aef65f2e38d3eea29a9d45e0 (patch)
tree6cc8859f3137b05d6c9b94635b2e11b78f39ff65
parentc3532bc8a18e28474350e5b471f00cf33ba5a290 (diff)
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.
-rw-r--r--include/sway/tree/view.h3
-rw-r--r--sway/tree/view.c60
2 files changed, 54 insertions, 9 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index bdd8960c..4ce487fc 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 e8f5a299..4fd3a65a 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);