mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-18 06:47:31 -04:00
Merge branch 'subsurface_visibility' into 'master'
wlr_scene: Introduce visibily to subsurface_tree See merge request wlroots/wlroots!4735
This commit is contained in:
commit
3e14d467de
6 changed files with 155 additions and 120 deletions
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
struct wlr_scene_drag_icon {
|
||||
struct wlr_scene_tree *tree;
|
||||
struct wlr_scene_tree *surface_tree;
|
||||
struct wlr_scene_subsurface_tree *surface_tree;
|
||||
struct wlr_drag_icon *drag_icon;
|
||||
|
||||
struct wl_listener tree_destroy;
|
||||
|
|
@ -17,7 +17,7 @@ static void drag_icon_handle_surface_commit(struct wl_listener *listener, void *
|
|||
struct wlr_scene_drag_icon *icon =
|
||||
wl_container_of(listener, icon, drag_icon_surface_commit);
|
||||
struct wlr_surface *surface = icon->drag_icon->surface;
|
||||
struct wlr_scene_node *node = &icon->surface_tree->node;
|
||||
struct wlr_scene_node *node = &icon->surface_tree->tree->node;
|
||||
wlr_scene_node_set_position(node,
|
||||
node->x + surface->current.dx, node->y + surface->current.dy);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,9 +142,9 @@ struct wlr_scene_layer_surface_v1 *wlr_scene_layer_surface_v1_create(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_scene_tree *surface_tree = wlr_scene_subsurface_tree_create(
|
||||
scene_layer_surface->surface_tree = wlr_scene_subsurface_tree_create(
|
||||
scene_layer_surface->tree, layer_surface->surface);
|
||||
if (surface_tree == NULL) {
|
||||
if (scene_layer_surface->surface_tree == NULL) {
|
||||
wlr_scene_node_destroy(&scene_layer_surface->tree->node);
|
||||
free(scene_layer_surface);
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -11,22 +11,25 @@
|
|||
*
|
||||
* `tree` contains `scene_surface` and one node per sub-surface.
|
||||
*/
|
||||
struct wlr_scene_subsurface_tree {
|
||||
struct wlr_scene_subsurface_tree_surface {
|
||||
struct wlr_scene_tree *tree;
|
||||
struct wlr_surface *surface;
|
||||
struct wlr_scene_surface *scene_surface;
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree;
|
||||
|
||||
struct wl_listener surface_destroy;
|
||||
struct wl_listener surface_commit;
|
||||
struct wl_listener surface_map;
|
||||
struct wl_listener surface_unmap;
|
||||
struct wl_listener surface_new_subsurface;
|
||||
struct wl_listener scene_outputs_update;
|
||||
struct wl_listener scene_destroy;
|
||||
|
||||
struct wlr_scene_subsurface_tree *parent; // NULL for the top-level surface
|
||||
|
||||
struct wlr_addon scene_addon;
|
||||
struct wlr_scene_subsurface_tree_surface *parent; // NULL for the top-level surface
|
||||
|
||||
struct wlr_box clip;
|
||||
struct wl_list link;
|
||||
bool is_visible;
|
||||
|
||||
// Only valid if the surface is a sub-surface
|
||||
|
||||
|
|
@ -35,38 +38,64 @@ struct wlr_scene_subsurface_tree {
|
|||
struct wl_listener subsurface_destroy;
|
||||
};
|
||||
|
||||
static void subsurface_tree_addon_destroy(struct wlr_addon *addon) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
wl_container_of(addon, subsurface_tree, scene_addon);
|
||||
static void subsurface_tree_handle_update_visibility(
|
||||
struct wlr_scene_subsurface_tree_surface *tree, bool is_destroying) {
|
||||
bool is_visible = tree->scene_surface->buffer->primary_output && !is_destroying;
|
||||
|
||||
if (is_visible && !tree->is_visible) {
|
||||
tree->subsurface_tree->visible_surfaces++;
|
||||
} else if (!is_visible && tree->is_visible) {
|
||||
assert(tree->subsurface_tree->visible_surfaces > 0);
|
||||
tree->subsurface_tree->visible_surfaces--;
|
||||
}
|
||||
|
||||
tree->is_visible = is_visible;
|
||||
|
||||
bool is_tree_visible = tree->subsurface_tree->visible_surfaces > 0;
|
||||
if (is_tree_visible != tree->subsurface_tree->is_visible) {
|
||||
tree->subsurface_tree->is_visible = is_tree_visible;
|
||||
wl_signal_emit_mutable(&tree->subsurface_tree->events.visibility, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void subsurface_tree_handle_scene_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(listener, subsurface_tree, scene_destroy);
|
||||
|
||||
subsurface_tree_handle_update_visibility(subsurface_tree, true);
|
||||
|
||||
// tree and scene_surface will be cleaned up by scene_node_finish
|
||||
if (subsurface_tree->parent) {
|
||||
wlr_addon_finish(&subsurface_tree->surface_addon);
|
||||
wl_list_remove(&subsurface_tree->subsurface_destroy.link);
|
||||
} else {
|
||||
free(subsurface_tree->subsurface_tree);
|
||||
}
|
||||
wlr_addon_finish(&subsurface_tree->scene_addon);
|
||||
wl_list_remove(&subsurface_tree->surface_destroy.link);
|
||||
wl_list_remove(&subsurface_tree->surface_commit.link);
|
||||
wl_list_remove(&subsurface_tree->surface_map.link);
|
||||
wl_list_remove(&subsurface_tree->surface_unmap.link);
|
||||
wl_list_remove(&subsurface_tree->surface_new_subsurface.link);
|
||||
wl_list_remove(&subsurface_tree->scene_destroy.link);
|
||||
wl_list_remove(&subsurface_tree->link);
|
||||
free(subsurface_tree);
|
||||
}
|
||||
|
||||
static const struct wlr_addon_interface subsurface_tree_surface_addon_impl;
|
||||
|
||||
static struct wlr_scene_subsurface_tree *subsurface_tree_from_subsurface(
|
||||
struct wlr_scene_subsurface_tree *parent,
|
||||
static struct wlr_scene_subsurface_tree_surface *subsurface_tree_from_subsurface(
|
||||
struct wlr_scene_subsurface_tree_surface *parent,
|
||||
struct wlr_subsurface *subsurface) {
|
||||
struct wlr_addon *addon = wlr_addon_find(&subsurface->surface->addons,
|
||||
parent, &subsurface_tree_surface_addon_impl);
|
||||
assert(addon != NULL);
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(addon, subsurface_tree, surface_addon);
|
||||
return subsurface_tree;
|
||||
}
|
||||
|
||||
static bool subsurface_tree_reconfigure_clip(
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree) {
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree) {
|
||||
if (subsurface_tree->parent) {
|
||||
subsurface_tree->clip = (struct wlr_box){
|
||||
.x = subsurface_tree->parent->clip.x - subsurface_tree->tree->node.x,
|
||||
|
|
@ -102,7 +131,7 @@ static bool subsurface_tree_reconfigure_clip(
|
|||
}
|
||||
|
||||
static void subsurface_tree_reconfigure(
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree) {
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree) {
|
||||
bool has_clip = subsurface_tree_reconfigure_clip(subsurface_tree);
|
||||
|
||||
struct wlr_surface *surface = subsurface_tree->surface;
|
||||
|
|
@ -111,7 +140,7 @@ static void subsurface_tree_reconfigure(
|
|||
struct wlr_subsurface *subsurface;
|
||||
wl_list_for_each(subsurface, &surface->current.subsurfaces_below,
|
||||
current.link) {
|
||||
struct wlr_scene_subsurface_tree *child =
|
||||
struct wlr_scene_subsurface_tree_surface *child =
|
||||
subsurface_tree_from_subsurface(subsurface_tree, subsurface);
|
||||
if (prev != NULL) {
|
||||
wlr_scene_node_place_above(&child->tree->node, prev);
|
||||
|
|
@ -133,7 +162,7 @@ static void subsurface_tree_reconfigure(
|
|||
|
||||
wl_list_for_each(subsurface, &surface->current.subsurfaces_above,
|
||||
current.link) {
|
||||
struct wlr_scene_subsurface_tree *child =
|
||||
struct wlr_scene_subsurface_tree_surface *child =
|
||||
subsurface_tree_from_subsurface(subsurface_tree, subsurface);
|
||||
wlr_scene_node_place_above(&child->tree->node, prev);
|
||||
prev = &child->tree->node;
|
||||
|
|
@ -149,14 +178,14 @@ static void subsurface_tree_reconfigure(
|
|||
|
||||
static void subsurface_tree_handle_surface_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(listener, subsurface_tree, surface_destroy);
|
||||
wlr_scene_node_destroy(&subsurface_tree->tree->node);
|
||||
}
|
||||
|
||||
static void subsurface_tree_handle_surface_commit(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(listener, subsurface_tree, surface_commit);
|
||||
|
||||
// TODO: only do this on subsurface order or position change
|
||||
|
|
@ -165,14 +194,14 @@ static void subsurface_tree_handle_surface_commit(struct wl_listener *listener,
|
|||
|
||||
static void subsurface_tree_handle_subsurface_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(listener, subsurface_tree, subsurface_destroy);
|
||||
wlr_scene_node_destroy(&subsurface_tree->tree->node);
|
||||
}
|
||||
|
||||
static void subsurface_tree_handle_surface_map(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(listener, subsurface_tree, surface_map);
|
||||
|
||||
wlr_scene_node_set_enabled(&subsurface_tree->tree->node, true);
|
||||
|
|
@ -180,31 +209,32 @@ static void subsurface_tree_handle_surface_map(struct wl_listener *listener,
|
|||
|
||||
static void subsurface_tree_handle_surface_unmap(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(listener, subsurface_tree, surface_unmap);
|
||||
|
||||
wlr_scene_node_set_enabled(&subsurface_tree->tree->node, false);
|
||||
}
|
||||
|
||||
static void subsurface_tree_surface_addon_destroy(struct wlr_addon *addon) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(addon, subsurface_tree, surface_addon);
|
||||
wlr_scene_node_destroy(&subsurface_tree->tree->node);
|
||||
}
|
||||
|
||||
static const struct wlr_addon_interface subsurface_tree_surface_addon_impl = {
|
||||
.name = "wlr_scene_subsurface_tree",
|
||||
.name = "wlr_scene_subsurface_tree_surface",
|
||||
.destroy = subsurface_tree_surface_addon_destroy,
|
||||
};
|
||||
|
||||
static struct wlr_scene_subsurface_tree *scene_surface_tree_create(
|
||||
static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surface(
|
||||
struct wlr_scene_subsurface_tree *tree,
|
||||
struct wlr_scene_tree *parent, struct wlr_surface *surface);
|
||||
|
||||
static bool subsurface_tree_create_subsurface(
|
||||
struct wlr_scene_subsurface_tree *parent,
|
||||
struct wlr_scene_subsurface_tree_surface *parent,
|
||||
struct wlr_subsurface *subsurface) {
|
||||
struct wlr_scene_subsurface_tree *child = scene_surface_tree_create(
|
||||
parent->tree, subsurface->surface);
|
||||
struct wlr_scene_subsurface_tree_surface *child = scene_surface_tree_create_surface(
|
||||
parent->subsurface_tree, parent->tree, subsurface->surface);
|
||||
if (child == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -222,7 +252,7 @@ static bool subsurface_tree_create_subsurface(
|
|||
|
||||
static void subsurface_tree_handle_surface_new_subsurface(
|
||||
struct wl_listener *listener, void *data) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(listener, subsurface_tree, surface_new_subsurface);
|
||||
struct wlr_subsurface *subsurface = data;
|
||||
if (!subsurface_tree_create_subsurface(subsurface_tree, subsurface)) {
|
||||
|
|
@ -230,19 +260,23 @@ static void subsurface_tree_handle_surface_new_subsurface(
|
|||
}
|
||||
}
|
||||
|
||||
static const struct wlr_addon_interface subsurface_tree_addon_impl = {
|
||||
.name = "wlr_scene_subsurface_tree",
|
||||
.destroy = subsurface_tree_addon_destroy,
|
||||
};
|
||||
static void subsurface_tree_handle_scene_outputs_update(
|
||||
struct wl_listener *listener, void *data) {
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
wl_container_of(listener, subsurface_tree, scene_outputs_update);
|
||||
subsurface_tree_handle_update_visibility(subsurface_tree, false);
|
||||
}
|
||||
|
||||
static struct wlr_scene_subsurface_tree *scene_surface_tree_create(
|
||||
static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surface(
|
||||
struct wlr_scene_subsurface_tree *tree,
|
||||
struct wlr_scene_tree *parent, struct wlr_surface *surface) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree =
|
||||
calloc(1, sizeof(*subsurface_tree));
|
||||
if (subsurface_tree == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
subsurface_tree->subsurface_tree = tree;
|
||||
subsurface_tree->tree = wlr_scene_tree_create(parent);
|
||||
if (subsurface_tree->tree == NULL) {
|
||||
goto error_surface_tree;
|
||||
|
|
@ -270,10 +304,15 @@ static struct wlr_scene_subsurface_tree *scene_surface_tree_create(
|
|||
}
|
||||
}
|
||||
|
||||
wl_list_insert(&tree->surfaces, &subsurface_tree->link);
|
||||
subsurface_tree_reconfigure(subsurface_tree);
|
||||
|
||||
wlr_addon_init(&subsurface_tree->scene_addon, &subsurface_tree->tree->node.addons,
|
||||
NULL, &subsurface_tree_addon_impl);
|
||||
subsurface_tree->scene_destroy.notify = subsurface_tree_handle_scene_destroy;
|
||||
wl_signal_add(&subsurface_tree->tree->node.events.destroy, &subsurface_tree->scene_destroy);
|
||||
|
||||
subsurface_tree->scene_outputs_update.notify = subsurface_tree_handle_scene_outputs_update;
|
||||
wl_signal_add(&subsurface_tree->scene_surface->buffer->events.outputs_update,
|
||||
&subsurface_tree->scene_outputs_update);
|
||||
|
||||
subsurface_tree->surface_destroy.notify = subsurface_tree_handle_surface_destroy;
|
||||
wl_signal_add(&surface->events.destroy, &subsurface_tree->surface_destroy);
|
||||
|
|
@ -293,6 +332,7 @@ static struct wlr_scene_subsurface_tree *scene_surface_tree_create(
|
|||
&subsurface_tree->surface_new_subsurface);
|
||||
|
||||
wlr_scene_node_set_enabled(&subsurface_tree->tree->node, surface->mapped);
|
||||
subsurface_tree_handle_update_visibility(subsurface_tree, false);
|
||||
|
||||
return subsurface_tree;
|
||||
|
||||
|
|
@ -303,68 +343,44 @@ error_surface_tree:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_scene_tree *wlr_scene_subsurface_tree_create(
|
||||
struct wlr_scene_subsurface_tree *wlr_scene_subsurface_tree_create(
|
||||
struct wlr_scene_tree *parent, struct wlr_surface *surface) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree =
|
||||
scene_surface_tree_create(parent, surface);
|
||||
if (subsurface_tree == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return subsurface_tree->tree;
|
||||
}
|
||||
|
||||
static struct wlr_scene_subsurface_tree *get_subsurface_tree_from_node(
|
||||
struct wlr_scene_node *node) {
|
||||
struct wlr_addon *addon = wlr_addon_find(&node->addons, NULL, &subsurface_tree_addon_impl);
|
||||
if (!addon) {
|
||||
struct wlr_scene_subsurface_tree *subsurface_tree = calloc(1, sizeof(*subsurface_tree));
|
||||
if (!subsurface_tree) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_scene_subsurface_tree *tree =
|
||||
wl_container_of(addon, tree, scene_addon);
|
||||
return tree;
|
||||
wl_list_init(&subsurface_tree->surfaces);
|
||||
wl_signal_init(&subsurface_tree->events.visibility);
|
||||
|
||||
struct wlr_scene_subsurface_tree_surface *subsurface_tree_surface =
|
||||
scene_surface_tree_create_surface(subsurface_tree, parent, surface);
|
||||
if (subsurface_tree_surface == NULL) {
|
||||
free(subsurface_tree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
subsurface_tree->root = subsurface_tree_surface;
|
||||
subsurface_tree->tree = subsurface_tree_surface->tree;
|
||||
return subsurface_tree;
|
||||
}
|
||||
|
||||
static bool subsurface_tree_set_clip(struct wlr_scene_node *node,
|
||||
void wlr_scene_subsurface_tree_set_clip(struct wlr_scene_subsurface_tree *tree,
|
||||
const struct wlr_box *clip) {
|
||||
if (node->type != WLR_SCENE_NODE_TREE) {
|
||||
return false;
|
||||
if (wlr_box_equal(&tree->root->clip, clip)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool discovered_subsurface_tree = false;
|
||||
struct wlr_scene_subsurface_tree *tree = get_subsurface_tree_from_node(node);
|
||||
if (tree) {
|
||||
if (tree->parent == NULL) {
|
||||
if (wlr_box_equal(&tree->clip, clip)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (clip) {
|
||||
tree->clip = *clip;
|
||||
} else {
|
||||
tree->clip = (struct wlr_box){0};
|
||||
}
|
||||
}
|
||||
|
||||
discovered_subsurface_tree = true;
|
||||
subsurface_tree_reconfigure_clip(tree);
|
||||
if (clip) {
|
||||
tree->root->clip = *clip;
|
||||
} else {
|
||||
tree->root->clip = (struct wlr_box){0};
|
||||
}
|
||||
|
||||
struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node);
|
||||
struct wlr_scene_node *child;
|
||||
wl_list_for_each(child, &scene_tree->children, link) {
|
||||
discovered_subsurface_tree |= subsurface_tree_set_clip(child, clip);
|
||||
// iterate in reverse because children of parent subsurface will appear
|
||||
// earlier in the list.
|
||||
struct wlr_scene_subsurface_tree_surface *surface;
|
||||
wl_list_for_each_reverse(surface, &tree->surfaces, link) {
|
||||
subsurface_tree_reconfigure_clip(surface);
|
||||
}
|
||||
|
||||
return discovered_subsurface_tree;
|
||||
}
|
||||
|
||||
void wlr_scene_subsurface_tree_set_clip(struct wlr_scene_node *node,
|
||||
const struct wlr_box *clip) {
|
||||
#ifndef NDEBUG
|
||||
bool found =
|
||||
#endif
|
||||
subsurface_tree_set_clip(node, clip);
|
||||
|
||||
assert(found);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,6 @@
|
|||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
|
||||
struct wlr_scene_xdg_surface {
|
||||
struct wlr_scene_tree *tree;
|
||||
struct wlr_xdg_surface *xdg_surface;
|
||||
struct wlr_scene_tree *surface_tree;
|
||||
|
||||
struct wl_listener tree_destroy;
|
||||
struct wl_listener xdg_surface_destroy;
|
||||
struct wl_listener xdg_surface_commit;
|
||||
};
|
||||
|
||||
static void scene_xdg_surface_handle_tree_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_scene_xdg_surface *scene_xdg_surface =
|
||||
|
|
@ -36,7 +26,7 @@ static void scene_xdg_surface_update_position(
|
|||
|
||||
struct wlr_box geo = {0};
|
||||
wlr_xdg_surface_get_geometry(xdg_surface, &geo);
|
||||
wlr_scene_node_set_position(&scene_xdg_surface->surface_tree->node,
|
||||
wlr_scene_node_set_position(&scene_xdg_surface->surface_tree->tree->node,
|
||||
-geo.x, -geo.y);
|
||||
|
||||
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
|
||||
|
|
@ -55,7 +45,7 @@ static void scene_xdg_surface_handle_xdg_surface_commit(struct wl_listener *list
|
|||
scene_xdg_surface_update_position(scene_xdg_surface);
|
||||
}
|
||||
|
||||
struct wlr_scene_tree *wlr_scene_xdg_surface_create(
|
||||
struct wlr_scene_xdg_surface *wlr_scene_xdg_surface_create(
|
||||
struct wlr_scene_tree *parent, struct wlr_xdg_surface *xdg_surface) {
|
||||
struct wlr_scene_xdg_surface *scene_xdg_surface =
|
||||
calloc(1, sizeof(*scene_xdg_surface));
|
||||
|
|
@ -95,5 +85,5 @@ struct wlr_scene_tree *wlr_scene_xdg_surface_create(
|
|||
|
||||
scene_xdg_surface_update_position(scene_xdg_surface);
|
||||
|
||||
return scene_xdg_surface->tree;
|
||||
return scene_xdg_surface;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue