aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/swaybar/tray/item.h1
-rw-r--r--swaybar/tray/item.c109
-rw-r--r--swaybar/tray/tray.c4
3 files changed, 62 insertions, 52 deletions
diff --git a/include/swaybar/tray/item.h b/include/swaybar/tray/item.h
index 4238bdb8..5ffd8363 100644
--- a/include/swaybar/tray/item.h
+++ b/include/swaybar/tray/item.h
@@ -20,6 +20,7 @@ struct swaybar_sni {
cairo_surface_t *icon;
int min_size;
int max_size;
+ int target_size;
// dbus properties
char *watcher_id;
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);
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) {
struct swaybar_tray *tray = output->bar->tray;
for (int i = 0; i < tray->items->length; ++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;