mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-12-22 18:09:49 +01:00
wlr_scene: Introduce wlr_scene_subsurface_tree_set_clip
This commit is contained in:
parent
d1ddd4ca3a
commit
3d3cca9164
2 changed files with 115 additions and 0 deletions
|
@ -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 *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
|
||||
* scene-graph.
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/util/addon.h>
|
||||
#include "types/wlr_scene.h"
|
||||
|
||||
/**
|
||||
* 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_box clip;
|
||||
|
||||
// Only valid if the surface is a sub-surface
|
||||
|
||||
struct wlr_addon surface_addon;
|
||||
|
@ -62,8 +65,46 @@ static struct wlr_scene_subsurface_tree *subsurface_tree_from_subsurface(
|
|||
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(
|
||||
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_scene_node *prev = NULL;
|
||||
|
@ -79,6 +120,10 @@ static void subsurface_tree_reconfigure(
|
|||
|
||||
wlr_scene_node_set_position(&child->tree->node,
|
||||
subsurface->current.x, subsurface->current.y);
|
||||
|
||||
if (has_clip) {
|
||||
subsurface_tree_reconfigure_clip(child);
|
||||
}
|
||||
}
|
||||
|
||||
if (prev != NULL) {
|
||||
|
@ -95,6 +140,10 @@ static void subsurface_tree_reconfigure(
|
|||
|
||||
wlr_scene_node_set_position(&child->tree->node,
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue