diff --git a/include/node.h b/include/node.h index 07e6aff4..e8d6535b 100644 --- a/include/node.h +++ b/include/node.h @@ -16,6 +16,7 @@ enum node_descriptor_type { LAB_NODE_DESC_LAYER_POPUP, LAB_NODE_DESC_MENUITEM, LAB_NODE_DESC_TREE, + LAB_NODE_DESC_SSD_BUTTON, }; struct node_descriptor { diff --git a/include/ssd.h b/include/ssd.h index 69b82c99..0f9ff624 100644 --- a/include/ssd.h +++ b/include/ssd.h @@ -158,11 +158,12 @@ struct ssd_part *add_scene_buffer( struct ssd_part *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 wlr_buffer *icon_buffer, int x, struct view *view); struct ssd_part *add_scene_button_corner( struct wl_list *part_list, enum ssd_part_type type, - struct wlr_scene_tree *parent, struct wlr_buffer *corner_buffer, - struct wlr_buffer *icon_buffer, int x); + enum ssd_part_type corner_type, struct wlr_scene_tree *parent, + struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer, + int x, struct view *view); /* SSD internal helpers */ struct ssd_part *ssd_get_part( diff --git a/src/desktop.c b/src/desktop.c index 3ad77207..30f38264 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -294,6 +294,11 @@ desktop_node_and_view_at(struct server *server, double lx, double ly, if (desc->type == LAB_NODE_DESC_XDG_POPUP) { goto has_view_data; } + if (desc->type == LAB_NODE_DESC_SSD_BUTTON) { + /* Always return the top scene node for SSD buttons */ + *scene_node = node; + goto has_view_data; + } if (desc->type == LAB_NODE_DESC_LAYER_SURFACE) { /* FIXME: we shouldn't have to set *view_area */ *view_area = LAB_SSD_CLIENT; diff --git a/src/node.c b/src/node.c index f667d82a..6386fc81 100644 --- a/src/node.c +++ b/src/node.c @@ -43,7 +43,8 @@ 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_XDG_POPUP + || node_descriptor->type == LAB_NODE_DESC_SSD_BUTTON); return (struct view *)node_descriptor->data; } diff --git a/src/ssd/ssd_part.c b/src/ssd/ssd_part.c index ddd09014..95c3ab70 100644 --- a/src/ssd/ssd_part.c +++ b/src/ssd/ssd_part.c @@ -3,6 +3,7 @@ #include #include "labwc.h" #include "ssd.h" +#include "node.h" struct ssd_part * add_scene_part(struct wl_list *part_list, enum ssd_part_type type) @@ -45,70 +46,69 @@ add_scene_buffer(struct wl_list *list, enum ssd_part_type type, return part; } -static void -finish_scene_button(struct wl_list *part_list, enum ssd_part_type type, - struct wlr_scene_tree *parent, struct wlr_buffer *icon_buffer) +struct ssd_part * +add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type, + enum ssd_part_type corner_type, struct wlr_scene_tree *parent, + struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer, + int x, struct view *view) { + int offset_x; + float invisible[4] = { 0, 0, 0, 0 }; + + if (corner_type == LAB_SSD_PART_CORNER_TOP_LEFT) { + offset_x = rc.theme->border_width; + } else if (corner_type == LAB_SSD_PART_CORNER_TOP_RIGHT) { + offset_x = 0; + } else { + assert(false && "invalid corner button type"); + } + + struct ssd_part *button_root = add_scene_part(part_list, corner_type); + parent = wlr_scene_tree_create(parent); + button_root->node = &parent->node; + wlr_scene_node_set_position(button_root->node, x, 0); + + /* + * Background, x and y adjusted for border_width which is + * already included in rendered theme.c / corner_buffer + */ + add_scene_buffer(part_list, corner_type, parent, corner_buffer, + -offset_x, -rc.theme->border_width); + + /* Finally just put a usual theme button on top, using an invisible hitbox */ + add_scene_button(part_list, type, parent, invisible, icon_buffer, 0, view); + return button_root; +} + +struct ssd_part * +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; 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, + BUTTON_WIDTH, rc.theme->title_height, 0, 0, bg_color); + /* Icon */ add_scene_buffer(part_list, type, parent, icon_buffer, (BUTTON_WIDTH - icon_buffer->width) / 2, (rc.theme->title_height - icon_buffer->height) / 2); /* Hover overlay */ - struct ssd_part *hover_part; - hover_part = add_scene_rect(part_list, type, parent, BUTTON_WIDTH, + part = add_scene_rect(part_list, type, parent, BUTTON_WIDTH, rc.theme->title_height, 0, 0, hover_bg); - wlr_scene_node_set_enabled(hover_part->node, false); -} + wlr_scene_node_set_enabled(part->node, false); -struct ssd_part * -add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type, - struct wlr_scene_tree *parent, struct wlr_buffer *corner_buffer, - struct wlr_buffer *icon_buffer, int x) -{ - 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); - - int offset_x; - if (type == LAB_SSD_BUTTON_WINDOW_MENU) { - offset_x = rc.theme->border_width; - } else if (type == LAB_SSD_BUTTON_CLOSE) { - offset_x = 0; - } else { - assert(false && "invalid corner button type"); - } - - struct ssd_part *part; - /* - * Background, y adjusted for border_width which is - * already included in rendered theme.c / corner_buffer - */ - part = add_scene_buffer(part_list, type, parent, corner_buffer, - -offset_x, -rc.theme->border_width); - finish_scene_button(part_list, type, parent, icon_buffer); - return part; -} - -struct ssd_part * -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 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); - - struct ssd_part *part; - /* Background */ - part = add_scene_rect(part_list, type, parent, - BUTTON_WIDTH, rc.theme->title_height, 0, 0, bg_color); - finish_scene_button(part_list, type, parent, icon_buffer); - return part; + return button_root; } struct ssd_part * diff --git a/src/ssd/ssd_titlebar.c b/src/ssd/ssd_titlebar.c index 80aed120..6c27943f 100644 --- a/src/ssd/ssd_titlebar.c +++ b/src/ssd/ssd_titlebar.c @@ -46,18 +46,19 @@ ssd_titlebar_create(struct view *view) width - BUTTON_WIDTH * BUTTON_COUNT, theme->title_height, BUTTON_WIDTH, 0, color); /* Buttons */ - add_scene_button_corner(&subtree->parts, LAB_SSD_BUTTON_WINDOW_MENU, - parent, corner_top_left, - &theme->xbm_menu_active_unpressed->base, 0); + add_scene_button_corner(&subtree->parts, + LAB_SSD_BUTTON_WINDOW_MENU, LAB_SSD_PART_CORNER_TOP_LEFT, parent, + corner_top_left, &theme->xbm_menu_active_unpressed->base, 0, view); add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent, color, &theme->xbm_iconify_active_unpressed->base, - width - BUTTON_WIDTH * 3); + width - BUTTON_WIDTH * 3, view); add_scene_button(&subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent, color, &theme->xbm_maximize_active_unpressed->base, - width - BUTTON_WIDTH * 2); - add_scene_button_corner(&subtree->parts, LAB_SSD_BUTTON_CLOSE, parent, + width - BUTTON_WIDTH * 2, view); + add_scene_button_corner(&subtree->parts, + LAB_SSD_BUTTON_CLOSE, LAB_SSD_PART_CORNER_TOP_RIGHT, parent, corner_top_right, &theme->xbm_close_active_unpressed->base, - width - BUTTON_WIDTH * 1); + width - BUTTON_WIDTH * 1, view); } FOR_EACH_END ssd_update_title(view); } @@ -100,7 +101,7 @@ ssd_titlebar_update(struct view *view) width - BUTTON_WIDTH * 2, 0); } continue; - case LAB_SSD_BUTTON_CLOSE: + case LAB_SSD_PART_CORNER_TOP_RIGHT: if (is_direct_child(part->node, subtree)) { wlr_scene_node_set_position(part->node, width - BUTTON_WIDTH * 1, 0);