@ -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 ) ;