Skip to content

Commit

Permalink
theme: add circle button hover effect (labwc#2127)
Browse files Browse the repository at this point in the history
  • Loading branch information
jp7677 authored and johanmalm committed Sep 10, 2024
1 parent dcd9b47 commit 9395348
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 19 deletions.
4 changes: 4 additions & 0 deletions docs/labwc-theme.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ labwc-config(5).
Space between titlebar buttons, in pixels.
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*
Color of the images in titlebar buttons in their default, unpressed,
state. This element is for the focused window.
Expand Down
3 changes: 3 additions & 0 deletions docs/themerc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ window.label.text.justify: center
window.button.width: 26
window.button.spacing: 0

# window button hover effect
window.button.hover.bg.shape: rectangle

# window buttons
window.active.button.unpressed.image.color: #000000
window.inactive.button.unpressed.image.color: #000000
Expand Down
7 changes: 7 additions & 0 deletions include/theme.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ enum lab_justification {
LAB_JUSTIFY_RIGHT,
};

enum lab_shape {
LAB_RECTANGLE,
LAB_CIRCLE,
};

struct theme_snapping_overlay {
bool bg_enabled;
bool border_enabled;
Expand Down Expand Up @@ -57,6 +62,8 @@ struct theme {
int window_button_width;
/* the space between buttons */
int window_button_spacing;
/* the shape of the hover effect */
enum lab_shape window_button_hover_bg_shape;

/* button colors */
float window_active_button_menu_unpressed_image_color[4];
Expand Down
64 changes: 45 additions & 19 deletions src/theme.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ struct rounded_corner_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
zdrop(struct lab_data_buffer **buffer)
{
Expand Down Expand Up @@ -162,26 +165,36 @@ create_hover_fallback(struct theme *theme, const char *icon_name,

/* Overlay (pre-multiplied alpha) */
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);

if (corner == LAB_CORNER_UNKNOWN) {
switch (theme->window_button_hover_bg_shape) {
case LAB_CIRCLE:
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);
} else {
struct rounded_corner_ctx rounded_ctx = {
.box = &(struct wlr_box) { .width = width, .height = height },
.radius = rc.corner_radius,
.line_width = theme->border_width,
.fill_color = overlay_color,
.border_color = overlay_color,
.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;
case LAB_RECTANGLE:
if (corner == LAB_CORNER_UNKNOWN) {
set_cairo_color(cairo, overlay_color);
cairo_rectangle(cairo, 0, 0, width, height);
cairo_fill(cairo);
} else {
struct rounded_corner_ctx rounded_ctx = {
.box = &(struct wlr_box){.width = width, .height = height},
.radius = rc.corner_radius,
.line_width = theme->border_width,
.fill_color = overlay_color,
.border_color = overlay_color,
.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);

Expand Down Expand Up @@ -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
* better to populate the theme variables with some sane values as no-one
Expand Down Expand Up @@ -569,6 +594,7 @@ theme_builtin(struct theme *theme, struct server *server)
theme->padding_width = 0;
theme->window_button_width = 26;
theme->window_button_spacing = 0;
theme->window_button_hover_bg_shape = LAB_RECTANGLE;

parse_hexstr("#000000",
theme->window_active_button_menu_unpressed_image_color);
Expand Down Expand Up @@ -774,6 +800,9 @@ entry(struct theme *theme, const char *key, const char *value)
theme->window_button_spacing = get_int_if_positive(
value, "window.button.spacing");
}
if (match_glob(key, "window.button.hover.bg.shape")) {
theme->window_button_hover_bg_shape = parse_shape(value);
}

/* universal button */
if (match_glob(key, "window.active.button.unpressed.image.color")) {
Expand Down Expand Up @@ -1077,9 +1106,6 @@ theme_read(struct theme *theme, struct wl_list *paths)
static struct lab_data_buffer *
rounded_rect(struct rounded_corner_ctx *ctx)
{
/* 1 degree in radians (=2π/360) */
double deg = 0.017453292519943295;

if (ctx->corner == LAB_CORNER_UNKNOWN) {
return NULL;
}
Expand Down

0 comments on commit 9395348

Please sign in to comment.