labwc/src/ssd/ssd-button.c
John Lindgren f129571779 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.
2025-09-06 16:00:20 -04:00

85 lines
2.8 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
#include <assert.h>
#include "config/rcxml.h"
#include "common/list.h"
#include "common/mem.h"
#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 API */
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 wlr_scene_tree *root = wlr_scene_tree_create(parent);
wlr_scene_node_set_position(&root->node, x, y);
assert(node_type_contains(LAB_NODE_BUTTON, type));
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 */
float invisible[4] = { 0, 0, 0, 0 };
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;
int button_height = rc.theme->window_button_height;
/*
* Ensure a small amount of horizontal padding within the button
* area (2px on each side with the default 26px button width).
* A new theme setting could be added to configure this. Using
* an existing setting (padding.width or window.button.spacing)
* was considered, but these settings have distinct purposes
* already and are zero by default.
*/
int icon_padding = button_width / 10;
if (type == LAB_NODE_BUTTON_WINDOW_ICON) {
struct scaled_icon_buffer *icon_buffer =
scaled_icon_buffer_create(root, view->server,
button_width - 2 * icon_padding, button_height);
assert(icon_buffer);
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;
state_set <= LAB_BS_ALL; state_set++) {
if (!imgs[state_set]) {
continue;
}
struct scaled_img_buffer *img_buffer = scaled_img_buffer_create(
root, imgs[state_set], rc.theme->window_button_width,
rc.theme->window_button_height);
assert(img_buffer);
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 */
wlr_scene_node_set_enabled(
&button->img_buffers[LAB_BS_DEFAULT]->scene_buffer->node, true);
}
return button;
}
/* called from node descriptor destroy */
void ssd_button_free(struct ssd_button *button)
{
wl_list_remove(&button->link);
free(button);
}