mirror of
https://github.com/labwc/labwc.git
synced 2026-03-02 01:40:24 -05:00
ssd: clean up scene management
Our codebase for ssd scenes has grown with a lot of technical debts: - We needed to call `ssd_get_part()` everywhere to get the scene node of a ssd part. We then needed to cast it to `wlr_scene_rect` and `wlr_scene_buffer`. This bloated our codebase and even blocked duplicated button types in `<titlebar><layout>`. - `ssd_get_part_type()` was a dirty hack. It compared parent, grandparent and grandgrandparent of a node with each subtree in the ssd to get the part type of the node. To resolve this issues, this commit changes how ssd scenes are managed: - Access scene rects and scene buffers just as a member of `struct ssd`. - `ssd_part` is now a attachment to a scene node that can be accessed via node_descriptor->data, with a new node-descriptor type `LAB_NODE_DESC_SSD_PART`. `LAB_NODE_DESC_SSD_BUTTON` is unified into it. Now the scene graph under ssd->tree looks like below. The parentheses indicate the type of ssd_part attached to the node: ssd->tree (LAB_SSD_NONE) +--titlebar (LAB_SSD_PART_TITLEBAR) | +--inactive | | +--background bar | | +--left corner | | +--right corner | | +--title (LAB_SSD_PART_TITLE) | | +--iconify button (LAB_SSD_BUTTON_ICONIFY) | | | +--normal close icon image | | | +--hovered close icon image | | | +--... | | +--window icon (LAB_SSD_BUTTON_WINDOW_ICON) | | | +--window icon image | | +--... | +--active | +--... +--border | +--inactive | | +--top | | +--... | +--active | +--top | +--... +--shadow | +--inactive | | +--top | | +--... | +--active | +--top | +--... +--extents +--top +--... When hovering on SSD, `get_cursor_context()` traverses this scene node from the leaf. If it finds a `ssd_part` attached to the node, it returns `ssd_part_type` that represents the resizing direction, button types or `Title`/`Titlebar`.
This commit is contained in:
parent
aa3dbb4f85
commit
f347a818e3
13 changed files with 516 additions and 726 deletions
|
|
@ -1,100 +1,77 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <assert.h>
|
||||
#include "buffer.h"
|
||||
#include "common/box.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "common/list.h"
|
||||
#include "common/mem.h"
|
||||
#include "common/scaled-icon-buffer.h"
|
||||
#include "common/scaled-img-buffer.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "labwc.h"
|
||||
#include "node.h"
|
||||
#include "ssd-internal.h"
|
||||
|
||||
/* Internal helpers */
|
||||
static void
|
||||
handle_button_node_destroy(struct wl_listener *listener, void *data)
|
||||
handle_node_destroy(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct ssd_button *button = wl_container_of(listener, button, destroy);
|
||||
wl_list_remove(&button->destroy.link);
|
||||
free(button);
|
||||
}
|
||||
struct ssd_part *part = wl_container_of(listener, part, node_destroy);
|
||||
wl_list_remove(&part->node_destroy.link);
|
||||
|
||||
/*
|
||||
* Create a new node_descriptor containing a link to a new ssd_button struct.
|
||||
* Both will be destroyed automatically once the scene_node they are attached
|
||||
* to is destroyed.
|
||||
*/
|
||||
static struct ssd_button *
|
||||
ssd_button_descriptor_create(struct wlr_scene_node *node)
|
||||
{
|
||||
/* Create new ssd_button */
|
||||
struct ssd_button *button = znew(*button);
|
||||
struct ssd_part_button *button = button_try_from_ssd_part(part);
|
||||
if (button) {
|
||||
wl_list_remove(&button->link);
|
||||
}
|
||||
|
||||
/* Let it destroy automatically when the scene node destroys */
|
||||
button->destroy.notify = handle_button_node_destroy;
|
||||
wl_signal_add(&node->events.destroy, &button->destroy);
|
||||
|
||||
/* And finally attach the ssd_button to a node descriptor */
|
||||
node_descriptor_create(node, LAB_NODE_DESC_SSD_BUTTON, button);
|
||||
return button;
|
||||
free(part);
|
||||
}
|
||||
|
||||
/* Internal API */
|
||||
struct ssd_part *
|
||||
add_scene_part(struct wl_list *part_list, enum ssd_part_type type)
|
||||
|
||||
/*
|
||||
* Create a new node_descriptor containing a link to a new ssd_part struct.
|
||||
* Both will be destroyed automatically once the scene_node they are attached
|
||||
* to is destroyed.
|
||||
*/
|
||||
static void
|
||||
init_ssd_part(struct ssd_part *part, enum ssd_part_type type,
|
||||
struct view *view, struct wlr_scene_node *node)
|
||||
{
|
||||
struct ssd_part *part = znew(*part);
|
||||
part->type = type;
|
||||
wl_list_append(part_list, &part->link);
|
||||
return part;
|
||||
part->node = node;
|
||||
part->view = view;
|
||||
|
||||
node_descriptor_create(node, LAB_NODE_DESC_SSD_PART, part);
|
||||
part->node_destroy.notify = handle_node_destroy;
|
||||
wl_signal_add(&node->events.destroy, &part->node_destroy);
|
||||
}
|
||||
|
||||
struct ssd_part *
|
||||
add_scene_rect(struct wl_list *list, enum ssd_part_type type,
|
||||
struct wlr_scene_tree *parent, int width, int height,
|
||||
int x, int y, float color[4])
|
||||
attach_ssd_part(enum ssd_part_type type, struct view *view,
|
||||
struct wlr_scene_node *node)
|
||||
{
|
||||
assert(width >= 0 && height >= 0);
|
||||
struct ssd_part *part = add_scene_part(list, type);
|
||||
part->node = &wlr_scene_rect_create(
|
||||
parent, width, height, color)->node;
|
||||
wlr_scene_node_set_position(part->node, x, y);
|
||||
assert(!ssd_part_contains(LAB_SSD_BUTTON, type));
|
||||
struct ssd_part *part = znew(*part);
|
||||
init_ssd_part(part, type, view, node);
|
||||
return part;
|
||||
}
|
||||
|
||||
struct ssd_part *
|
||||
add_scene_buffer(struct wl_list *list, enum ssd_part_type type,
|
||||
struct wlr_scene_tree *parent, struct wlr_buffer *buffer,
|
||||
int x, int y)
|
||||
{
|
||||
struct ssd_part *part = add_scene_part(list, type);
|
||||
part->node = &wlr_scene_buffer_create(parent, buffer)->node;
|
||||
wlr_scene_node_set_position(part->node, x, y);
|
||||
return part;
|
||||
}
|
||||
|
||||
struct ssd_part *
|
||||
add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||
struct ssd_part_button *
|
||||
attach_ssd_part_button(struct wl_list *button_parts, enum ssd_part_type type,
|
||||
struct wlr_scene_tree *parent,
|
||||
struct lab_img *imgs[LAB_BS_ALL + 1],
|
||||
int x, int y, struct view *view)
|
||||
{
|
||||
struct ssd_part *button_root = add_scene_part(part_list, type);
|
||||
parent = wlr_scene_tree_create(parent);
|
||||
button_root->node = &parent->node;
|
||||
wlr_scene_node_set_position(button_root->node, x, y);
|
||||
struct wlr_scene_tree *root = wlr_scene_tree_create(parent);
|
||||
wlr_scene_node_set_position(&root->node, x, y);
|
||||
|
||||
struct ssd_button *button = ssd_button_descriptor_create(button_root->node);
|
||||
button->type = type;
|
||||
button->view = view;
|
||||
assert(ssd_part_contains(LAB_SSD_BUTTON, type));
|
||||
struct ssd_part_button *button = znew(*button);
|
||||
init_ssd_part(&button->base, type, view, &root->node);
|
||||
wl_list_append(button_parts, &button->link);
|
||||
|
||||
/* Hitbox */
|
||||
float invisible[4] = { 0, 0, 0, 0 };
|
||||
add_scene_rect(part_list, type, parent,
|
||||
rc.theme->window_button_width, rc.theme->window_button_height, 0, 0,
|
||||
invisible);
|
||||
wlr_scene_rect_create(root, rc.theme->window_button_width,
|
||||
rc.theme->window_button_height, invisible);
|
||||
|
||||
/* Icons */
|
||||
int button_width = rc.theme->window_button_width;
|
||||
|
|
@ -110,14 +87,13 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
|||
int icon_padding = button_width / 10;
|
||||
|
||||
if (type == LAB_SSD_BUTTON_WINDOW_ICON) {
|
||||
struct ssd_part *icon_part = add_scene_part(part_list, type);
|
||||
struct scaled_icon_buffer *icon_buffer =
|
||||
scaled_icon_buffer_create(parent, view->server,
|
||||
scaled_icon_buffer_create(root, view->server,
|
||||
button_width - 2 * icon_padding, button_height);
|
||||
scaled_icon_buffer_set_view(icon_buffer, view);
|
||||
assert(icon_buffer);
|
||||
icon_part->node = &icon_buffer->scene_buffer->node;
|
||||
wlr_scene_node_set_position(icon_part->node, icon_padding, 0);
|
||||
struct wlr_scene_node *icon_node = &icon_buffer->scene_buffer->node;
|
||||
scaled_icon_buffer_set_view(icon_buffer, view);
|
||||
wlr_scene_node_set_position(icon_node, icon_padding, 0);
|
||||
button->window_icon = icon_buffer;
|
||||
} else {
|
||||
for (uint8_t state_set = LAB_BS_DEFAULT;
|
||||
|
|
@ -125,13 +101,12 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
|||
if (!imgs[state_set]) {
|
||||
continue;
|
||||
}
|
||||
struct ssd_part *icon_part = add_scene_part(part_list, type);
|
||||
struct scaled_img_buffer *img_buffer = scaled_img_buffer_create(
|
||||
parent, imgs[state_set], rc.theme->window_button_width,
|
||||
root, imgs[state_set], rc.theme->window_button_width,
|
||||
rc.theme->window_button_height);
|
||||
assert(img_buffer);
|
||||
icon_part->node = &img_buffer->scene_buffer->node;
|
||||
wlr_scene_node_set_enabled(icon_part->node, false);
|
||||
struct wlr_scene_node *icon_node = &img_buffer->scene_buffer->node;
|
||||
wlr_scene_node_set_enabled(icon_node, false);
|
||||
button->img_buffers[state_set] = img_buffer;
|
||||
}
|
||||
/* Initially show non-hover, non-toggled, unrounded variant */
|
||||
|
|
@ -139,34 +114,14 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
|||
&button->img_buffers[LAB_BS_DEFAULT]->scene_buffer->node, true);
|
||||
}
|
||||
|
||||
return button_root;
|
||||
return button;
|
||||
}
|
||||
|
||||
struct ssd_part *
|
||||
ssd_get_part(struct wl_list *part_list, enum ssd_part_type type)
|
||||
struct ssd_part_button *
|
||||
button_try_from_ssd_part(struct ssd_part *part)
|
||||
{
|
||||
struct ssd_part *part;
|
||||
wl_list_for_each(part, part_list, link) {
|
||||
if (part->type == type) {
|
||||
return part;
|
||||
}
|
||||
if (ssd_part_contains(LAB_SSD_BUTTON, part->type)) {
|
||||
return (struct ssd_part_button *)part;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ssd_destroy_parts(struct wl_list *list)
|
||||
{
|
||||
struct ssd_part *part, *tmp;
|
||||
wl_list_for_each_reverse_safe(part, tmp, list, link) {
|
||||
if (part->node) {
|
||||
wlr_scene_node_destroy(part->node);
|
||||
part->node = NULL;
|
||||
}
|
||||
/* part->buffer will free itself along the scene_buffer node */
|
||||
part->buffer = NULL;
|
||||
wl_list_remove(&part->link);
|
||||
free(part);
|
||||
}
|
||||
assert(wl_list_empty(list));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue