aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Konstantin Pospelov <kupospelov@gmail.com>2019-06-08 18:11:32 +0300
committerLibravatar Simon Ser <contact@emersion.fr>2019-10-21 17:22:25 +0200
commitfa0abaf7cfecf1dc433717d53379d6942226c2bb (patch)
treedeb117124ad6b8f824cab986b99cf60f4cc2871c /swaybar
parentFix refresh rate scale of output (diff)
downloadsway-fa0abaf7cfecf1dc433717d53379d6942226c2bb.tar.gz
sway-fa0abaf7cfecf1dc433717d53379d6942226c2bb.tar.zst
sway-fa0abaf7cfecf1dc433717d53379d6942226c2bb.zip
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')
-rw-r--r--swaybar/tray/item.c109
-rw-r--r--swaybar/tray/tray.c4
2 files changed, 61 insertions, 52 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 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <arpa/inet.h> 2#include <arpa/inet.h>
3#include <cairo.h> 3#include <cairo.h>
4#include <limits.h>
4#include <stdbool.h> 5#include <stdbool.h>
5#include <stdlib.h> 6#include <stdlib.h>
6#include <string.h> 7#include <string.h>
@@ -27,7 +28,7 @@ static bool sni_ready(struct swaybar_sni *sni) {
27 28
28static void set_sni_dirty(struct swaybar_sni *sni) { 29static void set_sni_dirty(struct swaybar_sni *sni) {
29 if (sni_ready(sni)) { 30 if (sni_ready(sni)) {
30 sni->min_size = sni->max_size = 0; // invalidate previous icon 31 sni->target_size = sni->min_size = sni->max_size = 0; // invalidate previous icon
31 set_bar_dirty(sni->tray->bar); 32 set_bar_dirty(sni->tray->bar);
32 } 33 }
33} 34}
@@ -401,69 +402,75 @@ static enum hotspot_event_handling icon_hotspot_callback(
401 return HOTSPOT_PROCESS; 402 return HOTSPOT_PROCESS;
402} 403}
403 404
405static void reload_sni(struct swaybar_sni *sni, char *icon_theme,
406 int target_size) {
407 char *icon_name = sni->status[0] == 'N' ?
408 sni->attention_icon_name : sni->icon_name;
409 if (icon_name) {
410 list_t *icon_search_paths = create_list();
411 list_cat(icon_search_paths, sni->tray->basedirs);
412 if (sni->icon_theme_path) {
413 list_add(icon_search_paths, sni->icon_theme_path);
414 }
415 char *icon_path = find_icon(sni->tray->themes, icon_search_paths,
416 icon_name, target_size, icon_theme,
417 &sni->min_size, &sni->max_size);
418 list_free(icon_search_paths);
419 if (!icon_path && sni->icon_theme_path) {
420 icon_path = find_icon_in_dir(icon_name, sni->icon_theme_path,
421 &sni->min_size, &sni->max_size);
422 }
423 if (icon_path) {
424 cairo_surface_destroy(sni->icon);
425 sni->icon = load_background_image(icon_path);
426 free(icon_path);
427 return;
428 }
429 }
430
431 list_t *pixmaps = sni->status[0] == 'N' ?
432 sni->attention_icon_pixmap : sni->icon_pixmap;
433 if (pixmaps) {
434 struct swaybar_pixmap *pixmap = NULL;
435 int min_error = INT_MAX;
436 for (int i = 0; i < pixmaps->length; ++i) {
437 struct swaybar_pixmap *p = pixmaps->items[i];
438 int e = abs(target_size - pixmap->size);
439 if (e < min_error) {
440 pixmap = p;
441 min_error = e;
442 }
443 }
444 cairo_surface_destroy(sni->icon);
445 sni->icon = cairo_image_surface_create_for_data(pixmap->pixels,
446 CAIRO_FORMAT_ARGB32, pixmap->size, pixmap->size,
447 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pixmap->size));
448 }
449}
450
404uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x, 451uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
405 struct swaybar_sni *sni) { 452 struct swaybar_sni *sni) {
406 uint32_t height = output->height * output->scale; 453 uint32_t height = output->height * output->scale;
407 int padding = output->bar->config->tray_padding; 454 int padding = output->bar->config->tray_padding;
408 int ideal_size = height - 2*padding; 455 int target_size = height - 2*padding;
409 if ((ideal_size < sni->min_size || ideal_size > sni->max_size) && sni_ready(sni)) { 456 if (target_size != sni->target_size && sni_ready(sni)) {
410 bool icon_found = false; 457 // check if another icon should be loaded
411 char *icon_name = sni->status[0] == 'N' ? 458 if (target_size < sni->min_size || target_size > sni->max_size) {
412 sni->attention_icon_name : sni->icon_name; 459 reload_sni(sni, output->bar->config->icon_theme, target_size);
413 if (icon_name) {
414 list_t *icon_search_paths = create_list();
415 list_cat(icon_search_paths, sni->tray->basedirs);
416 if (sni->icon_theme_path) {
417 list_add(icon_search_paths, sni->icon_theme_path);
418 }
419 char *icon_path = find_icon(sni->tray->themes, icon_search_paths,
420 icon_name, ideal_size, output->bar->config->icon_theme,
421 &sni->min_size, &sni->max_size);
422 list_free(icon_search_paths);
423 if (!icon_path && sni->icon_theme_path) {
424 icon_path = find_icon_in_dir(icon_name, sni->icon_theme_path,
425 &sni->min_size, &sni->max_size);
426 }
427 if (icon_path) {
428 cairo_surface_destroy(sni->icon);
429 sni->icon = load_background_image(icon_path);
430 free(icon_path);
431 icon_found = true;
432 }
433 }
434 if (!icon_found) {
435 list_t *pixmaps = sni->status[0] == 'N' ?
436 sni->attention_icon_pixmap : sni->icon_pixmap;
437 if (pixmaps) {
438 int idx = -1;
439 unsigned smallest_error = -1; // UINT_MAX
440 for (int i = 0; i < pixmaps->length; ++i) {
441 struct swaybar_pixmap *pixmap = pixmaps->items[i];
442 unsigned error = (ideal_size - pixmap->size) *
443 (ideal_size < pixmap->size ? -1 : 1);
444 if (error < smallest_error) {
445 smallest_error = error;
446 idx = i;
447 }
448 }
449 struct swaybar_pixmap *pixmap = pixmaps->items[idx];
450 cairo_surface_destroy(sni->icon);
451 sni->icon = cairo_image_surface_create_for_data(pixmap->pixels,
452 CAIRO_FORMAT_ARGB32, pixmap->size, pixmap->size,
453 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pixmap->size));
454 }
455 } 460 }
461
462 sni->target_size = target_size;
456 } 463 }
457 464
458 int icon_size; 465 int icon_size;
459 cairo_surface_t *icon; 466 cairo_surface_t *icon;
460 if (sni->icon) { 467 if (sni->icon) {
461 int actual_size = cairo_image_surface_get_height(sni->icon); 468 int actual_size = cairo_image_surface_get_height(sni->icon);
462 icon_size = actual_size < ideal_size ? 469 icon_size = actual_size < target_size ?
463 actual_size*(ideal_size/actual_size) : ideal_size; 470 actual_size*(target_size/actual_size) : target_size;
464 icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size); 471 icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size);
465 } else { // draw a :( 472 } else { // draw a :(
466 icon_size = ideal_size*0.8; 473 icon_size = target_size*0.8;
467 icon = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, icon_size, icon_size); 474 icon = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, icon_size, icon_size);
468 cairo_t *cairo_icon = cairo_create(icon); 475 cairo_t *cairo_icon = cairo_create(icon);
469 cairo_set_source_u32(cairo_icon, 0xFF0000FF); 476 cairo_set_source_u32(cairo_icon, 0xFF0000FF);
diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c
index fcf8114f..5fe6f9c3 100644
--- a/swaybar/tray/tray.c
+++ b/swaybar/tray/tray.c
@@ -124,7 +124,9 @@ uint32_t render_tray(cairo_t *cairo, struct swaybar_output *output, double *x) {
124 struct swaybar_tray *tray = output->bar->tray; 124 struct swaybar_tray *tray = output->bar->tray;
125 for (int i = 0; i < tray->items->length; ++i) { 125 for (int i = 0; i < tray->items->length; ++i) {
126 uint32_t h = render_sni(cairo, output, x, tray->items->items[i]); 126 uint32_t h = render_sni(cairo, output, x, tray->items->items[i]);
127 max_height = h > max_height ? h : max_height; 127 if (h > max_height) {
128 max_height = h;
129 }
128 } 130 }
129 131
130 return max_height; 132 return max_height;