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.
This commit is contained in:
parent
c3532bc8a1
commit
4925882920
|
@ -192,8 +192,11 @@ struct sway_view_child_impl {
|
||||||
*/
|
*/
|
||||||
struct sway_view_child {
|
struct sway_view_child {
|
||||||
const struct sway_view_child_impl *impl;
|
const struct sway_view_child_impl *impl;
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
struct sway_view *view;
|
struct sway_view *view;
|
||||||
|
struct sway_view_child *parent;
|
||||||
|
struct wl_list children; // sway_view_child::link
|
||||||
struct wlr_surface *surface;
|
struct wlr_surface *surface;
|
||||||
bool mapped;
|
bool mapped;
|
||||||
|
|
||||||
|
|
|
@ -728,15 +728,23 @@ static void subsurface_get_root_coords(struct sway_view_child *child,
|
||||||
*root_sx = -child->view->geometry.x;
|
*root_sx = -child->view->geometry.x;
|
||||||
*root_sy = -child->view->geometry.y;
|
*root_sy = -child->view->geometry.y;
|
||||||
|
|
||||||
while (surface && wlr_surface_is_subsurface(surface)) {
|
if (child->parent && child->parent->impl &&
|
||||||
struct wlr_subsurface *subsurface =
|
child->parent->impl->get_root_coords) {
|
||||||
wlr_subsurface_from_wlr_surface(surface);
|
int sx, sy;
|
||||||
if (subsurface == NULL) {
|
child->parent->impl->get_root_coords(child->parent, &sx, &sy);
|
||||||
break;
|
*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->destroy.notify = subsurface_handle_destroy;
|
||||||
|
|
||||||
subsurface->child.mapped = true;
|
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);
|
view_child_damage(&subsurface->child, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,7 +836,7 @@ static void view_child_handle_surface_new_subsurface(
|
||||||
struct sway_view_child *child =
|
struct sway_view_child *child =
|
||||||
wl_container_of(listener, child, surface_new_subsurface);
|
wl_container_of(listener, child, surface_new_subsurface);
|
||||||
struct wlr_subsurface *subsurface = data;
|
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,
|
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->impl = impl;
|
||||||
child->view = view;
|
child->view = view;
|
||||||
child->surface = surface;
|
child->surface = surface;
|
||||||
|
wl_list_init(&child->children);
|
||||||
|
|
||||||
wl_signal_add(&surface->events.commit, &child->surface_commit);
|
wl_signal_add(&surface->events.commit, &child->surface_commit);
|
||||||
child->surface_commit.notify = view_child_handle_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);
|
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_commit.link);
|
||||||
wl_list_remove(&child->surface_destroy.link);
|
wl_list_remove(&child->surface_destroy.link);
|
||||||
wl_list_remove(&child->view_unmap.link);
|
wl_list_remove(&child->view_unmap.link);
|
||||||
|
|
Loading…
Reference in a new issue