mirror of
https://github.com/swaywm/sway.git
synced 2024-11-22 07:51:28 +00:00
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.
This commit is contained in:
parent
a5b6f40937
commit
fa0abaf7cf
|
@ -20,6 +20,7 @@ struct swaybar_sni {
|
||||||
cairo_surface_t *icon;
|
cairo_surface_t *icon;
|
||||||
int min_size;
|
int min_size;
|
||||||
int max_size;
|
int max_size;
|
||||||
|
int target_size;
|
||||||
|
|
||||||
// dbus properties
|
// dbus properties
|
||||||
char *watcher_id;
|
char *watcher_id;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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) {
|
static void set_sni_dirty(struct swaybar_sni *sni) {
|
||||||
if (sni_ready(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);
|
set_bar_dirty(sni->tray->bar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,69 +402,75 @@ static enum hotspot_event_handling icon_hotspot_callback(
|
||||||
return HOTSPOT_PROCESS;
|
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,
|
uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
|
||||||
struct swaybar_sni *sni) {
|
struct swaybar_sni *sni) {
|
||||||
uint32_t height = output->height * output->scale;
|
uint32_t height = output->height * output->scale;
|
||||||
int padding = output->bar->config->tray_padding;
|
int padding = output->bar->config->tray_padding;
|
||||||
int ideal_size = height - 2*padding;
|
int target_size = height - 2*padding;
|
||||||
if ((ideal_size < sni->min_size || ideal_size > sni->max_size) && sni_ready(sni)) {
|
if (target_size != sni->target_size && sni_ready(sni)) {
|
||||||
bool icon_found = false;
|
// check if another icon should be loaded
|
||||||
char *icon_name = sni->status[0] == 'N' ?
|
if (target_size < sni->min_size || target_size > sni->max_size) {
|
||||||
sni->attention_icon_name : sni->icon_name;
|
reload_sni(sni, output->bar->config->icon_theme, target_size);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sni->target_size = target_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int icon_size;
|
int icon_size;
|
||||||
cairo_surface_t *icon;
|
cairo_surface_t *icon;
|
||||||
if (sni->icon) {
|
if (sni->icon) {
|
||||||
int actual_size = cairo_image_surface_get_height(sni->icon);
|
int actual_size = cairo_image_surface_get_height(sni->icon);
|
||||||
icon_size = actual_size < ideal_size ?
|
icon_size = actual_size < target_size ?
|
||||||
actual_size*(ideal_size/actual_size) : ideal_size;
|
actual_size*(target_size/actual_size) : target_size;
|
||||||
icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size);
|
icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size);
|
||||||
} else { // draw a :(
|
} 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);
|
icon = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, icon_size, icon_size);
|
||||||
cairo_t *cairo_icon = cairo_create(icon);
|
cairo_t *cairo_icon = cairo_create(icon);
|
||||||
cairo_set_source_u32(cairo_icon, 0xFF0000FF);
|
cairo_set_source_u32(cairo_icon, 0xFF0000FF);
|
||||||
|
|
|
@ -124,7 +124,9 @@ uint32_t render_tray(cairo_t *cairo, struct swaybar_output *output, double *x) {
|
||||||
struct swaybar_tray *tray = output->bar->tray;
|
struct swaybar_tray *tray = output->bar->tray;
|
||||||
for (int i = 0; i < tray->items->length; ++i) {
|
for (int i = 0; i < tray->items->length; ++i) {
|
||||||
uint32_t h = render_sni(cairo, output, x, tray->items->items[i]);
|
uint32_t h = render_sni(cairo, output, x, tray->items->items[i]);
|
||||||
max_height = h > max_height ? h : max_height;
|
if (h > max_height) {
|
||||||
|
max_height = h;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return max_height;
|
return max_height;
|
||||||
|
|
Loading…
Reference in a new issue