struct lab_layer_surface;
struct lab_layer_popup;
struct menuitem;
+struct ssd_button;
enum node_descriptor_type {
LAB_NODE_DESC_NODE = 0,
/**
* 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
* @type: node descriptor type
* @data: struct to point to as follows:
* - 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_BUTTON struct ssd_button
*/
void node_descriptor_create(struct wlr_scene_node *scene_node,
enum node_descriptor_type type, void *data);
struct menuitem *node_menuitem_from_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 */
struct wlr_box;
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 wlr_scene_tree *tree;
struct wl_list parts; /* ssd_part::link */
struct ssd_hover_state {
struct view *view;
- enum ssd_part_type type;
struct wlr_scene_node *node;
};
void ssd_update_geometry(struct view *view);
void ssd_reload(struct view *view);
void ssd_destroy(struct view *view);
-/* Returns hover overlay node so it can be disabled later on */
-struct wlr_scene_node *ssd_button_hover_enable(
- struct view *view, enum ssd_part_type type);
+void ssd_update_button_hover(struct wlr_scene_node *node,
+ struct ssd_hover_state *hover_state);
/* Public SSD helpers */
enum ssd_part_type ssd_at(struct view *view, double lx, double ly);
}
}
- /* SSD button mouse-over */
- struct ssd_hover_state *hover = &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;
- }
+ /* TODO: ssd_hover_state should likely be located in server->seat */
+ ssd_update_button_hover(node, &server->ssd_hover_state);
if (server->seat.pressed.surface &&
server->seat.pressed.surface != surface &&
}
if (desc->type == LAB_NODE_DESC_SSD_BUTTON) {
/* Always return the top scene node for SSD buttons */
+ struct ssd_button *button = node_ssd_button_from_node(node);
*scene_node = node;
- goto has_view_data;
+ *view_area = button->type;
+ return button->view;
}
if (desc->type == LAB_NODE_DESC_LAYER_SURFACE) {
/* FIXME: we shouldn't have to set *view_area */
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
- || node_descriptor->type == LAB_NODE_DESC_SSD_BUTTON);
+ || node_descriptor->type == LAB_NODE_DESC_XDG_POPUP);
return (struct view *)node_descriptor->data;
}
assert(node_descriptor->type == LAB_NODE_DESC_MENUITEM);
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;
+}
hover_state = &view->server->ssd_hover_state;
if (hover_state->view == view) {
hover_state->view = NULL;
- hover_state->type = LAB_SSD_NONE;
hover_state->node = NULL;
}
#include "ssd.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 *
add_scene_part(struct wl_list *part_list, enum ssd_part_type type)
{
struct wlr_scene_tree *parent, float *bg_color,
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};
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, 0);
- node_descriptor_create(button_root->node, LAB_NODE_DESC_SSD_BUTTON, view);
/* 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);
/* Icon */
(rc.theme->title_height - icon_buffer->height) / 2);
/* Hover overlay */
- part = add_scene_rect(part_list, type, parent, BUTTON_WIDTH,
- rc.theme->title_height, 0, 0, hover_bg);
- wlr_scene_node_set_enabled(part->node, false);
-
+ hover = add_scene_rect(part_list, type, parent, BUTTON_WIDTH,
+ rc.theme->title_height, 0, 0, hover_bg)->node;
+ 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;
}
#include "theme.h"
#include "common/font.h"
#include "common/scene-helpers.h"
+#include "node.h"
#define FOR_EACH_STATE(view, tmp) FOR_EACH(tmp, \
&(view)->ssd.titlebar.active, \
ssd_update_title_positions(view);
}
-/*
- * Returns the wlr_scene_node for hover effect.
- * To disable the hover effect later on just call
- * wlr_scene_node_set_enabled(node, false).
- */
-struct wlr_scene_node *
-ssd_button_hover_enable(struct view *view, enum ssd_part_type type)
+void
+ssd_update_button_hover(struct wlr_scene_node *node,
+ struct ssd_hover_state *hover_state)
{
- if (!view->ssd.tree) {
- wlr_log(WLR_ERROR, "%s() for destroyed view", __func__);
- return NULL;
+ struct ssd_button *button = NULL;
+ if (!node || !node->data) {
+ goto disable_old_hover;
}
- assert(ssd_is_button(type));
- struct ssd_part *part;
- struct ssd_sub_tree *subtree;
- FOR_EACH_STATE(view, subtree) {
- if (subtree->tree->node.enabled) {
- /*
- * 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;
- }
- }
+ struct node_descriptor *desc = node->data;
+ if (desc->type == LAB_NODE_DESC_SSD_BUTTON) {
+ button = node_ssd_button_from_node(node);
+ if (button->hover == hover_state->node) {
+ /* Cursor is still on the same button */
+ return;
}
- } FOR_EACH_END
+ }
- wlr_log(WLR_ERROR, "hover enable failed to find button");
- return NULL;
+disable_old_hover:
+ 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