ssd: unify struct ssd_part with struct node_descriptor

struct ssd_part and struct node_descriptor seem to have essentially the
same purpose: tag a wlr_scene_node with some extra data indicating what
we're using it for.

Also, as with enum ssd_part_type (now lab_node_type), ssd_part is used
for several types of nodes that are not part of SSD.

So instead of the current chaining (node_descriptor -> ssd_part), let's
flatten/unify the two structs.

In detail:

- First, merge node_descriptor_type into lab_node_type.
- Add a separate view pointer in node_descriptor, since in the case of
  SSD buttons we need separate view and button data pointers.
- Rename ssd_part_button to simply ssd_button. It no longer contains
  an ssd_part as base.
- Add node_try_ssd_button_from_node() which replaces
  node_ssd_part_from_node() + button_try_from_ssd_part().
- Factor out ssd_button_free() to be called in node descriptor destroy.
- Finally, get_cursor_context() needs a little reorganization to handle
  the unified structs.

Overall, this simplifies the code a bit, and in my opinion makes it
easier to understand. No functional change intended.
This commit is contained in:
John Lindgren 2025-09-03 05:32:44 -04:00
parent ba426e2271
commit f129571779
22 changed files with 169 additions and 239 deletions

View file

@ -46,12 +46,23 @@ enum lab_node_type {
LAB_NODE_CLIENT,
LAB_NODE_FRAME,
LAB_NODE_ROOT,
LAB_NODE_MENU,
LAB_NODE_MENUITEM,
LAB_NODE_OSD,
LAB_NODE_LAYER_SURFACE,
LAB_NODE_LAYER_SUBSURFACE,
LAB_NODE_UNMANAGED,
LAB_NODE_ALL,
/* translated to LAB_NODE_CLIENT by get_cursor_context() */
LAB_NODE_VIEW,
LAB_NODE_XDG_POPUP,
LAB_NODE_LAYER_POPUP,
LAB_NODE_SESSION_LOCK_SURFACE,
LAB_NODE_IME_POPUP,
/* never returned by get_cursor_context() */
LAB_NODE_TREE,
LAB_NODE_SCALED_BUFFER,
};
enum lab_node_type node_type_parse(const char *context);

View file

@ -225,7 +225,7 @@ struct server {
*/
struct view *active_view;
struct ssd_part_button *hovered_button;
struct ssd_button *hovered_button;
/* Tree for all non-layer xdg/xwayland-shell surfaces */
struct wlr_scene_tree *view_tree;

View file

@ -2,30 +2,11 @@
#ifndef LABWC_NODE_DESCRIPTOR_H
#define LABWC_NODE_DESCRIPTOR_H
#include <wlr/types/wlr_scene.h>
struct view;
struct lab_layer_surface;
struct lab_layer_popup;
struct menuitem;
struct ssd_part;
struct scaled_buffer;
enum node_descriptor_type {
LAB_NODE_DESC_NODE = 0,
LAB_NODE_DESC_VIEW,
LAB_NODE_DESC_XDG_POPUP,
LAB_NODE_DESC_LAYER_SURFACE,
LAB_NODE_DESC_LAYER_POPUP,
LAB_NODE_DESC_SESSION_LOCK_SURFACE,
LAB_NODE_DESC_IME_POPUP,
LAB_NODE_DESC_MENUITEM,
LAB_NODE_DESC_TREE,
LAB_NODE_DESC_SCALED_BUFFER,
LAB_NODE_DESC_SSD_PART,
};
#include "common/node-type.h"
struct node_descriptor {
enum node_descriptor_type type;
enum lab_node_type type;
struct view *view;
void *data;
struct wl_listener destroy;
};
@ -38,16 +19,15 @@ struct node_descriptor {
*
* @scene_node: wlr_scene_node to attached node_descriptor to
* @type: node descriptor type
* @view: associated view
* @data: struct to point to as follows:
* - LAB_NODE_DESC_VIEW struct view
* - LAB_NODE_DESC_XDG_POPUP struct view
* - LAB_NODE_DESC_LAYER_SURFACE struct lab_layer_surface
* - LAB_NODE_DESC_LAYER_POPUP struct lab_layer_popup
* - LAB_NODE_DESC_MENUITEM struct menuitem
* - LAB_NODE_DESC_SSD_PART struct ssd_part
* - LAB_NODE_LAYER_SURFACE struct lab_layer_surface
* - LAB_NODE_LAYER_POPUP struct lab_layer_popup
* - LAB_NODE_MENUITEM struct menuitem
* - LAB_NODE_BUTTON_* struct ssd_button
*/
void node_descriptor_create(struct wlr_scene_node *scene_node,
enum node_descriptor_type type, void *data);
enum lab_node_type type, struct view *view, void *data);
/**
* node_view_from_node - return view struct from node
@ -76,13 +56,6 @@ struct lab_layer_popup *node_layer_popup_from_node(
struct menuitem *node_menuitem_from_node(
struct wlr_scene_node *wlr_scene_node);
/**
* node_ssd_part_from_node - return ssd_part struct from node
* @wlr_scene_node: wlr_scene_node from which to return data
*/
struct ssd_part *node_ssd_part_from_node(
struct wlr_scene_node *wlr_scene_node);
/**
* node_scaled_buffer_from_node - return scaled_buffer from node
* @wlr_scene_node: wlr_scene_node from which to return data
@ -90,4 +63,11 @@ struct ssd_part *node_ssd_part_from_node(
struct scaled_buffer *node_scaled_buffer_from_node(
struct wlr_scene_node *wlr_scene_node);
/**
* node_try_ssd_button_from_node - return ssd_button or NULL from node
* @wlr_scene_node: wlr_scene_node from which to return data
*/
struct ssd_button *node_try_ssd_button_from_node(
struct wlr_scene_node *wlr_scene_node);
#endif /* LABWC_NODE_DESCRIPTOR_H */

View file

@ -135,23 +135,10 @@ struct ssd {
struct border margin;
};
/*
* ssd_part wraps a scene-node with ssd-specific information and can be
* accessed with node_ssd_part_from_node(wlr_scene_node *).
* This allows get_cursor_context() in desktop.c to see which SSD part is under
* the cursor.
*/
struct ssd_part {
enum lab_node_type type;
struct view *view;
/* This part represented in scene graph */
struct ssd_button {
struct wlr_scene_node *node;
struct wl_listener node_destroy;
};
enum lab_node_type type;
struct ssd_part_button {
struct ssd_part base;
/*
* Bitmap of lab_button_state that represents a combination of
* hover/toggled/rounded states.
@ -177,13 +164,10 @@ struct wlr_buffer;
struct wlr_scene_tree;
/* SSD internal helpers to create various SSD elements */
struct ssd_part *attach_ssd_part(enum lab_node_type type, struct view *view,
struct wlr_scene_node *node);
struct ssd_part_button *attach_ssd_part_button(struct wl_list *button_parts,
struct ssd_button *attach_ssd_button(struct wl_list *button_parts,
enum lab_node_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 *button_try_from_ssd_part(struct ssd_part *part);
/* SSD internal */
void ssd_titlebar_create(struct ssd *ssd);

View file

@ -25,7 +25,7 @@ struct wlr_cursor;
/* Forward declare arguments */
struct server;
struct ssd;
struct ssd_part;
struct ssd_button;
struct view;
struct wlr_scene;
struct wlr_scene_node;
@ -55,8 +55,7 @@ void ssd_enable_shade(struct ssd *ssd, bool enable);
void ssd_update_hovered_button(struct server *server,
struct wlr_scene_node *node);
enum lab_node_type ssd_part_get_type(const struct ssd_part *part);
struct view *ssd_part_get_view(const struct ssd_part *part);
void ssd_button_free(struct ssd_button *button);
/* Public SSD helpers */

View file

@ -247,11 +247,11 @@ get_surface_from_layer_node(struct wlr_scene_node *node)
{
assert(node->data);
struct node_descriptor *desc = (struct node_descriptor *)node->data;
if (desc->type == LAB_NODE_DESC_LAYER_SURFACE) {
if (desc->type == LAB_NODE_LAYER_SURFACE) {
struct lab_layer_surface *surface;
surface = node_layer_surface_from_node(node);
return surface->scene_layer_surface->layer_surface->surface;
} else if (desc->type == LAB_NODE_DESC_LAYER_POPUP) {
} else if (desc->type == LAB_NODE_LAYER_POPUP) {
struct lab_layer_popup *popup;
popup = node_layer_popup_from_node(node);
return popup->wlr_popup->base->surface;
@ -299,9 +299,9 @@ get_cursor_context(struct server *server)
struct node_descriptor *desc = node->data;
if (desc) {
switch (desc->type) {
case LAB_NODE_DESC_VIEW:
case LAB_NODE_DESC_XDG_POPUP:
ret.view = desc->data;
case LAB_NODE_VIEW:
case LAB_NODE_XDG_POPUP:
ret.view = desc->view;
if (ret.node->type == WLR_SCENE_NODE_BUFFER
&& lab_wlr_surface_from_node(ret.node)) {
ret.type = LAB_NODE_CLIENT;
@ -311,10 +311,43 @@ get_cursor_context(struct server *server)
wlr_log(WLR_ERROR, "cursor not on client or ssd");
}
return ret;
case LAB_NODE_DESC_SSD_PART: {
struct ssd_part *part = node_ssd_part_from_node(node);
case LAB_NODE_LAYER_SURFACE:
ret.node = node;
ret.view = ssd_part_get_view(part);
ret.type = LAB_NODE_LAYER_SURFACE;
ret.surface = get_surface_from_layer_node(node);
return ret;
case LAB_NODE_LAYER_POPUP:
ret.node = node;
ret.type = LAB_NODE_CLIENT;
ret.surface = get_surface_from_layer_node(node);
return ret;
case LAB_NODE_SESSION_LOCK_SURFACE: /* fallthrough */
case LAB_NODE_IME_POPUP:
ret.type = LAB_NODE_CLIENT;
ret.surface = lab_wlr_surface_from_node(ret.node);
return ret;
case LAB_NODE_MENUITEM:
/* Always return the top scene node for menu items */
ret.node = node;
ret.type = LAB_NODE_MENUITEM;
return ret;
case LAB_NODE_TREE:
case LAB_NODE_SCALED_BUFFER:
/* Continue to parent node */
break;
default:
/*
* All other node descriptors (buttons, title,
* etc.) should have an associated view.
*/
if (!desc->view) {
wlr_log(WLR_ERROR, "cursor not on any view "
"(node type %d)", desc->type);
return ret;
}
ret.node = node;
ret.view = desc->view;
/* Detect mouse contexts like Top, Left and TRCorner */
ret.type = ssd_get_resizing_type(ret.view->ssd, cursor);
@ -323,36 +356,11 @@ get_cursor_context(struct server *server)
* Otherwise, detect mouse contexts like
* Title, Titlebar and Iconify
*/
ret.type = ssd_part_get_type(part);
ret.type = desc->type;
}
return ret;
}
case LAB_NODE_DESC_LAYER_SURFACE:
ret.node = node;
ret.type = LAB_NODE_LAYER_SURFACE;
ret.surface = get_surface_from_layer_node(node);
return ret;
case LAB_NODE_DESC_LAYER_POPUP:
ret.node = node;
ret.type = LAB_NODE_CLIENT;
ret.surface = get_surface_from_layer_node(node);
return ret;
case LAB_NODE_DESC_SESSION_LOCK_SURFACE: /* fallthrough */
case LAB_NODE_DESC_IME_POPUP:
ret.type = LAB_NODE_CLIENT;
ret.surface = lab_wlr_surface_from_node(ret.node);
return ret;
case LAB_NODE_DESC_MENUITEM:
/* Always return the top scene node for menu items */
ret.node = node;
ret.type = LAB_NODE_MENU;
return ret;
case LAB_NODE_DESC_NODE:
case LAB_NODE_DESC_TREE:
case LAB_NODE_DESC_SCALED_BUFFER:
break;
}
}
/* Edge-case nodes without node-descriptors */

View file

@ -314,7 +314,7 @@ subtract_node_tree(struct wlr_scene_tree *tree, pixman_region32_t *available,
}
node_desc = node->data;
if (node_desc && node_desc->type == LAB_NODE_DESC_VIEW) {
if (node_desc && node_desc->type == LAB_NODE_VIEW) {
view = node_view_from_node(node);
if (view != ignored_view) {
subtract_view_from_space(view, available);

View file

@ -609,7 +609,7 @@ cursor_process_motion(struct server *server, uint32_t time, double *sx, double *
struct cursor_context ctx = get_cursor_context(server);
struct seat *seat = &server->seat;
if (ctx.type == LAB_NODE_MENU) {
if (ctx.type == LAB_NODE_MENUITEM) {
menu_process_cursor_motion(ctx.node);
cursor_set(&server->seat, LAB_CURSOR_DEFAULT);
return false;
@ -1173,7 +1173,7 @@ cursor_process_button_release(struct seat *seat, uint32_t button,
if (server->input_mode == LAB_INPUT_STATE_MENU) {
/* TODO: take into account overflow of time_msec */
if (time_msec - press_msec > rc.menu_ignore_button_release_period) {
if (ctx.type == LAB_NODE_MENU) {
if (ctx.type == LAB_NODE_MENUITEM) {
menu_call_selected_actions(server);
} else {
menu_close_root(server);

View file

@ -393,7 +393,8 @@ handle_input_method_new_popup_surface(struct wl_listener *listener, void *data)
popup->tree = wlr_scene_subsurface_tree_create(
relay->popup_tree, popup->popup_surface->surface);
node_descriptor_create(&popup->tree->node, LAB_NODE_DESC_IME_POPUP, NULL);
node_descriptor_create(&popup->tree->node, LAB_NODE_IME_POPUP,
/*view*/ NULL, /*data*/ NULL);
wl_list_insert(&relay->popups, &popup->link);

View file

@ -473,7 +473,7 @@ create_popup(struct server *server, struct wlr_xdg_popup *wlr_popup,
wlr_popup->base->surface->data = popup->scene_tree;
node_descriptor_create(&popup->scene_tree->node,
LAB_NODE_DESC_LAYER_POPUP, popup);
LAB_NODE_LAYER_POPUP, /*view*/ NULL, popup);
popup->destroy.notify = handle_popup_destroy;
wl_signal_add(&wlr_popup->events.destroy, &popup->destroy);
@ -624,7 +624,7 @@ handle_new_layer_surface(struct wl_listener *listener, void *data)
layer_surface->surface->data = surface->scene_layer_surface->tree;
node_descriptor_create(&surface->scene_layer_surface->tree->node,
LAB_NODE_DESC_LAYER_SURFACE, surface);
LAB_NODE_LAYER_SURFACE, /*view*/ NULL, surface);
surface->server = server;
surface->scene_layer_surface->layer_surface = layer_surface;

View file

@ -246,8 +246,8 @@ item_create_scene(struct menuitem *menuitem, int *item_y)
/* Menu item root node */
menuitem->tree = wlr_scene_tree_create(menu->scene_tree);
node_descriptor_create(&menuitem->tree->node,
LAB_NODE_DESC_MENUITEM, menuitem);
node_descriptor_create(&menuitem->tree->node, LAB_NODE_MENUITEM,
/*view*/ NULL, menuitem);
/* Create scenes for unselected/selected states */
menuitem->normal_tree = item_create_scene_for_state(menuitem,
@ -295,8 +295,8 @@ separator_create_scene(struct menuitem *menuitem, int *item_y)
/* Menu item root node */
menuitem->tree = wlr_scene_tree_create(menu->scene_tree);
node_descriptor_create(&menuitem->tree->node,
LAB_NODE_DESC_MENUITEM, menuitem);
node_descriptor_create(&menuitem->tree->node, LAB_NODE_MENUITEM,
/*view*/ NULL, menuitem);
/* Tree to hold background and line buffer */
menuitem->normal_tree = wlr_scene_tree_create(menuitem->tree);
@ -343,8 +343,8 @@ title_create_scene(struct menuitem *menuitem, int *item_y)
/* Menu item root node */
menuitem->tree = wlr_scene_tree_create(menu->scene_tree);
node_descriptor_create(&menuitem->tree->node,
LAB_NODE_DESC_MENUITEM, menuitem);
node_descriptor_create(&menuitem->tree->node, LAB_NODE_MENUITEM,
/*view*/ NULL, menuitem);
/* Tree to hold background and text buffer */
menuitem->normal_tree = wlr_scene_tree_create(menuitem->tree);

View file

@ -3,31 +3,29 @@
#include <assert.h>
#include <stdlib.h>
#include "common/mem.h"
static void
descriptor_destroy(struct node_descriptor *node_descriptor)
{
if (!node_descriptor) {
return;
}
wl_list_remove(&node_descriptor->destroy.link);
free(node_descriptor);
}
#include "ssd.h"
static void
handle_node_destroy(struct wl_listener *listener, void *data)
{
struct node_descriptor *node_descriptor =
wl_container_of(listener, node_descriptor, destroy);
descriptor_destroy(node_descriptor);
if (node_type_contains(LAB_NODE_BUTTON, node_descriptor->type)) {
ssd_button_free(node_descriptor->data);
}
wl_list_remove(&node_descriptor->destroy.link);
free(node_descriptor);
}
void
node_descriptor_create(struct wlr_scene_node *scene_node,
enum node_descriptor_type type, void *data)
enum lab_node_type type, struct view *view, void *data)
{
struct node_descriptor *node_descriptor = znew(*node_descriptor);
node_descriptor->type = type;
node_descriptor->view = view;
node_descriptor->data = data;
node_descriptor->destroy.notify = handle_node_destroy;
wl_signal_add(&scene_node->events.destroy, &node_descriptor->destroy);
@ -39,9 +37,7 @@ node_view_from_node(struct wlr_scene_node *wlr_scene_node)
{
assert(wlr_scene_node->data);
struct node_descriptor *node_descriptor = wlr_scene_node->data;
assert(node_descriptor->type == LAB_NODE_DESC_VIEW
|| node_descriptor->type == LAB_NODE_DESC_XDG_POPUP);
return (struct view *)node_descriptor->data;
return node_descriptor->view;
}
struct lab_layer_surface *
@ -49,7 +45,7 @@ node_layer_surface_from_node(struct wlr_scene_node *wlr_scene_node)
{
assert(wlr_scene_node->data);
struct node_descriptor *node_descriptor = wlr_scene_node->data;
assert(node_descriptor->type == LAB_NODE_DESC_LAYER_SURFACE);
assert(node_descriptor->type == LAB_NODE_LAYER_SURFACE);
return (struct lab_layer_surface *)node_descriptor->data;
}
@ -58,7 +54,7 @@ node_layer_popup_from_node(struct wlr_scene_node *wlr_scene_node)
{
assert(wlr_scene_node->data);
struct node_descriptor *node_descriptor = wlr_scene_node->data;
assert(node_descriptor->type == LAB_NODE_DESC_LAYER_POPUP);
assert(node_descriptor->type == LAB_NODE_LAYER_POPUP);
return (struct lab_layer_popup *)node_descriptor->data;
}
@ -67,24 +63,28 @@ node_menuitem_from_node(struct wlr_scene_node *wlr_scene_node)
{
assert(wlr_scene_node->data);
struct node_descriptor *node_descriptor = wlr_scene_node->data;
assert(node_descriptor->type == LAB_NODE_DESC_MENUITEM);
assert(node_descriptor->type == LAB_NODE_MENUITEM);
return (struct menuitem *)node_descriptor->data;
}
struct ssd_part *
node_ssd_part_from_node(struct wlr_scene_node *wlr_scene_node)
{
assert(wlr_scene_node->data);
struct node_descriptor *node_descriptor = wlr_scene_node->data;
assert(node_descriptor->type == LAB_NODE_DESC_SSD_PART);
return (struct ssd_part *)node_descriptor->data;
}
struct scaled_buffer *
node_scaled_buffer_from_node(struct wlr_scene_node *wlr_scene_node)
{
assert(wlr_scene_node->data);
struct node_descriptor *node_descriptor = wlr_scene_node->data;
assert(node_descriptor->type == LAB_NODE_DESC_SCALED_BUFFER);
assert(node_descriptor->type == LAB_NODE_SCALED_BUFFER);
return (struct scaled_buffer *)node_descriptor->data;
}
struct ssd_button *
node_try_ssd_button_from_node(struct wlr_scene_node *wlr_scene_node)
{
assert(wlr_scene_node->data);
struct node_descriptor *node_descriptor = wlr_scene_node->data;
if (node_type_contains(LAB_NODE_BUTTON, node_descriptor->type)) {
return (struct ssd_button *)node_descriptor->data;
}
return NULL;
}

View file

@ -511,17 +511,17 @@ handle_new_output(struct wl_listener *listener, void *data)
output->layer_tree[i] =
wlr_scene_tree_create(&server->scene->tree);
node_descriptor_create(&output->layer_tree[i]->node,
LAB_NODE_DESC_TREE, NULL);
LAB_NODE_TREE, /*view*/ NULL, /*data*/ NULL);
}
output->layer_popup_tree = wlr_scene_tree_create(&server->scene->tree);
node_descriptor_create(&output->layer_popup_tree->node,
LAB_NODE_DESC_TREE, NULL);
LAB_NODE_TREE, /*view*/ NULL, /*data*/ NULL);
output->osd_tree = wlr_scene_tree_create(&server->scene->tree);
node_descriptor_create(&output->osd_tree->node,
LAB_NODE_DESC_TREE, NULL);
LAB_NODE_TREE, /*view*/ NULL, /*data*/ NULL);
output->session_lock_tree = wlr_scene_tree_create(&server->scene->tree);
node_descriptor_create(&output->session_lock_tree->node,
LAB_NODE_DESC_TREE, NULL);
LAB_NODE_TREE, /*view*/ NULL, /*data*/ NULL);
/*
* Set the z-positions to achieve the following order (from top to

View file

@ -198,7 +198,7 @@ scaled_buffer_create(struct wlr_scene_tree *parent,
return NULL;
}
node_descriptor_create(&self->scene_buffer->node,
LAB_NODE_DESC_SCALED_BUFFER, self);
LAB_NODE_SCALED_BUFFER, /*view*/ NULL, self);
self->impl = impl;
/*

View file

@ -135,7 +135,7 @@ handle_new_surface(struct wl_listener *listener, void *data)
struct wlr_scene_tree *surface_tree =
wlr_scene_subsurface_tree_create(lock_output->tree, lock_surface->surface);
node_descriptor_create(&surface_tree->node,
LAB_NODE_DESC_SESSION_LOCK_SURFACE, NULL);
LAB_NODE_SESSION_LOCK_SURFACE, /*view*/ NULL, /*data*/ NULL);
lock_output->surface_destroy.notify = handle_surface_destroy;
wl_signal_add(&lock_surface->events.destroy, &lock_output->surface_destroy);

View file

@ -1,7 +1,7 @@
labwc_sources += files(
'resize-indicator.c',
'ssd.c',
'ssd-part.c',
'ssd-button.c',
'ssd-titlebar.c',
'ssd-border.c',
'ssd-extents.c',

View file

@ -7,55 +7,13 @@
#include "node.h"
#include "scaled-buffer/scaled-icon-buffer.h"
#include "scaled-buffer/scaled-img-buffer.h"
#include "ssd.h"
#include "ssd-internal.h"
/* Internal helpers */
static void
handle_node_destroy(struct wl_listener *listener, void *data)
{
struct ssd_part *part = wl_container_of(listener, part, node_destroy);
wl_list_remove(&part->node_destroy.link);
struct ssd_part_button *button = button_try_from_ssd_part(part);
if (button) {
wl_list_remove(&button->link);
}
free(part);
}
/* Internal API */
/*
* 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 lab_node_type type,
struct view *view, struct wlr_scene_node *node)
{
part->type = type;
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 *
attach_ssd_part(enum lab_node_type type, struct view *view,
struct wlr_scene_node *node)
{
assert(!node_type_contains(LAB_NODE_BUTTON, type));
struct ssd_part *part = znew(*part);
init_ssd_part(part, type, view, node);
return part;
}
struct ssd_part_button *
attach_ssd_part_button(struct wl_list *button_parts, enum lab_node_type type,
struct ssd_button *
attach_ssd_button(struct wl_list *button_parts, enum lab_node_type type,
struct wlr_scene_tree *parent,
struct lab_img *imgs[LAB_BS_ALL + 1],
int x, int y, struct view *view)
@ -64,8 +22,10 @@ attach_ssd_part_button(struct wl_list *button_parts, enum lab_node_type type,
wlr_scene_node_set_position(&root->node, x, y);
assert(node_type_contains(LAB_NODE_BUTTON, type));
struct ssd_part_button *button = znew(*button);
init_ssd_part(&button->base, type, view, &root->node);
struct ssd_button *button = znew(*button);
button->node = &root->node;
button->type = type;
node_descriptor_create(&root->node, type, view, button);
wl_list_append(button_parts, &button->link);
/* Hitbox */
@ -117,11 +77,9 @@ attach_ssd_part_button(struct wl_list *button_parts, enum lab_node_type type,
return button;
}
struct ssd_part_button *
button_try_from_ssd_part(struct ssd_part *part)
/* called from node descriptor destroy */
void ssd_button_free(struct ssd_button *button)
{
if (node_type_contains(LAB_NODE_BUTTON, part->type)) {
return (struct ssd_part_button *)part;
}
return NULL;
wl_list_remove(&button->link);
free(button);
}

View file

@ -34,7 +34,8 @@ ssd_titlebar_create(struct ssd *ssd)
int corner_width = ssd_get_corner_width();
ssd->titlebar.tree = wlr_scene_tree_create(ssd->tree);
attach_ssd_part(LAB_NODE_TITLEBAR, view, &ssd->titlebar.tree->node);
node_descriptor_create(&ssd->titlebar.tree->node,
LAB_NODE_TITLEBAR, view, /*data*/ NULL);
enum ssd_active_state active;
FOR_EACH_ACTIVE_STATE(active) {
@ -78,8 +79,8 @@ ssd_titlebar_create(struct ssd *ssd)
subtree->tree, theme->titlebar_height,
theme->window[active].titlebar_pattern);
assert(subtree->title);
attach_ssd_part(LAB_NODE_TITLE,
view, &subtree->title->scene_buffer->node);
node_descriptor_create(&subtree->title->scene_buffer->node,
LAB_NODE_TITLE, view, /*data*/ NULL);
/* Buttons */
struct title_button *b;
@ -94,7 +95,7 @@ ssd_titlebar_create(struct ssd *ssd)
wl_list_for_each(b, &rc.title_buttons_left, link) {
struct lab_img **imgs =
theme->window[active].button_imgs[b->type];
attach_ssd_part_button(&subtree->buttons_left, b->type, parent,
attach_ssd_button(&subtree->buttons_left, b->type, parent,
imgs, x, y, view);
x += theme->window_button_width + theme->window_button_spacing;
}
@ -104,7 +105,7 @@ ssd_titlebar_create(struct ssd *ssd)
x -= theme->window_button_width + theme->window_button_spacing;
struct lab_img **imgs =
theme->window[active].button_imgs[b->type];
attach_ssd_part_button(&subtree->buttons_right, b->type, parent,
attach_ssd_button(&subtree->buttons_right, b->type, parent,
imgs, x, y, view);
}
}
@ -134,7 +135,7 @@ ssd_titlebar_create(struct ssd *ssd)
}
static void
update_button_state(struct ssd_part_button *button, enum lab_button_state state,
update_button_state(struct ssd_button *button, enum lab_button_state state,
bool enable)
{
if (enable) {
@ -177,7 +178,7 @@ set_squared_corners(struct ssd *ssd, bool enable)
wlr_scene_node_set_enabled(&subtree->corner_right->node, !enable);
/* (Un)round the corner buttons */
struct ssd_part_button *button;
struct ssd_button *button;
wl_list_for_each(button, &subtree->buttons_left, link) {
update_button_state(button, LAB_BS_ROUNDED, !enable);
break;
@ -196,15 +197,15 @@ set_alt_button_icon(struct ssd *ssd, enum lab_node_type type, bool enable)
FOR_EACH_ACTIVE_STATE(active) {
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
struct ssd_part_button *button;
struct ssd_button *button;
wl_list_for_each(button, &subtree->buttons_left, link) {
if (button->base.type == type) {
if (button->type == type) {
update_button_state(button,
LAB_BS_TOGGLED, enable);
}
}
wl_list_for_each(button, &subtree->buttons_right, link) {
if (button->base.type == type) {
if (button->type == type) {
update_button_state(button,
LAB_BS_TOGGLED, enable);
}
@ -251,16 +252,16 @@ update_visible_buttons(struct ssd *ssd)
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
int button_count = 0;
struct ssd_part_button *button;
struct ssd_button *button;
wl_list_for_each(button, &subtree->buttons_left, link) {
wlr_scene_node_set_enabled(button->base.node,
wlr_scene_node_set_enabled(button->node,
button_count < button_count_left);
button_count++;
}
button_count = 0;
wl_list_for_each(button, &subtree->buttons_right, link) {
wlr_scene_node_set_enabled(button->base.node,
wlr_scene_node_set_enabled(button->node,
button_count < button_count_right);
button_count++;
}
@ -317,9 +318,9 @@ ssd_titlebar_update(struct ssd *ssd)
MAX(width - bg_offset * 2, 0), theme->titlebar_height);
x = theme->window_titlebar_padding_width;
struct ssd_part_button *button;
struct ssd_button *button;
wl_list_for_each(button, &subtree->buttons_left, link) {
wlr_scene_node_set_position(button->base.node, x, y);
wlr_scene_node_set_position(button->node, x, y);
x += theme->window_button_width + theme->window_button_spacing;
}
@ -330,7 +331,7 @@ ssd_titlebar_update(struct ssd *ssd)
x = width - theme->window_titlebar_padding_width + theme->window_button_spacing;
wl_list_for_each(button, &subtree->buttons_right, link) {
x -= theme->window_button_width + theme->window_button_spacing;
wlr_scene_node_set_position(button->base.node, x, y);
wlr_scene_node_set_position(button->node, x, y);
}
}
@ -419,14 +420,14 @@ get_title_offsets(struct ssd *ssd, int *offset_left, int *offset_right)
*offset_left = padding_width;
*offset_right = padding_width;
struct ssd_part_button *button;
struct ssd_button *button;
wl_list_for_each(button, &subtree->buttons_left, link) {
if (button->base.node->enabled) {
if (button->node->enabled) {
*offset_left += button_width + button_spacing;
}
}
wl_list_for_each(button, &subtree->buttons_right, link) {
if (button->base.node->enabled) {
if (button->node->enabled) {
*offset_right += button_width + button_spacing;
}
}
@ -494,17 +495,13 @@ ssd_update_title(struct ssd *ssd)
void
ssd_update_hovered_button(struct server *server, struct wlr_scene_node *node)
{
struct ssd_part_button *button = NULL;
struct ssd_button *button = NULL;
if (node && node->data) {
struct node_descriptor *desc = node->data;
if (desc->type == LAB_NODE_DESC_SSD_PART) {
button = button_try_from_ssd_part(
node_ssd_part_from_node(node));
if (button == server->hovered_button) {
/* Cursor is still on the same button */
return;
}
button = node_try_ssd_button_from_node(node);
if (button == server->hovered_button) {
/* Cursor is still on the same button */
return;
}
}

View file

@ -14,6 +14,7 @@
#include "common/scene-helpers.h"
#include "config/rcxml.h"
#include "labwc.h"
#include "node.h"
#include "ssd-internal.h"
#include "theme.h"
#include "view.h"
@ -145,7 +146,8 @@ ssd_create(struct view *view, bool active)
ssd->view = view;
ssd->tree = wlr_scene_tree_create(view->scene_tree);
attach_ssd_part(LAB_NODE_NONE, view, &ssd->tree->node);
node_descriptor_create(&ssd->tree->node,
LAB_NODE_NONE, view, /*data*/ NULL);
wlr_scene_node_lower_to_bottom(&ssd->tree->node);
ssd->titlebar.height = view->server->theme->titlebar_height;
ssd_shadow_create(ssd);
@ -265,7 +267,8 @@ ssd_destroy(struct ssd *ssd)
/* Maybe reset hover view */
struct view *view = ssd->view;
struct server *server = view->server;
if (server->hovered_button && server->hovered_button->base.view == view) {
if (server->hovered_button && node_view_from_node(
server->hovered_button->node) == view) {
server->hovered_button = NULL;
}
@ -343,18 +346,6 @@ ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable)
wlr_scene_rect_set_color(ssd->border.subtrees[SSD_ACTIVE].top, color);
}
enum lab_node_type
ssd_part_get_type(const struct ssd_part *part)
{
return part ? part->type : LAB_NODE_NONE;
}
struct view *
ssd_part_get_view(const struct ssd_part *part)
{
return part ? part->view : NULL;
}
bool
ssd_debug_is_root_node(const struct ssd *ssd, struct wlr_scene_node *node)
{

View file

@ -164,5 +164,5 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
wlr_popup->base->surface->data =
wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base);
node_descriptor_create(wlr_popup->base->surface->data,
LAB_NODE_DESC_XDG_POPUP, view);
LAB_NODE_XDG_POPUP, view, /*data*/ NULL);
}

View file

@ -1023,7 +1023,7 @@ handle_new_xdg_toplevel(struct wl_listener *listener, void *data)
}
view->content_tree = tree;
node_descriptor_create(&view->scene_tree->node,
LAB_NODE_DESC_VIEW, view);
LAB_NODE_VIEW, view, /*data*/ NULL);
/*
* The xdg_toplevel_decoration and kde_server_decoration protocols

View file

@ -1090,7 +1090,8 @@ xwayland_view_create(struct server *server,
view->workspace = server->workspaces.current;
view->scene_tree = wlr_scene_tree_create(view->workspace->tree);
node_descriptor_create(&view->scene_tree->node, LAB_NODE_DESC_VIEW, view);
node_descriptor_create(&view->scene_tree->node,
LAB_NODE_VIEW, view, /*data*/ NULL);
CONNECT_SIGNAL(xsurface, view, destroy);
CONNECT_SIGNAL(xsurface, view, request_minimize);