From 39ff873d5b368434671ecddb0aae64fb3049ca07 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Sun, 18 Aug 2024 10:49:18 +0200 Subject: [PATCH] ssd: apply title layout --- include/ssd.h | 1 - src/snap.c | 3 +- src/ssd/ssd-titlebar.c | 173 ++++++++++++++++++++++++++--------------- src/ssd/ssd.c | 7 +- src/theme.c | 28 +++++-- src/view.c | 3 +- src/xwayland.c | 3 +- 7 files changed, 140 insertions(+), 78 deletions(-) diff --git a/include/ssd.h b/include/ssd.h index 19b22450..7a2e7a77 100644 --- a/include/ssd.h +++ b/include/ssd.h @@ -5,7 +5,6 @@ #include #include "common/border.h" -#define SSD_BUTTON_COUNT 4 #define SSD_EXTENDED_AREA 8 /* diff --git a/src/snap.c b/src/snap.c index 5f1dbff8..3f188f6f 100644 --- a/src/snap.c +++ b/src/snap.c @@ -220,7 +220,8 @@ snap_shrink_to_next_edge(struct view *view, *geo = view->pending; uint32_t resize_edges; - int min_view_width = rc.theme->window_button_width * SSD_BUTTON_COUNT; + int min_view_width = rc.theme->window_button_width * ( + wl_list_length(&rc.title_buttons_left) + wl_list_length(&rc.title_buttons_right)); /* * First shrink the view along the relevant edge. The maximum shrink diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index ba4dc2bf..7326a707 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -99,24 +99,82 @@ ssd_titlebar_create(struct ssd *ssd) -rc.theme->border_width); /* Buttons */ - add_scene_button(&subtree->parts, LAB_SSD_BUTTON_WINDOW_MENU, parent, - menu_button_unpressed, menu_button_hover, 0, view); - add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent, - iconify_button_unpressed, iconify_button_hover, - width - theme->window_button_width * 3, view); + int x = 0; + struct ssd_part *btn_max_root; + struct ssd_button *btn_max; + struct title_button *b; + wl_list_for_each(b, &rc.title_buttons_left, link) { + switch (b->type) { + case LAB_SSD_BUTTON_WINDOW_MENU: + add_scene_button(&subtree->parts, LAB_SSD_BUTTON_WINDOW_MENU, + parent, menu_button_unpressed, menu_button_hover, x, + view); + x += theme->window_button_width; + continue; + case LAB_SSD_BUTTON_ICONIFY: + add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent, + iconify_button_unpressed, iconify_button_hover, x, + view); + x += theme->window_button_width; + continue; + case LAB_SSD_BUTTON_MAXIMIZE: + /* Maximize button has an alternate state when maximized */ + btn_max_root = add_scene_button( + &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent, + maximize_button_unpressed, maximize_button_hover, x, view); + btn_max = node_ssd_button_from_node(btn_max_root->node); + add_toggled_icon(btn_max, &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, + restore_button_unpressed, restore_button_hover); + x += theme->window_button_width; + continue; + case LAB_SSD_BUTTON_CLOSE: + add_scene_button(&subtree->parts, LAB_SSD_BUTTON_CLOSE, parent, + close_button_unpressed, close_button_hover, x, view); + x += theme->window_button_width; + continue; + default: + assert(false && "invalid titlebar part"); + wlr_log(WLR_ERROR, "invalid titlebar type"); + abort(); + } + } - /* Maximize button has an alternate state when maximized */ - struct ssd_part *btn_max_root = add_scene_button( - &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent, - maximize_button_unpressed, maximize_button_hover, - width - theme->window_button_width * 2, view); - struct ssd_button *btn_max = node_ssd_button_from_node(btn_max_root->node); - add_toggled_icon(btn_max, &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, - restore_button_unpressed, restore_button_hover); - - add_scene_button(&subtree->parts, LAB_SSD_BUTTON_CLOSE, parent, - close_button_unpressed, close_button_hover, - width - theme->window_button_width * 1, view); + x = width - theme->window_button_width; + wl_list_for_each_reverse(b, &rc.title_buttons_right, link) { + switch (b->type) { + case LAB_SSD_BUTTON_WINDOW_MENU: + add_scene_button(&subtree->parts, LAB_SSD_BUTTON_WINDOW_MENU, + parent, menu_button_unpressed, menu_button_hover, x, + view); + x -= theme->window_button_width; + continue; + case LAB_SSD_BUTTON_ICONIFY: + add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent, + iconify_button_unpressed, iconify_button_hover, x, + view); + x -= theme->window_button_width; + continue; + case LAB_SSD_BUTTON_MAXIMIZE: + /* Maximize button has an alternate state when maximized */ + btn_max_root = add_scene_button( + &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent, + maximize_button_unpressed, maximize_button_hover, x, view); + btn_max = node_ssd_button_from_node(btn_max_root->node); + add_toggled_icon(btn_max, &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, + restore_button_unpressed, restore_button_hover); + x -= theme->window_button_width; + continue; + case LAB_SSD_BUTTON_CLOSE: + add_scene_button(&subtree->parts, LAB_SSD_BUTTON_CLOSE, parent, + close_button_unpressed, close_button_hover, x, view); + x -= theme->window_button_width; + continue; + default: + assert(false && "invalid titlebar part"); + wlr_log(WLR_ERROR, "invalid titlebar type"); + abort(); + } + } } FOR_EACH_END ssd_update_title(ssd); @@ -133,12 +191,6 @@ ssd_titlebar_create(struct ssd *ssd) } } -static bool -is_direct_child(struct wlr_scene_node *node, struct ssd_sub_tree *subtree) -{ - return node->parent == subtree->tree; -} - static void set_squared_corners(struct ssd *ssd, bool enable) { @@ -173,6 +225,10 @@ set_maximize_alt_icon(struct ssd *ssd, bool enable) FOR_EACH_STATE(ssd, subtree) { part = ssd_get_part(&subtree->parts, LAB_SSD_BUTTON_MAXIMIZE); + if (!part) { + return; + } + button = node_ssd_button_from_node(part->node); if (button->toggled) { @@ -212,45 +268,31 @@ ssd_titlebar_update(struct ssd *ssd) return; } + int x; struct ssd_part *part; struct ssd_sub_tree *subtree; + struct title_button *b; int bg_offset = maximized || tiled_not_maximized ? 0 : theme->window_button_width; FOR_EACH_STATE(ssd, subtree) { - wl_list_for_each(part, &subtree->parts, link) { - switch (part->type) { - case LAB_SSD_PART_TITLEBAR: - wlr_scene_rect_set_size( - wlr_scene_rect_from_node(part->node), - width - bg_offset * 2, theme->title_height); - continue; - case LAB_SSD_BUTTON_ICONIFY: - if (is_direct_child(part->node, subtree)) { - wlr_scene_node_set_position(part->node, - width - theme->window_button_width * 3, 0); - } - continue; - case LAB_SSD_BUTTON_MAXIMIZE: - if (is_direct_child(part->node, subtree)) { - wlr_scene_node_set_position(part->node, - width - theme->window_button_width * 2, 0); - } - continue; - case LAB_SSD_BUTTON_CLOSE: - if (is_direct_child(part->node, subtree)) { - wlr_scene_node_set_position(part->node, - width - theme->window_button_width * 1, 0); - } - continue; - case LAB_SSD_PART_CORNER_TOP_RIGHT: - if (is_direct_child(part->node, subtree)) { - wlr_scene_node_set_position(part->node, - width - theme->window_button_width * 1, - -rc.theme->border_width); - } - continue; - default: - continue; - } + part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR); + wlr_scene_rect_set_size( + wlr_scene_rect_from_node(part->node), + width - bg_offset * 2, theme->title_height); + + x = 0; + wl_list_for_each(b, &rc.title_buttons_left, link) { + part = ssd_get_part(&subtree->parts, b->type); + wlr_scene_node_set_position(part->node, x, 0); + x += theme->window_button_width; + } + + x = width - theme->window_button_width; + part = ssd_get_part(&subtree->parts, LAB_SSD_PART_CORNER_TOP_RIGHT); + wlr_scene_node_set_position(part->node, x, -rc.theme->border_width); + wl_list_for_each_reverse(b, &rc.title_buttons_right, link) { + part = ssd_get_part(&subtree->parts, b->type); + wlr_scene_node_set_position(part->node, x, 0); + x -= theme->window_button_width; } } FOR_EACH_END ssd_update_title(ssd); @@ -297,7 +339,9 @@ ssd_update_title_positions(struct ssd *ssd) struct view *view = ssd->view; struct theme *theme = view->server->theme; int width = view->current.width; - int title_bg_width = width - theme->window_button_width * SSD_BUTTON_COUNT; + int offset_left = theme->window_button_width * wl_list_length(&rc.title_buttons_left); + int offset_right = theme->window_button_width * wl_list_length(&rc.title_buttons_right); + int title_bg_width = width - offset_left - offset_right; int x, y; int buffer_height, buffer_width; @@ -313,7 +357,7 @@ ssd_update_title_positions(struct ssd *ssd) buffer_width = part->buffer ? part->buffer->width : 0; buffer_height = part->buffer ? part->buffer->height : 0; - x = theme->window_button_width; + x = offset_left; y = (theme->title_height - buffer_height) / 2; if (title_bg_width <= 0) { @@ -323,7 +367,7 @@ ssd_update_title_positions(struct ssd *ssd) wlr_scene_node_set_enabled(part->node, true); if (theme->window_label_text_justify == LAB_JUSTIFY_CENTER) { - if (buffer_width + theme->window_button_width * 2 <= title_bg_width) { + if (buffer_width + MAX(offset_left, offset_right) * 2 <= width) { /* Center based on the full width */ x = (width - buffer_width) / 2; } else { @@ -346,7 +390,7 @@ ssd_update_title_positions(struct ssd *ssd) void ssd_update_title(struct ssd *ssd) { - if (!ssd) { + if (!ssd || !rc.show_title) { return; } @@ -366,8 +410,9 @@ ssd_update_title(struct ssd *ssd) struct ssd_part *part; struct ssd_sub_tree *subtree; struct ssd_state_title_width *dstate; - int title_bg_width = view->current.width - - theme->window_button_width * SSD_BUTTON_COUNT; + int offset_left = theme->window_button_width * wl_list_length(&rc.title_buttons_left); + int offset_right = theme->window_button_width * wl_list_length(&rc.title_buttons_right); + int title_bg_width = view->current.width - offset_left - offset_right; FOR_EACH_STATE(ssd, subtree) { if (subtree == &ssd->titlebar.active) { diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index a8c3e173..ca82fe4a 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -233,14 +233,17 @@ ssd_update_geometry(struct ssd *ssd) struct wlr_box cached = ssd->state.geometry; struct wlr_box current = ssd->view->current; - int min_view_width = rc.theme->window_button_width * SSD_BUTTON_COUNT; + int min_view_width = rc.theme->window_button_width * ( + wl_list_length(&rc.title_buttons_left) + wl_list_length(&rc.title_buttons_right)); int eff_width = current.width; int eff_height = view_effective_height(ssd->view, /* use_pending */ false); if (eff_width > 0 && eff_width < min_view_width) { /* * Prevent negative values in calculations like - * `width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT` + * `width - theme->window_button_width + * * (wl_list_length(&rc.title_buttons_left) + * + wl_list_length(&rc.title_buttons_right))` */ wlr_log(WLR_ERROR, "view width is smaller than its minimal value"); diff --git a/src/theme.c b/src/theme.c index d699773e..eeb4a079 100644 --- a/src/theme.c +++ b/src/theme.c @@ -84,14 +84,26 @@ corner_from_icon_name(const char *icon_name) { assert(icon_name); - /* - * TODO: Once we implement titleLayout we can make the - * return values depend on parsed config values. - */ - if (!strcmp(icon_name, "menu")) { - return LAB_CORNER_TOP_LEFT; - } else if (!strcmp(icon_name, "close")) { - return LAB_CORNER_TOP_RIGHT; + struct title_button *b; + wl_list_for_each(b, &rc.title_buttons_left, link) { + if ((b->type == LAB_SSD_BUTTON_WINDOW_MENU && !strcmp(icon_name, "menu")) + || (b->type == LAB_SSD_BUTTON_ICONIFY && !strcmp(icon_name, "iconify")) + || (b->type == LAB_SSD_BUTTON_MAXIMIZE && !strcmp(icon_name, "max")) + || (b->type == LAB_SSD_BUTTON_MAXIMIZE && !strcmp(icon_name, "max_toggled")) + || (b->type == LAB_SSD_BUTTON_CLOSE && !strcmp(icon_name, "close"))) { + return LAB_CORNER_TOP_LEFT; + } + break; + } + wl_list_for_each_reverse(b, &rc.title_buttons_right, link) { + if ((b->type == LAB_SSD_BUTTON_WINDOW_MENU && !strcmp(icon_name, "menu")) + || (b->type == LAB_SSD_BUTTON_ICONIFY && !strcmp(icon_name, "iconify")) + || (b->type == LAB_SSD_BUTTON_MAXIMIZE && !strcmp(icon_name, "max")) + || (b->type == LAB_SSD_BUTTON_MAXIMIZE && !strcmp(icon_name, "max_toggled")) + || (b->type == LAB_SSD_BUTTON_CLOSE && !strcmp(icon_name, "close"))) { + return LAB_CORNER_TOP_RIGHT; + } + break; } return LAB_CORNER_UNKNOWN; } diff --git a/src/view.c b/src/view.c index d6668d8a..9ac24022 100644 --- a/src/view.c +++ b/src/view.c @@ -617,7 +617,8 @@ view_adjust_size(struct view *view, int *w, int *h) { assert(view); struct view_size_hints hints = view_get_size_hints(view); - int min_view_width = rc.theme->window_button_width * SSD_BUTTON_COUNT; + int min_view_width = rc.theme->window_button_width * ( + wl_list_length(&rc.title_buttons_left) + wl_list_length(&rc.title_buttons_right)); /* * "If a base size is not provided, the minimum size is to be diff --git a/src/xwayland.c b/src/xwayland.c index 738c2b17..2e035f38 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -622,7 +622,8 @@ check_natural_geometry(struct view *view) * un-maximized size when started maximized. Try to detect this * and set a fallback size. */ - int min_view_width = rc.theme->window_button_width * SSD_BUTTON_COUNT; + int min_view_width = rc.theme->window_button_width * ( + wl_list_length(&rc.title_buttons_left) + wl_list_length(&rc.title_buttons_right)); if (!view_is_floating(view) && (view->natural_geometry.width < min_view_width || view->natural_geometry.height < LAB_MIN_VIEW_HEIGHT)) {