wlr_scene: Introduce wlr_scene_subsurface_tree_set_clip

This commit is contained in:
Alexander Orzechowski 2023-11-13 01:25:52 -05:00 committed by Isaac Freund
parent d1ddd4ca3a
commit 3d3cca9164
2 changed files with 115 additions and 0 deletions

View file

@ -543,6 +543,16 @@ void wlr_scene_output_layout_add_output(struct wlr_scene_output_layout *sol,
struct wlr_scene_tree *wlr_scene_subsurface_tree_create( struct wlr_scene_tree *wlr_scene_subsurface_tree_create(
struct wlr_scene_tree *parent, struct wlr_surface *surface); struct wlr_scene_tree *parent, struct wlr_surface *surface);
/**
* Sets a cropping region for any subsurface trees that are children of this
* scene node. The clip coordinate space will be that of the root surface of
* the subsurface tree.
*
* A NULL or empty clip will disable clipping
*/
void wlr_scene_subsurface_tree_set_clip(struct wlr_scene_node *node,
struct wlr_box *clip);
/** /**
* Add a node displaying an xdg_surface and all of its sub-surfaces to the * Add a node displaying an xdg_surface and all of its sub-surfaces to the
* scene-graph. * scene-graph.

View file

@ -4,6 +4,7 @@
#include <wlr/types/wlr_scene.h> #include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_subcompositor.h> #include <wlr/types/wlr_subcompositor.h>
#include <wlr/util/addon.h> #include <wlr/util/addon.h>
#include "types/wlr_scene.h"
/** /**
* A tree for a surface and all of its child sub-surfaces. * A tree for a surface and all of its child sub-surfaces.
@ -25,6 +26,8 @@ struct wlr_scene_subsurface_tree {
struct wlr_addon scene_addon; struct wlr_addon scene_addon;
struct wlr_box clip;
// Only valid if the surface is a sub-surface // Only valid if the surface is a sub-surface
struct wlr_addon surface_addon; struct wlr_addon surface_addon;
@ -62,8 +65,46 @@ static struct wlr_scene_subsurface_tree *subsurface_tree_from_subsurface(
return subsurface_tree; return subsurface_tree;
} }
static bool subsurface_tree_reconfigure_clip(
struct wlr_scene_subsurface_tree *subsurface_tree) {
if (subsurface_tree->parent) {
subsurface_tree->clip = (struct wlr_box){
.x = subsurface_tree->parent->clip.x - subsurface_tree->tree->node.x,
.y = subsurface_tree->parent->clip.y - subsurface_tree->tree->node.y,
.width = subsurface_tree->parent->clip.width,
.height = subsurface_tree->parent->clip.height,
};
}
if (wlr_box_empty(&subsurface_tree->clip)) {
scene_surface_set_clip(subsurface_tree->scene_surface, NULL);
wlr_scene_node_set_enabled(&subsurface_tree->scene_surface->buffer->node, true);
wlr_scene_node_set_position(&subsurface_tree->scene_surface->buffer->node, 0, 0);
return false;
} else {
struct wlr_box clip = subsurface_tree->clip;
struct wlr_box surface_box = {
.width = subsurface_tree->surface->current.width,
.height = subsurface_tree->surface->current.height,
};
bool intersects = wlr_box_intersection(&clip, &clip, &surface_box);
wlr_scene_node_set_enabled(&subsurface_tree->scene_surface->buffer->node, intersects);
if (intersects) {
wlr_scene_node_set_position(&subsurface_tree->scene_surface->buffer->node, clip.x, clip.y);
scene_surface_set_clip(subsurface_tree->scene_surface, &clip);
}
return true;
}
}
static void subsurface_tree_reconfigure( static void subsurface_tree_reconfigure(
struct wlr_scene_subsurface_tree *subsurface_tree) { struct wlr_scene_subsurface_tree *subsurface_tree) {
bool has_clip = subsurface_tree_reconfigure_clip(subsurface_tree);
struct wlr_surface *surface = subsurface_tree->surface; struct wlr_surface *surface = subsurface_tree->surface;
struct wlr_scene_node *prev = NULL; struct wlr_scene_node *prev = NULL;
@ -79,6 +120,10 @@ static void subsurface_tree_reconfigure(
wlr_scene_node_set_position(&child->tree->node, wlr_scene_node_set_position(&child->tree->node,
subsurface->current.x, subsurface->current.y); subsurface->current.x, subsurface->current.y);
if (has_clip) {
subsurface_tree_reconfigure_clip(child);
}
} }
if (prev != NULL) { if (prev != NULL) {
@ -95,6 +140,10 @@ static void subsurface_tree_reconfigure(
wlr_scene_node_set_position(&child->tree->node, wlr_scene_node_set_position(&child->tree->node,
subsurface->current.x, subsurface->current.y); subsurface->current.x, subsurface->current.y);
if (has_clip) {
subsurface_tree_reconfigure_clip(child);
}
} }
} }
@ -263,3 +312,59 @@ struct wlr_scene_tree *wlr_scene_subsurface_tree_create(
} }
return subsurface_tree->tree; 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) {
return NULL;
}
struct wlr_scene_subsurface_tree *tree =
wl_container_of(addon, tree, scene_addon);
return tree;
}
static bool subsurface_tree_set_clip(struct wlr_scene_node *node,
struct wlr_box *clip) {
if (node->type != WLR_SCENE_NODE_TREE) {
return false;
}
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);
}
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);
}
return discovered_subsurface_tree;
}
void wlr_scene_subsurface_tree_set_clip(struct wlr_scene_node *node,
struct wlr_box *clip) {
#ifndef NDEBUG
bool found =
#endif
subsurface_tree_set_clip(node, clip);
assert(found);
}