mirror of
				https://github.com/swaywm/sway.git
				synced 2025-10-29 05:40:18 -04: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
					
				
					 3 changed files with 62 additions and 52 deletions
				
			
		|  | @ -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; | ||||
|  |  | |||
|  | @ -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,13 +402,8 @@ static enum hotspot_event_handling icon_hotspot_callback( | |||
| 	return HOTSPOT_PROCESS; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| 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) { | ||||
|  | @ -417,7 +413,7 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x, | |||
| 			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, | ||||
| 				icon_name, target_size, icon_theme, | ||||
| 				&sni->min_size, &sni->max_size); | ||||
| 		list_free(icon_search_paths); | ||||
| 		if (!icon_path && sni->icon_theme_path) { | ||||
|  | @ -428,42 +424,53 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x, | |||
| 			cairo_surface_destroy(sni->icon); | ||||
| 			sni->icon = load_background_image(icon_path); | ||||
| 			free(icon_path); | ||||
| 				icon_found = true; | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 		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
 | ||||
| 		struct swaybar_pixmap *pixmap = NULL; | ||||
| 		int min_error = INT_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 *p = pixmaps->items[i]; | ||||
| 			int e = abs(target_size - pixmap->size); | ||||
| 			if (e < min_error) { | ||||
| 				pixmap = p; | ||||
| 				min_error = e; | ||||
| 			} | ||||
| 		} | ||||
| 				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)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 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 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); | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Konstantin Pospelov
						Konstantin Pospelov