theme: draw hover overlay in the correct scale

The hover icon buffer on which the hover overlay is draw can be larger
than the button size when a large non-hover icon is provided by user. In
this case, we should scale up all the coorinates that are used to draw
the hover overlay. Before this commit, corner radius and padding.width
are not scaled correctly.

This commit fixes it by scaling the cairo context with cairo_scale()
when drawing the hover overlay.
This commit is contained in:
tokyo4j 2024-10-03 09:23:50 +09:00 committed by Johan Malm
parent c06b86c345
commit fb0c7a29c6

View file

@ -135,34 +135,37 @@ create_hover_fallback(struct theme *theme, const char *icon_name,
int width = theme->window_button_width; int width = theme->window_button_width;
int height = theme->title_height; int height = theme->title_height;
if (width && height) {
/* /*
* Proportionately increase size of hover_buffer if the * Proportionately increase size of hover_buffer if the non-hover
* non-hover 'donor' buffer is larger than the allocated space. * 'donor' buffer is larger than the allocated space. It will get
* It will get scaled down again by wlroots when rendered and as * scaled down again by wlroots when rendered and as required by the
* required by the current output scale. * current output scale.
* *
* This ensures that icons > width or > height keep their aspect * This ensures that icons > width or > height keep their aspect ratio
* ratio and are rendered the same as without the hover overlay. * and are rendered the same as without the hover overlay.
*/ */
double scale = MAX((double)icon_width / width, double scale = (width && height) ?
(double)icon_height / height); MAX((double)icon_width / width, (double)icon_height / height) : 1.0;
if (scale > 1.0f) { if (scale < 1.0) {
width = (double)width * scale; scale = 1.0;
height = (double)height * scale;
}
} }
int buffer_width = (double)width * scale;
int buffer_height = (double)height * scale;
*hover_buffer = buffer_create_cairo(width, height, 1.0, true); *hover_buffer = buffer_create_cairo(buffer_width, buffer_height, 1.0, true);
cairo_t *cairo = (*hover_buffer)->cairo; cairo_t *cairo = (*hover_buffer)->cairo;
cairo_surface_t *surf = cairo_get_target(cairo); cairo_surface_t *surf = cairo_get_target(cairo);
/* Background */ /* Background */
cairo_set_source_surface(cairo, icon.surface, cairo_set_source_surface(cairo, icon.surface,
(width - icon_width) / 2, (height - icon_height) / 2); (buffer_width - icon_width) / 2, (buffer_height - icon_height) / 2);
cairo_paint(cairo); cairo_paint(cairo);
/* Switch from buffer scale to theme scale */
cairo_save(cairo);
cairo_scale(cairo, scale, scale);
/* 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; int radius = MIN(width, height) / 2;
@ -212,6 +215,7 @@ create_hover_fallback(struct theme *theme, const char *icon_name,
break; break;
} }
cairo_surface_flush(surf); cairo_surface_flush(surf);
cairo_restore(cairo);
if (icon.is_duplicate) { if (icon.is_duplicate) {
cairo_surface_destroy(icon.surface); cairo_surface_destroy(icon.surface);