diff --git a/include/icon-loader.h b/include/icon-loader.h index e6741ddb..846d20a2 100644 --- a/include/icon-loader.h +++ b/include/icon-loader.h @@ -7,6 +7,6 @@ struct server; void icon_loader_init(struct server *server); void icon_loader_finish(struct server *server); struct lab_data_buffer *icon_loader_lookup(struct server *server, - const char *app_id, int size, int scale); + const char *app_id, int size, float scale); #endif /* LABWC_ICON_LOADER_H */ diff --git a/include/img/img-svg.h b/include/img/img-svg.h index 6843774d..c8acc71c 100644 --- a/include/img/img-svg.h +++ b/include/img/img-svg.h @@ -5,6 +5,6 @@ struct lab_data_buffer; void img_svg_load(const char *filename, struct lab_data_buffer **buffer, - int size); + int size, float scale); #endif /* LABWC_IMG_SVG_H */ diff --git a/include/labwc.h b/include/labwc.h index ce593e12..0a6c3a17 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -546,6 +546,14 @@ struct wlr_box output_usable_area_scaled(struct output *output); void handle_output_power_manager_set_mode(struct wl_listener *listener, void *data); void output_enable_adaptive_sync(struct wlr_output *output, bool enabled); + +/** + * output_max_scale() - get maximum scale factor of all usable outputs. + * Used when loading/rendering resources (e.g. icons) that may be + * displayed on any output. + */ +float output_max_scale(struct server *server); + void new_tearing_hint(struct wl_listener *listener, void *data); void server_init(struct server *server); diff --git a/src/icon-loader.c b/src/icon-loader.c index 60f82029..b824f5d5 100644 --- a/src/icon-loader.c +++ b/src/icon-loader.c @@ -5,6 +5,7 @@ #include #include #include +#include "common/macros.h" #include "common/mem.h" #include "common/string-helpers.h" #include "config.h" @@ -219,7 +220,8 @@ get_db_entry_by_id_fuzzy(struct sfdo_desktop_db *db, const char *app_id) } struct lab_data_buffer * -icon_loader_lookup(struct server *server, const char *app_id, int size, int scale) +icon_loader_lookup(struct server *server, const char *app_id, int size, + float scale) { struct icon_loader *loader = server->icon_loader; if (!loader) { @@ -236,16 +238,23 @@ icon_loader_lookup(struct server *server, const char *app_id, int size, int scal icon_name = sfdo_desktop_entry_get_icon(entry, NULL); } + /* + * libsfdo doesn't support loading icons for fractional scales, + * so round down and increase the icon size to compensate. + */ + int lookup_scale = MAX((int)scale, 1); + int lookup_size = lroundf(size * scale / lookup_scale); + struct icon_ctx ctx = {0}; int ret; if (!icon_name) { /* fall back to app id */ - ret = process_rel_name(&ctx, app_id, loader, size, scale); + ret = process_rel_name(&ctx, app_id, loader, lookup_size, lookup_scale); } else if (icon_name[0] == '/') { ret = process_abs_name(&ctx, icon_name); } else { /* this should be the case for most icons */ - ret = process_rel_name(&ctx, icon_name, loader, size, scale); + ret = process_rel_name(&ctx, icon_name, loader, lookup_size, lookup_scale); } if (ret < 0) { return NULL; @@ -261,7 +270,7 @@ icon_loader_lookup(struct server *server, const char *app_id, int size, int scal break; case SFDO_ICON_FILE_FORMAT_SVG: #if HAVE_RSVG - img_svg_load(ctx.path, &icon_buffer, size * scale); + img_svg_load(ctx.path, &icon_buffer, size, scale); #endif break; case SFDO_ICON_FILE_FORMAT_XPM: diff --git a/src/img/img-svg.c b/src/img/img-svg.c index 498c1bd0..baab5faa 100644 --- a/src/img/img-svg.c +++ b/src/img/img-svg.c @@ -15,8 +15,8 @@ #include "labwc.h" void -img_svg_load(const char *filename, struct lab_data_buffer **buffer, - int size) +img_svg_load(const char *filename, struct lab_data_buffer **buffer, int size, + float scale) { if (*buffer) { wlr_buffer_drop(&(*buffer)->base); @@ -39,7 +39,7 @@ img_svg_load(const char *filename, struct lab_data_buffer **buffer, return; } - *buffer = buffer_create_cairo(size, size, 1.0); + *buffer = buffer_create_cairo(size, size, scale); cairo_surface_t *image = (*buffer)->surface; cairo_t *cr = (*buffer)->cairo; diff --git a/src/output.c b/src/output.c index e0cb3ae8..58743e31 100644 --- a/src/output.c +++ b/src/output.c @@ -1067,3 +1067,17 @@ output_enable_adaptive_sync(struct wlr_output *output, bool enabled) enabled ? "en" : "dis", output->name); } } + +float +output_max_scale(struct server *server) +{ + /* Never return less than 1, in case outputs are disabled */ + float scale = 1; + struct output *output; + wl_list_for_each(output, &server->outputs, link) { + if (output_is_usable(output)) { + scale = MAX(scale, output->wlr_output->scale); + } + } + return scale; +} diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index ca5a8dde..530b9210 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -604,8 +604,16 @@ ssd_update_window_icon(struct ssd *ssd) int hpad = theme->window_button_width / 10; int icon_size = MIN(theme->window_button_width - 2 * hpad, theme->title_height - 2 * theme->padding_height); - /* TODO: take into account output scales */ - int icon_scale = 1; + + /* + * Load/render icons at the max scale of any usable output (at + * this point in time). We don't want to be constantly reloading + * icons as views are moved between outputs. + * + * TODO: currently there's no signal to reload/render icons if + * outputs are reconfigured and the max scale changes. + */ + float icon_scale = output_max_scale(ssd->view->server); struct lab_data_buffer *icon_buffer = icon_loader_lookup( ssd->view->server, app_id, icon_size, icon_scale); diff --git a/src/theme.c b/src/theme.c index 886ffa15..32bcfa23 100644 --- a/src/theme.c +++ b/src/theme.c @@ -257,7 +257,8 @@ load_button(struct theme *theme, struct button *b, int active) int size = theme->title_height - 2 * theme->padding_height; get_button_filename(filename, sizeof(filename), b->name, active ? "-active.svg" : "-inactive.svg"); - img_svg_load(filename, buffer, size); + /* TODO: account for output scale */ + img_svg_load(filename, buffer, size, 1); } #endif