theme: add circle button hover effect (#2127)

This commit is contained in:
Jens Peters 2024-09-09 17:44:03 +02:00 committed by Johan Malm
parent dcd9b47e5b
commit 9395348c55
4 changed files with 59 additions and 19 deletions

View file

@ -132,6 +132,10 @@ labwc-config(5).
Space between titlebar buttons, in pixels. Space between titlebar buttons, in pixels.
Default is 0. Default is 0.
*window.button.hover.bg.shape*
The shape of the hover effect of a titlebar button: "rectangle" or "circle".
Default is "rectangle".
*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

@ -34,6 +34,9 @@ window.label.text.justify: center
window.button.width: 26 window.button.width: 26
window.button.spacing: 0 window.button.spacing: 0
# window button hover effect
window.button.hover.bg.shape: rectangle
# 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

@ -17,6 +17,11 @@ enum lab_justification {
LAB_JUSTIFY_RIGHT, LAB_JUSTIFY_RIGHT,
}; };
enum lab_shape {
LAB_RECTANGLE,
LAB_CIRCLE,
};
struct theme_snapping_overlay { struct theme_snapping_overlay {
bool bg_enabled; bool bg_enabled;
bool border_enabled; bool border_enabled;
@ -57,6 +62,8 @@ struct theme {
int window_button_width; int window_button_width;
/* the space between buttons */ /* the space between buttons */
int window_button_spacing; int window_button_spacing;
/* the shape of the hover effect */
enum lab_shape window_button_hover_bg_shape;
/* button colors */ /* button colors */
float window_active_button_menu_unpressed_image_color[4]; float window_active_button_menu_unpressed_image_color[4];

View file

@ -70,6 +70,9 @@ struct rounded_corner_ctx {
static struct lab_data_buffer *rounded_rect(struct rounded_corner_ctx *ctx); static struct lab_data_buffer *rounded_rect(struct rounded_corner_ctx *ctx);
/* 1 degree in radians (=2π/360) */
static const double deg = 0.017453292519943295;
static void static void
zdrop(struct lab_data_buffer **buffer) zdrop(struct lab_data_buffer **buffer)
{ {
@ -162,26 +165,36 @@ create_hover_fallback(struct theme *theme, const char *icon_name,
/* Overlay (pre-multiplied alpha) */ /* Overlay (pre-multiplied alpha) */
float overlay_color[4] = { 0.15f, 0.15f, 0.15f, 0.3f}; float overlay_color[4] = { 0.15f, 0.15f, 0.15f, 0.3f};
int radius = MIN(width, height) / 2;
enum corner corner = corner_from_icon_name(icon_name); enum corner corner = corner_from_icon_name(icon_name);
if (corner == LAB_CORNER_UNKNOWN) { switch (theme->window_button_hover_bg_shape) {
case LAB_CIRCLE:
set_cairo_color(cairo, overlay_color); set_cairo_color(cairo, overlay_color);
cairo_rectangle(cairo, 0, 0, width, height); cairo_arc(cairo, width / 2, height / 2, radius, 0 * deg, 360 * deg);
cairo_fill(cairo); cairo_fill(cairo);
} else { break;
struct rounded_corner_ctx rounded_ctx = { case LAB_RECTANGLE:
.box = &(struct wlr_box) { .width = width, .height = height }, if (corner == LAB_CORNER_UNKNOWN) {
.radius = rc.corner_radius, set_cairo_color(cairo, overlay_color);
.line_width = theme->border_width, cairo_rectangle(cairo, 0, 0, width, height);
.fill_color = overlay_color, cairo_fill(cairo);
.border_color = overlay_color, } else {
.corner = corner struct rounded_corner_ctx rounded_ctx = {
}; .box = &(struct wlr_box){.width = width, .height = height},
struct lab_data_buffer *overlay_buffer = rounded_rect(&rounded_ctx); .radius = rc.corner_radius,
cairo_set_source_surface(cairo, .line_width = theme->border_width,
cairo_get_target(overlay_buffer->cairo), 0, 0); .fill_color = overlay_color,
cairo_paint(cairo); .border_color = overlay_color,
wlr_buffer_drop(&overlay_buffer->base); .corner = corner};
struct lab_data_buffer *overlay_buffer =
rounded_rect(&rounded_ctx);
cairo_set_source_surface(cairo,
cairo_get_target(overlay_buffer->cairo), 0, 0);
cairo_paint(cairo);
wlr_buffer_drop(&overlay_buffer->base);
}
break;
} }
cairo_surface_flush(surf); cairo_surface_flush(surf);
@ -532,6 +545,18 @@ parse_justification(const char *str)
} }
} }
static enum lab_shape
parse_shape(const char *str)
{
if (!strcasecmp(str, "Rectangle")) {
return LAB_RECTANGLE;
} else if (!strcasecmp(str, "Circle")) {
return LAB_CIRCLE;
} else {
return LAB_RECTANGLE;
}
}
/* /*
* We generally use Openbox defaults, but if no theme file can be found it's * We generally use Openbox defaults, but if no theme file can be found it's
* better to populate the theme variables with some sane values as no-one * better to populate the theme variables with some sane values as no-one
@ -569,6 +594,7 @@ theme_builtin(struct theme *theme, struct server *server)
theme->padding_width = 0; theme->padding_width = 0;
theme->window_button_width = 26; theme->window_button_width = 26;
theme->window_button_spacing = 0; theme->window_button_spacing = 0;
theme->window_button_hover_bg_shape = LAB_RECTANGLE;
parse_hexstr("#000000", parse_hexstr("#000000",
theme->window_active_button_menu_unpressed_image_color); theme->window_active_button_menu_unpressed_image_color);
@ -774,6 +800,9 @@ entry(struct theme *theme, const char *key, const char *value)
theme->window_button_spacing = get_int_if_positive( theme->window_button_spacing = get_int_if_positive(
value, "window.button.spacing"); value, "window.button.spacing");
} }
if (match_glob(key, "window.button.hover.bg.shape")) {
theme->window_button_hover_bg_shape = parse_shape(value);
}
/* universal button */ /* universal button */
if (match_glob(key, "window.active.button.unpressed.image.color")) { if (match_glob(key, "window.active.button.unpressed.image.color")) {
@ -1077,9 +1106,6 @@ theme_read(struct theme *theme, struct wl_list *paths)
static struct lab_data_buffer * static struct lab_data_buffer *
rounded_rect(struct rounded_corner_ctx *ctx) rounded_rect(struct rounded_corner_ctx *ctx)
{ {
/* 1 degree in radians (=2π/360) */
double deg = 0.017453292519943295;
if (ctx->corner == LAB_CORNER_UNKNOWN) { if (ctx->corner == LAB_CORNER_UNKNOWN) {
return NULL; return NULL;
} }