]> git.mdlowis.com Git - proto/labwc.git/commitdiff
src/ssd: Convert button node descriptors to struct ssd_button
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Wed, 8 Jun 2022 17:51:02 +0000 (19:51 +0200)
committerJohan Malm <johanmalm@users.noreply.github.com>
Thu, 9 Jun 2022 21:04:35 +0000 (22:04 +0100)
This allows for way easier button hover detection and future
features like toggling rounded corner buttons on maximize.

include/node.h
include/ssd.h
src/cursor.c
src/desktop.c
src/node.c
src/ssd/ssd.c
src/ssd/ssd_part.c
src/ssd/ssd_titlebar.c

index e8d6535bbd59d5e473ce8288ef0c05928938e8b8..3e0601a50d2e330adba9101da739e9c4a7ac15ac 100644 (file)
@@ -7,6 +7,7 @@ struct view;
 struct lab_layer_surface;
 struct lab_layer_popup;
 struct menuitem;
+struct ssd_button;
 
 enum node_descriptor_type {
        LAB_NODE_DESC_NODE = 0,
@@ -27,6 +28,10 @@ struct node_descriptor {
 
 /**
  * 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:
@@ -34,6 +39,8 @@ struct node_descriptor {
  *   - 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);
@@ -65,4 +72,11 @@ struct lab_layer_popup *node_layer_popup_from_node(
 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 */
index 0f9ff624623e17a60181d4898d4f2119edb34513..027dcc211f5437cf00572213219bf6976f9c0705 100644 (file)
@@ -54,6 +54,14 @@ struct wl_list;
 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 */
@@ -120,7 +128,6 @@ struct ssd_part {
 
 struct ssd_hover_state {
        struct view *view;
-       enum ssd_part_type type;
        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_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);
index 2527be9f9a387ac6de94fc9118f108642082974a..b248d083482361799b3a528b33dc10876e71ed83 100644 (file)
@@ -274,25 +274,8 @@ process_cursor_motion(struct server *server, uint32_t time)
                }
        }
 
-       /* 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 &&
index 30f3826436817d745e2ffa53a1ba90113e8e2815..9e16465e5a496e453c264b2dccef8d331367fdef 100644 (file)
@@ -296,8 +296,10 @@ desktop_node_and_view_at(struct server *server, double lx, double ly,
                        }
                        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 */
index 6386fc81c44aab34c3ba44f514085799af98b834..67c01a153f94e34a7af86d4dc5b2a63ed362cd1e 100644 (file)
@@ -43,8 +43,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
-               || node_descriptor->type == LAB_NODE_DESC_SSD_BUTTON);
+               || node_descriptor->type == LAB_NODE_DESC_XDG_POPUP);
        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);
        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;
+}
index 97e804c6e305eda1f10bb5cd66a356561bdadeb0..94dcf501e217e79eb7346d24fb8f43132d794595 100644 (file)
@@ -240,7 +240,6 @@ ssd_destroy(struct view *view)
        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;
        }
 
index 95c3ab70ef49c228d2e8649eb6b8dd84820f9146..d060f08fbf1c4034bb155e64bc2ccec39b03b1a5 100644 (file)
@@ -5,6 +5,36 @@
 #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)
 {
@@ -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_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 */
@@ -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);
 
        /* 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;
 }
 
index 6c27943f97ddc3bc40bc86a22359dc7e1cc59070..e741bf0652dbe817981236f64ab6914663ddf382 100644 (file)
@@ -8,6 +8,7 @@
 #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, \
@@ -271,52 +272,35 @@ ssd_update_title(struct view *view)
        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