]> git.mdlowis.com Git - proto/labwc.git/commitdiff
ssd: apply title layout
authorTobias Bengfort <tobias.bengfort@posteo.de>
Sun, 18 Aug 2024 08:49:18 +0000 (10:49 +0200)
committerTobias Bengfort <tobias.bengfort@posteo.de>
Tue, 20 Aug 2024 21:04:10 +0000 (23:04 +0200)
include/ssd.h
src/snap.c
src/ssd/ssd-titlebar.c
src/ssd/ssd.c
src/theme.c
src/view.c
src/xwayland.c

index 19b224505efcb6df4a7c12f533d2d9c9e6e5e38a..7a2e7a77e665bb9fbd3adb3dd4c7dfea856e8826 100644 (file)
@@ -5,7 +5,6 @@
 #include <wayland-server-core.h>
 #include "common/border.h"
 
-#define SSD_BUTTON_COUNT 4
 #define SSD_EXTENDED_AREA 8
 
 /*
index 5f1dbff8edd9a45e28ebc07571c981dbbeab76cd..3f188f6feaf0d17129f2f87e693387e4e362f225 100644 (file)
@@ -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
index ba4dc2bfca98758a936efb9c3e03676ac85ca24d..7326a707986759f73add6a09d9a74b59e76d39be 100644 (file)
@@ -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);
-
-               /* 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);
+               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();
+                       }
+               }
+
+               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) {
index a8c3e173b3066efbbcd6bf83d1a6b03d8db00d4a..ca82fe4a29b2da86b57ba5ceae43d842ecb58612 100644 (file)
@@ -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");
index d699773ede6694f06053846f91c6b0ada9224140..eeb4a079cf46d4a45390a13eaef4ef9268746dbf 100644 (file)
@@ -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;
 }
index d6668d8a594b741fb2d32c1dfa450d0f8265defd..9ac24022f482358c0de06fd906228aaa9cc790b6 100644 (file)
@@ -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
index 738c2b17d0df566f072fc853ae3bd48d280155e3..2e035f384e9f6dfd7b7f03cbc8fc2d3082ad167c 100644 (file)
@@ -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)) {