mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
src/ssd: Convert button node descriptors to struct ssd_button
This allows for way easier button hover detection and future features like toggling rounded corner buttons on maximize.
This commit is contained in:
parent
f1ada7e407
commit
ca9226a7a6
8 changed files with 103 additions and 74 deletions
|
|
@ -7,6 +7,7 @@ struct view;
|
||||||
struct lab_layer_surface;
|
struct lab_layer_surface;
|
||||||
struct lab_layer_popup;
|
struct lab_layer_popup;
|
||||||
struct menuitem;
|
struct menuitem;
|
||||||
|
struct ssd_button;
|
||||||
|
|
||||||
enum node_descriptor_type {
|
enum node_descriptor_type {
|
||||||
LAB_NODE_DESC_NODE = 0,
|
LAB_NODE_DESC_NODE = 0,
|
||||||
|
|
@ -27,6 +28,10 @@ struct node_descriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* node_descriptor_create - create node descriptor for wlr_scene_node user_data
|
* node_descriptor_create - create node descriptor for wlr_scene_node user_data
|
||||||
|
*
|
||||||
|
* The node_descriptor will be destroyed automatically
|
||||||
|
* once the scene_node it is attached to is destroyed.
|
||||||
|
*
|
||||||
* @scene_node: wlr_scene_node to attached node_descriptor to
|
* @scene_node: wlr_scene_node to attached node_descriptor to
|
||||||
* @type: node descriptor type
|
* @type: node descriptor type
|
||||||
* @data: struct to point to as follows:
|
* @data: struct to point to as follows:
|
||||||
|
|
@ -34,6 +39,8 @@ struct node_descriptor {
|
||||||
* - LAB_NODE_DESC_XDG_POPUP struct view
|
* - LAB_NODE_DESC_XDG_POPUP struct view
|
||||||
* - LAB_NODE_DESC_LAYER_SURFACE struct lab_layer_surface
|
* - LAB_NODE_DESC_LAYER_SURFACE struct lab_layer_surface
|
||||||
* - LAB_NODE_DESC_LAYER_POPUP struct lab_layer_popup
|
* - LAB_NODE_DESC_LAYER_POPUP struct lab_layer_popup
|
||||||
|
* - LAB_NODE_DESC_MENUITEM struct menuitem
|
||||||
|
* - LAB_NODE_DESC_SSD_BUTTON struct ssd_button
|
||||||
*/
|
*/
|
||||||
void node_descriptor_create(struct wlr_scene_node *scene_node,
|
void node_descriptor_create(struct wlr_scene_node *scene_node,
|
||||||
enum node_descriptor_type type, void *data);
|
enum node_descriptor_type type, void *data);
|
||||||
|
|
@ -65,4 +72,11 @@ struct lab_layer_popup *node_layer_popup_from_node(
|
||||||
struct menuitem *node_menuitem_from_node(
|
struct menuitem *node_menuitem_from_node(
|
||||||
struct wlr_scene_node *wlr_scene_node);
|
struct wlr_scene_node *wlr_scene_node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* node_ssd_button_from_node - return ssd_button struct from node
|
||||||
|
* @wlr_scene_node: wlr_scene_node from which to return data
|
||||||
|
*/
|
||||||
|
struct ssd_button *node_ssd_button_from_node(
|
||||||
|
struct wlr_scene_node *wlr_scene_node);
|
||||||
|
|
||||||
#endif /* __LABWC_NODE_DESCRIPTOR_H */
|
#endif /* __LABWC_NODE_DESCRIPTOR_H */
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,14 @@ struct wl_list;
|
||||||
struct wlr_box;
|
struct wlr_box;
|
||||||
struct wlr_scene_tree;
|
struct wlr_scene_tree;
|
||||||
|
|
||||||
|
struct ssd_button {
|
||||||
|
struct view *view;
|
||||||
|
enum ssd_part_type type;
|
||||||
|
struct wlr_scene_node *hover;
|
||||||
|
|
||||||
|
struct wl_listener destroy;
|
||||||
|
};
|
||||||
|
|
||||||
struct ssd_sub_tree {
|
struct ssd_sub_tree {
|
||||||
struct wlr_scene_tree *tree;
|
struct wlr_scene_tree *tree;
|
||||||
struct wl_list parts; /* ssd_part::link */
|
struct wl_list parts; /* ssd_part::link */
|
||||||
|
|
@ -120,7 +128,6 @@ struct ssd_part {
|
||||||
|
|
||||||
struct ssd_hover_state {
|
struct ssd_hover_state {
|
||||||
struct view *view;
|
struct view *view;
|
||||||
enum ssd_part_type type;
|
|
||||||
struct wlr_scene_node *node;
|
struct wlr_scene_node *node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -132,9 +139,8 @@ void ssd_update_title(struct view *view);
|
||||||
void ssd_update_geometry(struct view *view);
|
void ssd_update_geometry(struct view *view);
|
||||||
void ssd_reload(struct view *view);
|
void ssd_reload(struct view *view);
|
||||||
void ssd_destroy(struct view *view);
|
void ssd_destroy(struct view *view);
|
||||||
/* Returns hover overlay node so it can be disabled later on */
|
void ssd_update_button_hover(struct wlr_scene_node *node,
|
||||||
struct wlr_scene_node *ssd_button_hover_enable(
|
struct ssd_hover_state *hover_state);
|
||||||
struct view *view, enum ssd_part_type type);
|
|
||||||
|
|
||||||
/* Public SSD helpers */
|
/* Public SSD helpers */
|
||||||
enum ssd_part_type ssd_at(struct view *view, double lx, double ly);
|
enum ssd_part_type ssd_at(struct view *view, double lx, double ly);
|
||||||
|
|
|
||||||
21
src/cursor.c
21
src/cursor.c
|
|
@ -274,25 +274,8 @@ process_cursor_motion(struct server *server, uint32_t time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SSD button mouse-over */
|
/* TODO: ssd_hover_state should likely be located in server->seat */
|
||||||
struct ssd_hover_state *hover = &server->ssd_hover_state;
|
ssd_update_button_hover(node, &server->ssd_hover_state);
|
||||||
if (ssd_is_button(view_area)) {
|
|
||||||
/* Cursor entered new button area */
|
|
||||||
if (hover->view != view || hover->type != view_area) {
|
|
||||||
if (hover->node) {
|
|
||||||
wlr_scene_node_set_enabled(hover->node, false);
|
|
||||||
}
|
|
||||||
hover->view = view;
|
|
||||||
hover->type = view_area;
|
|
||||||
hover->node = ssd_button_hover_enable(view, view_area);
|
|
||||||
}
|
|
||||||
} else if (hover->node) {
|
|
||||||
/* Cursor left button area */
|
|
||||||
wlr_scene_node_set_enabled(hover->node, false);
|
|
||||||
hover->view = NULL;
|
|
||||||
hover->type = LAB_SSD_NONE;
|
|
||||||
hover->node = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server->seat.pressed.surface &&
|
if (server->seat.pressed.surface &&
|
||||||
server->seat.pressed.surface != surface &&
|
server->seat.pressed.surface != surface &&
|
||||||
|
|
|
||||||
|
|
@ -296,8 +296,10 @@ desktop_node_and_view_at(struct server *server, double lx, double ly,
|
||||||
}
|
}
|
||||||
if (desc->type == LAB_NODE_DESC_SSD_BUTTON) {
|
if (desc->type == LAB_NODE_DESC_SSD_BUTTON) {
|
||||||
/* Always return the top scene node for SSD buttons */
|
/* Always return the top scene node for SSD buttons */
|
||||||
|
struct ssd_button *button = node_ssd_button_from_node(node);
|
||||||
*scene_node = node;
|
*scene_node = node;
|
||||||
goto has_view_data;
|
*view_area = button->type;
|
||||||
|
return button->view;
|
||||||
}
|
}
|
||||||
if (desc->type == LAB_NODE_DESC_LAYER_SURFACE) {
|
if (desc->type == LAB_NODE_DESC_LAYER_SURFACE) {
|
||||||
/* FIXME: we shouldn't have to set *view_area */
|
/* FIXME: we shouldn't have to set *view_area */
|
||||||
|
|
|
||||||
12
src/node.c
12
src/node.c
|
|
@ -43,8 +43,7 @@ node_view_from_node(struct wlr_scene_node *wlr_scene_node)
|
||||||
assert(wlr_scene_node->data);
|
assert(wlr_scene_node->data);
|
||||||
struct node_descriptor *node_descriptor = wlr_scene_node->data;
|
struct node_descriptor *node_descriptor = wlr_scene_node->data;
|
||||||
assert(node_descriptor->type == LAB_NODE_DESC_VIEW
|
assert(node_descriptor->type == LAB_NODE_DESC_VIEW
|
||||||
|| node_descriptor->type == LAB_NODE_DESC_XDG_POPUP
|
|| node_descriptor->type == LAB_NODE_DESC_XDG_POPUP);
|
||||||
|| node_descriptor->type == LAB_NODE_DESC_SSD_BUTTON);
|
|
||||||
return (struct view *)node_descriptor->data;
|
return (struct view *)node_descriptor->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,3 +73,12 @@ node_menuitem_from_node(struct wlr_scene_node *wlr_scene_node)
|
||||||
assert(node_descriptor->type == LAB_NODE_DESC_MENUITEM);
|
assert(node_descriptor->type == LAB_NODE_DESC_MENUITEM);
|
||||||
return (struct menuitem *)node_descriptor->data;
|
return (struct menuitem *)node_descriptor->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ssd_button *
|
||||||
|
node_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;
|
||||||
|
assert(node_descriptor->type == LAB_NODE_DESC_SSD_BUTTON);
|
||||||
|
return (struct ssd_button *)node_descriptor->data;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,6 @@ ssd_destroy(struct view *view)
|
||||||
hover_state = &view->server->ssd_hover_state;
|
hover_state = &view->server->ssd_hover_state;
|
||||||
if (hover_state->view == view) {
|
if (hover_state->view == view) {
|
||||||
hover_state->view = NULL;
|
hover_state->view = NULL;
|
||||||
hover_state->type = LAB_SSD_NONE;
|
|
||||||
hover_state->node = NULL;
|
hover_state->node = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,36 @@
|
||||||
#include "ssd.h"
|
#include "ssd.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
|
||||||
|
/* Internal helpers */
|
||||||
|
static void
|
||||||
|
ssd_button_destroy_notify(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct ssd_button *button = wl_container_of(listener, button, destroy);
|
||||||
|
wl_list_remove(&button->destroy.link);
|
||||||
|
free(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 = calloc(1, sizeof(struct ssd_button));
|
||||||
|
|
||||||
|
/* Let it destroy automatically when the scene node destroys */
|
||||||
|
button->destroy.notify = ssd_button_destroy_notify;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Internal API */
|
||||||
struct ssd_part *
|
struct ssd_part *
|
||||||
add_scene_part(struct wl_list *part_list, enum ssd_part_type type)
|
add_scene_part(struct wl_list *part_list, enum ssd_part_type type)
|
||||||
{
|
{
|
||||||
|
|
@ -85,17 +115,16 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
struct wlr_scene_tree *parent, float *bg_color,
|
struct wlr_scene_tree *parent, float *bg_color,
|
||||||
struct wlr_buffer *icon_buffer, int x, struct view *view)
|
struct wlr_buffer *icon_buffer, int x, struct view *view)
|
||||||
{
|
{
|
||||||
struct ssd_part *part;
|
struct wlr_scene_node *hover;
|
||||||
float hover_bg[4] = {0.15f, 0.15f, 0.15f, 0.3f};
|
float hover_bg[4] = {0.15f, 0.15f, 0.15f, 0.3f};
|
||||||
|
|
||||||
struct ssd_part *button_root = add_scene_part(part_list, type);
|
struct ssd_part *button_root = add_scene_part(part_list, type);
|
||||||
parent = wlr_scene_tree_create(parent);
|
parent = wlr_scene_tree_create(parent);
|
||||||
button_root->node = &parent->node;
|
button_root->node = &parent->node;
|
||||||
wlr_scene_node_set_position(button_root->node, x, 0);
|
wlr_scene_node_set_position(button_root->node, x, 0);
|
||||||
node_descriptor_create(button_root->node, LAB_NODE_DESC_SSD_BUTTON, view);
|
|
||||||
|
|
||||||
/* Background */
|
/* Background */
|
||||||
part = add_scene_rect(part_list, type, parent,
|
add_scene_rect(part_list, type, parent,
|
||||||
BUTTON_WIDTH, rc.theme->title_height, 0, 0, bg_color);
|
BUTTON_WIDTH, rc.theme->title_height, 0, 0, bg_color);
|
||||||
|
|
||||||
/* Icon */
|
/* Icon */
|
||||||
|
|
@ -104,10 +133,14 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
(rc.theme->title_height - icon_buffer->height) / 2);
|
(rc.theme->title_height - icon_buffer->height) / 2);
|
||||||
|
|
||||||
/* Hover overlay */
|
/* Hover overlay */
|
||||||
part = add_scene_rect(part_list, type, parent, BUTTON_WIDTH,
|
hover = add_scene_rect(part_list, type, parent, BUTTON_WIDTH,
|
||||||
rc.theme->title_height, 0, 0, hover_bg);
|
rc.theme->title_height, 0, 0, hover_bg)->node;
|
||||||
wlr_scene_node_set_enabled(part->node, false);
|
wlr_scene_node_set_enabled(hover, false);
|
||||||
|
|
||||||
|
struct ssd_button *button = ssd_button_descriptor_create(button_root->node);
|
||||||
|
button->type = type;
|
||||||
|
button->view = view;
|
||||||
|
button->hover = hover;
|
||||||
return button_root;
|
return button_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "common/font.h"
|
#include "common/font.h"
|
||||||
#include "common/scene-helpers.h"
|
#include "common/scene-helpers.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
#define FOR_EACH_STATE(view, tmp) FOR_EACH(tmp, \
|
#define FOR_EACH_STATE(view, tmp) FOR_EACH(tmp, \
|
||||||
&(view)->ssd.titlebar.active, \
|
&(view)->ssd.titlebar.active, \
|
||||||
|
|
@ -271,52 +272,35 @@ ssd_update_title(struct view *view)
|
||||||
ssd_update_title_positions(view);
|
ssd_update_title_positions(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void
|
||||||
* Returns the wlr_scene_node for hover effect.
|
ssd_update_button_hover(struct wlr_scene_node *node,
|
||||||
* To disable the hover effect later on just call
|
struct ssd_hover_state *hover_state)
|
||||||
* wlr_scene_node_set_enabled(node, false).
|
|
||||||
*/
|
|
||||||
struct wlr_scene_node *
|
|
||||||
ssd_button_hover_enable(struct view *view, enum ssd_part_type type)
|
|
||||||
{
|
{
|
||||||
if (!view->ssd.tree) {
|
struct ssd_button *button = NULL;
|
||||||
wlr_log(WLR_ERROR, "%s() for destroyed view", __func__);
|
if (!node || !node->data) {
|
||||||
return NULL;
|
goto disable_old_hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(ssd_is_button(type));
|
struct node_descriptor *desc = node->data;
|
||||||
struct ssd_part *part;
|
if (desc->type == LAB_NODE_DESC_SSD_BUTTON) {
|
||||||
struct ssd_sub_tree *subtree;
|
button = node_ssd_button_from_node(node);
|
||||||
FOR_EACH_STATE(view, subtree) {
|
if (button->hover == hover_state->node) {
|
||||||
if (subtree->tree->node.enabled) {
|
/* Cursor is still on the same button */
|
||||||
/*
|
return;
|
||||||
* TODO: This function makes too many magic assumptions:
|
|
||||||
* - It expects the returned part to be the tree for the button
|
|
||||||
* - It expects the last node in that tree to be the hover overlay
|
|
||||||
*
|
|
||||||
* Both assumptions are valid as long as ssd_parts.c isn't changing
|
|
||||||
* the way a button is created but this cries for introducing bugs
|
|
||||||
* in the future if the button creation process or ssd_get_part()
|
|
||||||
* lookup routine would ever change.
|
|
||||||
*/
|
|
||||||
part = ssd_get_part(&subtree->parts, type);
|
|
||||||
if (!part) {
|
|
||||||
wlr_log(WLR_ERROR, "hover enable failed to find button");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
struct wlr_scene_node *child;
|
|
||||||
struct wlr_scene_tree *button = lab_scene_tree_from_node(part->node);
|
|
||||||
wl_list_for_each_reverse(child, &button->children, link) {
|
|
||||||
if (child->type == WLR_SCENE_NODE_RECT) {
|
|
||||||
wlr_scene_node_set_enabled(child, true);
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} FOR_EACH_END
|
}
|
||||||
|
|
||||||
wlr_log(WLR_ERROR, "hover enable failed to find button");
|
disable_old_hover:
|
||||||
return NULL;
|
if (hover_state->node) {
|
||||||
|
wlr_scene_node_set_enabled(hover_state->node, false);
|
||||||
|
hover_state->view = NULL;
|
||||||
|
hover_state->node = NULL;
|
||||||
|
}
|
||||||
|
if (button) {
|
||||||
|
wlr_scene_node_set_enabled(button->hover, true);
|
||||||
|
hover_state->view = button->view;
|
||||||
|
hover_state->node = button->hover;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef FOR_EACH_STATE
|
#undef FOR_EACH_STATE
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue