theme: allow to set window button size (#1965)

This commit introduces new option "window.button.width". Despite the name
it currently affects both width and height.
This commit is contained in:
Consus 2024-07-20 11:33:57 +03:00 committed by GitHub
parent 46ec513630
commit e4afa10fe4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 59 additions and 33 deletions

View file

@ -114,6 +114,10 @@ labwc-config(5).
Specifies how window titles are aligned in the titlebar for both Specifies how window titles are aligned in the titlebar for both
focused and unfocused windows. Type justification. Default Left. focused and unfocused windows. Type justification. Default Left.
*window.button.width*
Width of a titlebar button, in pixels.
Default is 26.
*window.active.button.unpressed.image.color* *window.active.button.unpressed.image.color*
Color of the images in titlebar buttons in their default, unpressed, Color of the images in titlebar buttons in their default, unpressed,
state. This element is for the focused window. state. This element is for the focused window.

View file

@ -29,6 +29,9 @@ window.active.label.text.color: #000000
window.inactive.label.text.color: #000000 window.inactive.label.text.color: #000000
window.label.text.justify: center window.label.text.justify: center
# window button width
window.button.width: 26
# window buttons # window buttons
window.active.button.unpressed.image.color: #000000 window.active.button.unpressed.image.color: #000000
window.inactive.button.unpressed.image.color: #000000 window.inactive.button.unpressed.image.color: #000000

View file

@ -6,7 +6,6 @@
#include "common/border.h" #include "common/border.h"
#define SSD_BUTTON_COUNT 4 #define SSD_BUTTON_COUNT 4
#define SSD_BUTTON_WIDTH 26
#define SSD_EXTENDED_AREA 8 #define SSD_EXTENDED_AREA 8
/* /*

View file

@ -45,6 +45,9 @@ struct theme {
float window_inactive_label_text_color[4]; float window_inactive_label_text_color[4];
enum lab_justification window_label_text_justify; enum lab_justification window_label_text_justify;
/* button width */
int window_button_width;
/* button colors */ /* button colors */
float window_active_button_menu_unpressed_image_color[4]; float window_active_button_menu_unpressed_image_color[4];
float window_active_button_iconify_unpressed_image_color[4]; float window_active_button_iconify_unpressed_image_color[4];

View file

@ -10,7 +10,6 @@
#include <wlr/util/box.h> #include <wlr/util/box.h>
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#define LAB_MIN_VIEW_WIDTH (SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT)
#define LAB_MIN_VIEW_HEIGHT 60 #define LAB_MIN_VIEW_HEIGHT 60
/* /*

View file

@ -220,6 +220,7 @@ snap_shrink_to_next_edge(struct view *view,
*geo = view->pending; *geo = view->pending;
uint32_t resize_edges; uint32_t resize_edges;
int min_view_width = rc.theme->window_button_width * SSD_BUTTON_COUNT;
/* /*
* First shrink the view along the relevant edge. The maximum shrink * First shrink the view along the relevant edge. The maximum shrink
@ -228,12 +229,12 @@ snap_shrink_to_next_edge(struct view *view,
*/ */
switch (direction) { switch (direction) {
case VIEW_EDGE_RIGHT: case VIEW_EDGE_RIGHT:
geo->width = MAX(geo->width / 2, LAB_MIN_VIEW_WIDTH); geo->width = MAX(geo->width / 2, min_view_width);
geo->x = view->pending.x + view->pending.width - geo->width; geo->x = view->pending.x + view->pending.width - geo->width;
resize_edges = WLR_EDGE_LEFT; resize_edges = WLR_EDGE_LEFT;
break; break;
case VIEW_EDGE_LEFT: case VIEW_EDGE_LEFT:
geo->width = MAX(geo->width / 2, LAB_MIN_VIEW_WIDTH); geo->width = MAX(geo->width / 2, min_view_width);
resize_edges = WLR_EDGE_RIGHT; resize_edges = WLR_EDGE_RIGHT;
break; break;
case VIEW_EDGE_DOWN: case VIEW_EDGE_DOWN:

View file

@ -48,8 +48,8 @@ ssd_border_create(struct ssd *ssd)
add_scene_rect(&subtree->parts, LAB_SSD_PART_BOTTOM, parent, add_scene_rect(&subtree->parts, LAB_SSD_PART_BOTTOM, parent,
full_width, theme->border_width, 0, height, color); full_width, theme->border_width, 0, height, color);
add_scene_rect(&subtree->parts, LAB_SSD_PART_TOP, parent, add_scene_rect(&subtree->parts, LAB_SSD_PART_TOP, parent,
width - 2 * SSD_BUTTON_WIDTH, theme->border_width, width - 2 * theme->window_button_width, theme->border_width,
theme->border_width + SSD_BUTTON_WIDTH, theme->border_width + theme->window_button_width,
-(ssd->titlebar.height + theme->border_width), color); -(ssd->titlebar.height + theme->border_width), color);
} FOR_EACH_END } FOR_EACH_END
@ -121,10 +121,10 @@ ssd_border_update(struct ssd *ssd)
: 0; : 0;
int top_width = ssd->titlebar.height <= 0 || ssd->state.was_tiled_not_maximized int top_width = ssd->titlebar.height <= 0 || ssd->state.was_tiled_not_maximized
? full_width ? full_width
: width - 2 * SSD_BUTTON_WIDTH; : width - 2 * theme->window_button_width;
int top_x = ssd->titlebar.height <= 0 || ssd->state.was_tiled_not_maximized int top_x = ssd->titlebar.height <= 0 || ssd->state.was_tiled_not_maximized
? 0 ? 0
: theme->border_width + SSD_BUTTON_WIDTH; : theme->border_width + theme->window_button_width;
struct ssd_part *part; struct ssd_part *part;
struct wlr_scene_rect *rect; struct wlr_scene_rect *rect;

View file

@ -32,7 +32,8 @@ ssd_extents_create(struct ssd *ssd)
struct theme *theme = view->server->theme; struct theme *theme = view->server->theme;
struct wl_list *part_list = &ssd->extents.parts; struct wl_list *part_list = &ssd->extents.parts;
int extended_area = SSD_EXTENDED_AREA; int extended_area = SSD_EXTENDED_AREA;
int corner_size = extended_area + theme->border_width + SSD_BUTTON_WIDTH / 2; int corner_size = extended_area + theme->border_width +
theme->window_button_width / 2;
ssd->extents.tree = wlr_scene_tree_create(ssd->tree); ssd->extents.tree = wlr_scene_tree_create(ssd->tree);
struct wlr_scene_tree *parent = ssd->extents.tree; struct wlr_scene_tree *parent = ssd->extents.tree;
@ -109,7 +110,8 @@ ssd_extents_update(struct ssd *ssd)
int full_height = height + theme->border_width * 2 + ssd->titlebar.height; int full_height = height + theme->border_width * 2 + ssd->titlebar.height;
int full_width = width + 2 * theme->border_width; int full_width = width + 2 * theme->border_width;
int extended_area = SSD_EXTENDED_AREA; int extended_area = SSD_EXTENDED_AREA;
int corner_size = extended_area + theme->border_width + SSD_BUTTON_WIDTH / 2; int corner_size = extended_area + theme->border_width +
theme->window_button_width / 2;
int side_width = full_width + extended_area * 2 - corner_size * 2; int side_width = full_width + extended_area * 2 - corner_size * 2;
int side_height = full_height + extended_area * 2 - corner_size * 2; int side_height = full_height + extended_area * 2 - corner_size * 2;

View file

@ -153,12 +153,13 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
/* Background */ /* Background */
struct ssd_part *bg_rect = add_scene_rect(part_list, type, parent, struct ssd_part *bg_rect = add_scene_rect(part_list, type, parent,
SSD_BUTTON_WIDTH, rc.theme->title_height, 0, 0, bg_color); rc.theme->window_button_width, rc.theme->title_height, 0, 0,
bg_color);
/* Icon */ /* Icon */
struct wlr_scene_tree *icon_tree = wlr_scene_tree_create(parent); struct wlr_scene_tree *icon_tree = wlr_scene_tree_create(parent);
struct wlr_box icon_geo = get_scale_box(icon_buffer, struct wlr_box icon_geo = get_scale_box(icon_buffer,
SSD_BUTTON_WIDTH, rc.theme->title_height); rc.theme->window_button_width, rc.theme->title_height);
struct ssd_part *icon_part = add_scene_buffer(part_list, type, struct ssd_part *icon_part = add_scene_buffer(part_list, type,
icon_tree, icon_buffer, icon_geo.x, icon_geo.y); icon_tree, icon_buffer, icon_geo.x, icon_geo.y);
@ -171,7 +172,7 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
struct wlr_scene_tree *hover_tree = wlr_scene_tree_create(parent); struct wlr_scene_tree *hover_tree = wlr_scene_tree_create(parent);
wlr_scene_node_set_enabled(&hover_tree->node, false); wlr_scene_node_set_enabled(&hover_tree->node, false);
struct wlr_box hover_geo = get_scale_box(hover_buffer, struct wlr_box hover_geo = get_scale_box(hover_buffer,
SSD_BUTTON_WIDTH, rc.theme->title_height); rc.theme->window_button_width, rc.theme->title_height);
struct ssd_part *hover_part = add_scene_buffer(part_list, type, struct ssd_part *hover_part = add_scene_buffer(part_list, type,
hover_tree, hover_buffer, hover_geo.x, hover_geo.y); hover_tree, hover_buffer, hover_geo.x, hover_geo.y);
@ -200,7 +201,7 @@ add_toggled_icon(struct ssd_button *button, struct wl_list *part_list,
{ {
/* Alternate icon */ /* Alternate icon */
struct wlr_box icon_geo = get_scale_box(icon_buffer, struct wlr_box icon_geo = get_scale_box(icon_buffer,
SSD_BUTTON_WIDTH, rc.theme->title_height); rc.theme->window_button_width, rc.theme->title_height);
struct ssd_part *alticon_part = add_scene_buffer(part_list, type, struct ssd_part *alticon_part = add_scene_buffer(part_list, type,
button->icon_tree, icon_buffer, icon_geo.x, icon_geo.y); button->icon_tree, icon_buffer, icon_geo.x, icon_geo.y);
@ -212,7 +213,7 @@ add_toggled_icon(struct ssd_button *button, struct wl_list *part_list,
wlr_scene_node_set_enabled(alticon_part->node, false); wlr_scene_node_set_enabled(alticon_part->node, false);
struct wlr_box hover_geo = get_scale_box(hover_buffer, struct wlr_box hover_geo = get_scale_box(hover_buffer,
SSD_BUTTON_WIDTH, rc.theme->title_height); rc.theme->window_button_width, rc.theme->title_height);
struct ssd_part *althover_part = add_scene_buffer(part_list, type, struct ssd_part *althover_part = add_scene_buffer(part_list, type,
button->hover_tree, hover_buffer, hover_geo.x, hover_geo.y); button->hover_tree, hover_buffer, hover_geo.x, hover_geo.y);

View file

@ -90,21 +90,21 @@ ssd_titlebar_create(struct ssd *ssd)
/* Title */ /* Title */
add_scene_rect(&subtree->parts, LAB_SSD_PART_TITLEBAR, parent, add_scene_rect(&subtree->parts, LAB_SSD_PART_TITLEBAR, parent,
width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT, theme->title_height, width - theme->window_button_width * SSD_BUTTON_COUNT,
SSD_BUTTON_WIDTH, 0, color); theme->title_height, theme->window_button_width, 0, color);
/* Buttons */ /* Buttons */
add_scene_button_corner(&subtree->parts, add_scene_button_corner(&subtree->parts,
LAB_SSD_BUTTON_WINDOW_MENU, LAB_SSD_PART_CORNER_TOP_LEFT, parent, LAB_SSD_BUTTON_WINDOW_MENU, LAB_SSD_PART_CORNER_TOP_LEFT, parent,
corner_top_left, menu_button_unpressed, menu_button_hover, 0, view); corner_top_left, menu_button_unpressed, menu_button_hover, 0, view);
add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent, add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent,
color, iconify_button_unpressed, iconify_button_hover, color, iconify_button_unpressed, iconify_button_hover,
width - SSD_BUTTON_WIDTH * 3, view); width - theme->window_button_width * 3, view);
/* Maximize button has an alternate state when maximized */ /* Maximize button has an alternate state when maximized */
struct ssd_part *btn_max_root = add_scene_button( struct ssd_part *btn_max_root = add_scene_button(
&subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent, &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent,
color, maximize_button_unpressed, maximize_button_hover, color, maximize_button_unpressed, maximize_button_hover,
width - SSD_BUTTON_WIDTH * 2, view); width - theme->window_button_width * 2, view);
struct ssd_button *btn_max = node_ssd_button_from_node(btn_max_root->node); 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, add_toggled_icon(btn_max, &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE,
restore_button_unpressed, restore_button_hover); restore_button_unpressed, restore_button_hover);
@ -112,7 +112,7 @@ ssd_titlebar_create(struct ssd *ssd)
add_scene_button_corner(&subtree->parts, add_scene_button_corner(&subtree->parts,
LAB_SSD_BUTTON_CLOSE, LAB_SSD_PART_CORNER_TOP_RIGHT, parent, LAB_SSD_BUTTON_CLOSE, LAB_SSD_PART_CORNER_TOP_RIGHT, parent,
corner_top_right, close_button_unpressed, close_button_hover, corner_top_right, close_button_unpressed, close_button_hover,
width - SSD_BUTTON_WIDTH * 1, view); width - theme->window_button_width * 1, view);
} FOR_EACH_END } FOR_EACH_END
ssd_update_title(ssd); ssd_update_title(ssd);
@ -218,25 +218,25 @@ ssd_titlebar_update(struct ssd *ssd)
case LAB_SSD_PART_TITLEBAR: case LAB_SSD_PART_TITLEBAR:
wlr_scene_rect_set_size( wlr_scene_rect_set_size(
wlr_scene_rect_from_node(part->node), wlr_scene_rect_from_node(part->node),
width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT, width - theme->window_button_width * SSD_BUTTON_COUNT,
theme->title_height); theme->title_height);
continue; continue;
case LAB_SSD_BUTTON_ICONIFY: case LAB_SSD_BUTTON_ICONIFY:
if (is_direct_child(part->node, subtree)) { if (is_direct_child(part->node, subtree)) {
wlr_scene_node_set_position(part->node, wlr_scene_node_set_position(part->node,
width - SSD_BUTTON_WIDTH * 3, 0); width - theme->window_button_width * 3, 0);
} }
continue; continue;
case LAB_SSD_BUTTON_MAXIMIZE: case LAB_SSD_BUTTON_MAXIMIZE:
if (is_direct_child(part->node, subtree)) { if (is_direct_child(part->node, subtree)) {
wlr_scene_node_set_position(part->node, wlr_scene_node_set_position(part->node,
width - SSD_BUTTON_WIDTH * 2, 0); width - theme->window_button_width * 2, 0);
} }
continue; continue;
case LAB_SSD_PART_CORNER_TOP_RIGHT: case LAB_SSD_PART_CORNER_TOP_RIGHT:
if (is_direct_child(part->node, subtree)) { if (is_direct_child(part->node, subtree)) {
wlr_scene_node_set_position(part->node, wlr_scene_node_set_position(part->node,
width - SSD_BUTTON_WIDTH * 1, 0); width - theme->window_button_width * 1, 0);
} }
continue; continue;
default: default:
@ -288,7 +288,7 @@ ssd_update_title_positions(struct ssd *ssd)
struct view *view = ssd->view; struct view *view = ssd->view;
struct theme *theme = view->server->theme; struct theme *theme = view->server->theme;
int width = view->current.width; int width = view->current.width;
int title_bg_width = width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT; int title_bg_width = width - theme->window_button_width * SSD_BUTTON_COUNT;
int x, y; int x, y;
int buffer_height, buffer_width; int buffer_height, buffer_width;
@ -304,7 +304,7 @@ ssd_update_title_positions(struct ssd *ssd)
buffer_width = part->buffer ? part->buffer->width : 0; buffer_width = part->buffer ? part->buffer->width : 0;
buffer_height = part->buffer ? part->buffer->height : 0; buffer_height = part->buffer ? part->buffer->height : 0;
x = SSD_BUTTON_WIDTH; x = theme->window_button_width;
y = (theme->title_height - buffer_height) / 2; y = (theme->title_height - buffer_height) / 2;
if (title_bg_width <= 0) { if (title_bg_width <= 0) {
@ -314,7 +314,7 @@ ssd_update_title_positions(struct ssd *ssd)
wlr_scene_node_set_enabled(part->node, true); wlr_scene_node_set_enabled(part->node, true);
if (theme->window_label_text_justify == LAB_JUSTIFY_CENTER) { if (theme->window_label_text_justify == LAB_JUSTIFY_CENTER) {
if (buffer_width + SSD_BUTTON_WIDTH * 2 <= title_bg_width) { if (buffer_width + theme->window_button_width * 2 <= title_bg_width) {
/* Center based on the full width */ /* Center based on the full width */
x = (width - buffer_width) / 2; x = (width - buffer_width) / 2;
} else { } else {
@ -358,7 +358,7 @@ ssd_update_title(struct ssd *ssd)
struct ssd_sub_tree *subtree; struct ssd_sub_tree *subtree;
struct ssd_state_title_width *dstate; struct ssd_state_title_width *dstate;
int title_bg_width = view->current.width int title_bg_width = view->current.width
- SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT; - theme->window_button_width * SSD_BUTTON_COUNT;
FOR_EACH_STATE(ssd, subtree) { FOR_EACH_STATE(ssd, subtree) {
if (subtree == &ssd->titlebar.active) { if (subtree == &ssd->titlebar.active) {

View file

@ -233,10 +233,11 @@ ssd_update_geometry(struct ssd *ssd)
struct wlr_box cached = ssd->state.geometry; struct wlr_box cached = ssd->state.geometry;
struct wlr_box current = ssd->view->current; struct wlr_box current = ssd->view->current;
int min_view_width = rc.theme->window_button_width * SSD_BUTTON_COUNT;
int eff_width = current.width; int eff_width = current.width;
int eff_height = view_effective_height(ssd->view, /* use_pending */ false); int eff_height = view_effective_height(ssd->view, /* use_pending */ false);
if (eff_width > 0 && eff_width < LAB_MIN_VIEW_WIDTH) { if (eff_width > 0 && eff_width < min_view_width) {
/* /*
* Prevent negative values in calculations like * Prevent negative values in calculations like
* `width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT` * `width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT`

View file

@ -110,7 +110,7 @@ create_hover_fallback(struct theme *theme, const char *icon_name,
int icon_width = cairo_image_surface_get_width(icon.surface); int icon_width = cairo_image_surface_get_width(icon.surface);
int icon_height = cairo_image_surface_get_height(icon.surface); int icon_height = cairo_image_surface_get_height(icon.surface);
int width = SSD_BUTTON_WIDTH; int width = theme->window_button_width;
int height = theme->title_height; int height = theme->title_height;
if (width && height) { if (width && height) {
@ -488,6 +488,8 @@ theme_builtin(struct theme *theme, struct server *server)
parse_hexstr("#000000", theme->window_inactive_label_text_color); parse_hexstr("#000000", theme->window_inactive_label_text_color);
theme->window_label_text_justify = parse_justification("Center"); theme->window_label_text_justify = parse_justification("Center");
theme->window_button_width = 26;
parse_hexstr("#000000", parse_hexstr("#000000",
theme->window_active_button_menu_unpressed_image_color); theme->window_active_button_menu_unpressed_image_color);
parse_hexstr("#000000", parse_hexstr("#000000",
@ -642,6 +644,15 @@ entry(struct theme *theme, const char *key, const char *value)
theme->window_label_text_justify = parse_justification(value); theme->window_label_text_justify = parse_justification(value);
} }
if (match_glob(key, "window.button.width")) {
theme->window_button_width = atoi(value);
if (theme->window_button_width < 1) {
wlr_log(WLR_ERROR, "window.button.width cannot "
"be less than 1, clamping it to 1.");
theme->window_button_width = 1;
}
}
/* universal button */ /* universal button */
if (match_glob(key, "window.active.button.unpressed.image.color")) { if (match_glob(key, "window.active.button.unpressed.image.color")) {
parse_hexstr(value, parse_hexstr(value,
@ -1065,7 +1076,7 @@ create_corners(struct theme *theme)
struct wlr_box box = { struct wlr_box box = {
.x = 0, .x = 0,
.y = 0, .y = 0,
.width = SSD_BUTTON_WIDTH + theme->border_width, .width = theme->window_button_width + theme->border_width,
.height = theme->title_height + theme->border_width, .height = theme->title_height + theme->border_width,
}; };

View file

@ -611,6 +611,7 @@ view_adjust_size(struct view *view, int *w, int *h)
{ {
assert(view); assert(view);
struct view_size_hints hints = view_get_size_hints(view); struct view_size_hints hints = view_get_size_hints(view);
int min_view_width = rc.theme->window_button_width * SSD_BUTTON_COUNT;
/* /*
* "If a base size is not provided, the minimum size is to be * "If a base size is not provided, the minimum size is to be
@ -633,7 +634,7 @@ view_adjust_size(struct view *view, int *w, int *h)
* This is currently always the case for xdg-shell views. * This is currently always the case for xdg-shell views.
*/ */
if (hints.min_width < 1) { if (hints.min_width < 1) {
hints.min_width = LAB_MIN_VIEW_WIDTH; hints.min_width = min_view_width;
} }
if (hints.min_height < 1) { if (hints.min_height < 1) {
hints.min_height = LAB_MIN_VIEW_HEIGHT; hints.min_height = LAB_MIN_VIEW_HEIGHT;

View file

@ -621,8 +621,9 @@ check_natural_geometry(struct view *view)
* un-maximized size when started maximized. Try to detect this * un-maximized size when started maximized. Try to detect this
* and set a fallback size. * and set a fallback size.
*/ */
int min_view_width = rc.theme->window_button_width * SSD_BUTTON_COUNT;
if (!view_is_floating(view) if (!view_is_floating(view)
&& (view->natural_geometry.width < LAB_MIN_VIEW_WIDTH && (view->natural_geometry.width < min_view_width
|| view->natural_geometry.height < LAB_MIN_VIEW_HEIGHT)) { || view->natural_geometry.height < LAB_MIN_VIEW_HEIGHT)) {
view_set_fallback_natural_geometry(view); view_set_fallback_natural_geometry(view);
} }