diff options
author | Konstantin Pospelov <kupospelov@gmail.com> | 2019-06-08 18:11:32 +0300 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2019-10-21 17:22:25 +0200 |
commit | fa0abaf7cfecf1dc433717d53379d6942226c2bb (patch) | |
tree | deb117124ad6b8f824cab986b99cf60f4cc2871c /swaybar/tray/item.c | |
parent | a5b6f40937a1f7630ec484bd2485b0b0f5f91c20 (diff) |
swaybar: do not retry search for tray icons
In case a tray icon cannot be found or does not have a desirable size,
swaybar retries the search again and again, which increases load on disk
and CPU. This commit solves it by storing target_size for each icon, so
that swaybar does not search for an icon of some size if it already tried to.
Fixes #3789.
Diffstat (limited to 'swaybar/tray/item.c')
-rw-r--r-- | swaybar/tray/item.c | 109 |
1 files changed, 58 insertions, 51 deletions
diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c index c8fcd382..1a7672c9 100644 --- a/swaybar/tray/item.c +++ b/swaybar/tray/item.c @@ -1,6 +1,7 @@ #define _POSIX_C_SOURCE 200809L #include <arpa/inet.h> #include <cairo.h> +#include <limits.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> @@ -27,7 +28,7 @@ static bool sni_ready(struct swaybar_sni *sni) { static void set_sni_dirty(struct swaybar_sni *sni) { if (sni_ready(sni)) { - sni->min_size = sni->max_size = 0; // invalidate previous icon + sni->target_size = sni->min_size = sni->max_size = 0; // invalidate previous icon set_bar_dirty(sni->tray->bar); } } @@ -401,69 +402,75 @@ static enum hotspot_event_handling icon_hotspot_callback( return HOTSPOT_PROCESS; } +static void reload_sni(struct swaybar_sni *sni, char *icon_theme, + int target_size) { + char *icon_name = sni->status[0] == 'N' ? + sni->attention_icon_name : sni->icon_name; + if (icon_name) { + list_t *icon_search_paths = create_list(); + list_cat(icon_search_paths, sni->tray->basedirs); + if (sni->icon_theme_path) { + list_add(icon_search_paths, sni->icon_theme_path); + } + char *icon_path = find_icon(sni->tray->themes, icon_search_paths, + icon_name, target_size, icon_theme, + &sni->min_size, &sni->max_size); + list_free(icon_search_paths); + if (!icon_path && sni->icon_theme_path) { + icon_path = find_icon_in_dir(icon_name, sni->icon_theme_path, + &sni->min_size, &sni->max_size); + } + if (icon_path) { + cairo_surface_destroy(sni->icon); + sni->icon = load_background_image(icon_path); + free(icon_path); + return; + } + } + + list_t *pixmaps = sni->status[0] == 'N' ? + sni->attention_icon_pixmap : sni->icon_pixmap; + if (pixmaps) { + struct swaybar_pixmap *pixmap = NULL; + int min_error = INT_MAX; + for (int i = 0; i < pixmaps->length; ++i) { + struct swaybar_pixmap *p = pixmaps->items[i]; + int e = abs(target_size - pixmap->size); + if (e < min_error) { + pixmap = p; + min_error = e; + } + } + cairo_surface_destroy(sni->icon); + sni->icon = cairo_image_surface_create_for_data(pixmap->pixels, + CAIRO_FORMAT_ARGB32, pixmap->size, pixmap->size, + cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pixmap->size)); + } +} + uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x, struct swaybar_sni *sni) { uint32_t height = output->height * output->scale; int padding = output->bar->config->tray_padding; - int ideal_size = height - 2*padding; - if ((ideal_size < sni->min_size || ideal_size > sni->max_size) && sni_ready(sni)) { - bool icon_found = false; - char *icon_name = sni->status[0] == 'N' ? - sni->attention_icon_name : sni->icon_name; - if (icon_name) { - list_t *icon_search_paths = create_list(); - list_cat(icon_search_paths, sni->tray->basedirs); - if (sni->icon_theme_path) { - list_add(icon_search_paths, sni->icon_theme_path); - } - char *icon_path = find_icon(sni->tray->themes, icon_search_paths, - icon_name, ideal_size, output->bar->config->icon_theme, - &sni->min_size, &sni->max_size); - list_free(icon_search_paths); - if (!icon_path && sni->icon_theme_path) { - icon_path = find_icon_in_dir(icon_name, sni->icon_theme_path, - &sni->min_size, &sni->max_size); - } - if (icon_path) { - cairo_surface_destroy(sni->icon); - sni->icon = load_background_image(icon_path); - free(icon_path); - icon_found = true; - } - } - if (!icon_found) { - list_t *pixmaps = sni->status[0] == 'N' ? - sni->attention_icon_pixmap : sni->icon_pixmap; - if (pixmaps) { - int idx = -1; - unsigned smallest_error = -1; // UINT_MAX - for (int i = 0; i < pixmaps->length; ++i) { - struct swaybar_pixmap *pixmap = pixmaps->items[i]; - unsigned error = (ideal_size - pixmap->size) * - (ideal_size < pixmap->size ? -1 : 1); - if (error < smallest_error) { - smallest_error = error; - idx = i; - } - } - struct swaybar_pixmap *pixmap = pixmaps->items[idx]; - cairo_surface_destroy(sni->icon); - sni->icon = cairo_image_surface_create_for_data(pixmap->pixels, - CAIRO_FORMAT_ARGB32, pixmap->size, pixmap->size, - cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pixmap->size)); - } + int target_size = height - 2*padding; + if (target_size != sni->target_size && sni_ready(sni)) { + // check if another icon should be loaded + if (target_size < sni->min_size || target_size > sni->max_size) { + reload_sni(sni, output->bar->config->icon_theme, target_size); } + + sni->target_size = target_size; } int icon_size; cairo_surface_t *icon; if (sni->icon) { int actual_size = cairo_image_surface_get_height(sni->icon); - icon_size = actual_size < ideal_size ? - actual_size*(ideal_size/actual_size) : ideal_size; + icon_size = actual_size < target_size ? + actual_size*(target_size/actual_size) : target_size; icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size); } else { // draw a :( - icon_size = ideal_size*0.8; + icon_size = target_size*0.8; icon = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, icon_size, icon_size); cairo_t *cairo_icon = cairo_create(icon); cairo_set_source_u32(cairo_icon, 0xFF0000FF); |