summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Davenport <qball@blame.services>2021-06-15 17:18:34 +0200
committerDave Davenport <qball@blame.services>2021-06-15 17:18:34 +0200
commit4c1a74e15ed3fe35538a00d5351cebfd7ab574af (patch)
treeb96f16aff80f9d40445199987ce3a5f102fa33ce
parentf72bae02bb846af0091ff083e34325314907ea52 (diff)
[Widget] Add scaling option to background-image.
-rw-r--r--doc/rofi-theme.513
-rw-r--r--doc/rofi-theme.5.markdown9
-rw-r--r--include/rofi-icon-fetcher.h1
-rw-r--r--include/rofi-types.h11
-rw-r--r--lexer/theme-lexer.l8
-rw-r--r--lexer/theme-parser.y16
-rw-r--r--source/rofi-icon-fetcher.c50
-rw-r--r--source/theme.c23
8 files changed, 120 insertions, 11 deletions
diff --git a/doc/rofi-theme.5 b/doc/rofi-theme.5
index c089fdfe..646328fb 100644
--- a/doc/rofi-theme.5
+++ b/doc/rofi-theme.5
@@ -366,6 +366,8 @@ dynamic: false;
.IP \(bu 2
Format: url("path to image");
.IP \(bu 2
+Format: url("path to image", scale);
+.IP \(bu 2
Format: linear\-gradient(stop color,stop1, color, stop2 color, ...);
.IP \(bu 2
Format: linear\-gradient(to direction, stop color,stop1, color, stop2 color, ...);
@@ -375,7 +377,16 @@ Format: linear\-gradient(angle, stop color,stop1, color, stop2 color, ...);
Angle in deg,rad,grad (as used in color).
.PP
-Where the path is a string, and stop color is of type color.
+Where the \fB\fCpath\fR is a string, and \fB\fCstop\fR color is of type color.
+The \fB\fCscale\fR property can be:
+.IP \(bu 2
+none
+.IP \(bu 2
+both
+.IP \(bu 2
+width
+.IP \(bu 2
+height
.SH Color
.PP
diff --git a/doc/rofi-theme.5.markdown b/doc/rofi-theme.5.markdown
index 336f4cc5..19cb5134 100644
--- a/doc/rofi-theme.5.markdown
+++ b/doc/rofi-theme.5.markdown
@@ -255,13 +255,20 @@ dynamic: false;
**rofi** support a very limited set of image formats.
* Format: url("path to image");
+* Format: url("path to image", scale);
* Format: linear-gradient(stop color,stop1, color, stop2 color, ...);
* Format: linear-gradient(to direction, stop color,stop1, color, stop2 color, ...);
where direction is: top,left,right,bottom.
* Format: linear-gradient(angle, stop color,stop1, color, stop2 color, ...);
Angle in deg,rad,grad (as used in color).
-Where the path is a string, and stop color is of type color.
+Where the `path` is a string, and `stop` color is of type color.
+The `scale` property can be:
+
+* none
+* both
+* width
+* height
## Color
diff --git a/include/rofi-icon-fetcher.h b/include/rofi-icon-fetcher.h
index fed9c588..958f0a67 100644
--- a/include/rofi-icon-fetcher.h
+++ b/include/rofi-icon-fetcher.h
@@ -35,6 +35,7 @@ void rofi_icon_fetcher_destroy ( void );
* @returns the uid identifying the request.
*/
uint32_t rofi_icon_fetcher_query ( const char *name, const int size );
+uint32_t rofi_icon_fetcher_query_advanced ( const char *name, const int wsize, const int hsize );
/**
* @param uid The unique id representing the matching request.
diff --git a/include/rofi-types.h b/include/rofi-types.h
index 7e0794d3..4117a1b3 100644
--- a/include/rofi-types.h
+++ b/include/rofi-types.h
@@ -188,11 +188,22 @@ typedef enum
ROFI_DIRECTION_ANGLE,
} RofiDirection;
+typedef enum
+{
+ ROFI_SCALE_BOTH,
+ ROFI_SCALE_HEIGHT,
+ ROFI_SCALE_WIDTH,
+ ROFI_SCALE_NONE,
+} RofiScaleType;
+
typedef struct
{
RofiImageType type;
char *url;
+ RofiScaleType scaling;
+ int wsize;
+ int hsize;
RofiDirection dir;
double angle;
diff --git a/lexer/theme-lexer.l b/lexer/theme-lexer.l
index 394afa98..149b84b8 100644
--- a/lexer/theme-lexer.l
+++ b/lexer/theme-lexer.l
@@ -242,6 +242,11 @@ HSL (?i:hsl[a]?)
/* Image type */
URL (?i:url?)
LINEAR_GRADIENT (?i:linear-gradient?)
+WIDTH (?i:width?)
+HEIGHT (?i:height?)
+BOTH (?i:both?)
+
+
TO (?i:to?)
RIGHT (?i:right?)
@@ -564,6 +569,9 @@ if ( queue == NULL ){
}
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{URL} { return T_URL; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{LINEAR_GRADIENT} { return T_LINEAR_GRADIENT; }
+<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{WIDTH} { return T_WIDTH; }
+<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{HEIGHT} { return T_HEIGHT; }
+<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{BOTH} { return T_BOTH; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{TO} { return T_TO; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{LEFT} { return T_LEFT; }
diff --git a/lexer/theme-parser.y b/lexer/theme-parser.y
index a7031161..729101d9 100644
--- a/lexer/theme-parser.y
+++ b/lexer/theme-parser.y
@@ -210,6 +210,9 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%token T_COL_CMYK "cmyk colorscheme"
%token T_URL "an URL"
+%token T_WIDTH "an WIDTH"
+%token T_HEIGHT "an HEIGHT"
+%token T_BOTH "an BOTH"
%token T_TO "an TO"
%token T_LEFT "an LEFT"
%token T_RIGHT "an RIGHT"
@@ -217,6 +220,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%token T_BOTTOM "an BOTTOM"
%type <ival> t_property_direction
+%type <ival> t_property_scale_type
%token T_LINEAR_GRADIENT "a linear gradient"
%token T_PARENT_LEFT "Parent left ('(')"
@@ -561,6 +565,12 @@ t_property_element
$$->value.image.type = ROFI_IMAGE_URL;
$$->value.image.url = $3;
}
+| T_URL T_PARENT_LEFT T_STRING T_COMMA t_property_scale_type T_PARENT_RIGHT {
+ $$ = rofi_theme_property_create ( P_IMAGE );
+ $$->value.image.type = ROFI_IMAGE_URL;
+ $$->value.image.url = $3;
+ $$->value.image.scaling = $5;
+}
| T_LINEAR_GRADIENT T_PARENT_LEFT t_color_list T_PARENT_RIGHT {
$$ = rofi_theme_property_create ( P_IMAGE );
$$->value.image.type = ROFI_IMAGE_LINEAR_GRADIENT;
@@ -589,6 +599,12 @@ t_property_direction
| T_TOP { $$ = ROFI_DIRECTION_TOP; }
| T_BOTTOM { $$ = ROFI_DIRECTION_BOTTOM; }
;
+t_property_scale_type
+: T_BOTH { $$ = ROFI_SCALE_BOTH; }
+| T_WIDTH { $$ = ROFI_SCALE_WIDTH; }
+| T_HEIGHT { $$ = ROFI_SCALE_HEIGHT; }
+| T_NONE { $$ = ROFI_SCALE_NONE; }
+;
t_color_list
: t_property_color {
diff --git a/source/rofi-icon-fetcher.c b/source/rofi-icon-fetcher.c
index 12e912a1..6a09d22a 100644
--- a/source/rofi-icon-fetcher.c
+++ b/source/rofi-icon-fetcher.c
@@ -77,7 +77,8 @@ typedef struct
unsigned int *acount;
uint32_t uid;
- int size;
+ int wsize;
+ int hsize;
cairo_surface_t *surface;
IconFetcherNameEntry *entry;
@@ -301,13 +302,13 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
icon_path = sentry->entry->name;
}
else {
- icon_path = icon_path_ = nk_xdg_theme_get_icon ( rofi_icon_fetcher_data->xdg_context, themes, NULL, sentry->entry->name, sentry->size, 1, TRUE );
+ icon_path = icon_path_ = nk_xdg_theme_get_icon ( rofi_icon_fetcher_data->xdg_context, themes, NULL, sentry->entry->name, MIN(sentry->wsize,sentry->hsize), 1, TRUE );
if ( icon_path_ == NULL ) {
- g_debug ( "failed to get icon %s(%d): n/a", sentry->entry->name, sentry->size );
+ g_debug ( "failed to get icon %s(%dx%d): n/a", sentry->entry->name, sentry->wsize, sentry->hsize );
return;
}
else{
- g_debug ( "found icon %s(%d): %s", sentry->entry->name, sentry->size, icon_path );
+ g_debug ( "found icon %s(%dx%d): %s", sentry->entry->name, sentry->wsize, sentry->hsize, icon_path );
}
}
cairo_surface_t *icon_surf = NULL;
@@ -318,7 +319,7 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
}
GError *error = NULL;
- GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale ( icon_path, sentry->size, sentry->size, TRUE, &error );
+ GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale ( icon_path, sentry->wsize, sentry->hsize, TRUE, &error );
if ( error != NULL ) {
g_warning ( "Failed to load image: %s", error->message );
g_error_free ( error );
@@ -336,6 +337,40 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
rofi_view_reload ();
}
+uint32_t rofi_icon_fetcher_query_advanced ( const char *name, const int wsize, const int hsize )
+{
+ g_debug ( "Query: %s(%dx%d)", name, wsize, hsize );
+ IconFetcherNameEntry *entry = g_hash_table_lookup ( rofi_icon_fetcher_data->icon_cache, name );
+ if ( entry == NULL ) {
+ entry = g_new0 ( IconFetcherNameEntry, 1 );
+ entry->name = g_strdup ( name );
+ g_hash_table_insert ( rofi_icon_fetcher_data->icon_cache, entry->name, entry );
+ }
+ IconFetcherEntry *sentry;
+ for ( GList *iter = g_list_first ( entry->sizes ); iter; iter = g_list_next ( iter ) ) {
+ sentry = iter->data;
+ if ( sentry->wsize == wsize && sentry->hsize == hsize ) {
+ return sentry->uid;
+ }
+ }
+
+ // Not found.
+ sentry = g_new0 ( IconFetcherEntry, 1 );
+ sentry->uid = ++( rofi_icon_fetcher_data->last_uid );
+ sentry->wsize = wsize;
+ sentry->hsize = hsize;
+ sentry->entry = entry;
+ sentry->surface = NULL;
+
+ entry->sizes = g_list_prepend ( entry->sizes, sentry );
+ g_hash_table_insert ( rofi_icon_fetcher_data->icon_cache_uid, GINT_TO_POINTER ( sentry->uid ), sentry );
+
+ // Push into fetching queue.
+ sentry->state.callback = rofi_icon_fetcher_worker;
+ g_thread_pool_push ( tpool, sentry, NULL );
+
+ return sentry->uid;
+}
uint32_t rofi_icon_fetcher_query ( const char *name, const int size )
{
g_debug ( "Query: %s(%d)", name, size );
@@ -348,7 +383,7 @@ uint32_t rofi_icon_fetcher_query ( const char *name, const int size )
IconFetcherEntry *sentry;
for ( GList *iter = g_list_first ( entry->sizes ); iter; iter = g_list_next ( iter ) ) {
sentry = iter->data;
- if ( sentry->size == size ) {
+ if ( sentry->wsize == size && sentry->hsize == size ) {
return sentry->uid;
}
}
@@ -356,7 +391,8 @@ uint32_t rofi_icon_fetcher_query ( const char *name, const int size )
// Not found.
sentry = g_new0 ( IconFetcherEntry, 1 );
sentry->uid = ++( rofi_icon_fetcher_data->last_uid );
- sentry->size = size;
+ sentry->wsize = size;
+ sentry->hsize = size;
sentry->entry = entry;
sentry->surface = NULL;
diff --git a/source/theme.c b/source/theme.c
index fa8ac220..cd6546af 100644
--- a/source/theme.c
+++ b/source/theme.c
@@ -996,8 +996,27 @@ gboolean rofi_theme_get_image ( const widget *widget, const char *property, cair
return FALSE;
}
if ( p->value.image.type == ROFI_IMAGE_URL ) {
- if ( p->value.image.surface_id == 0 ) {
- p->value.image.surface_id = rofi_icon_fetcher_query ( p->value.image.url, -1 );
+ int wsize = -1;
+ int hsize = -1;
+ switch ( p->value.image.scaling ) {
+ case ROFI_SCALE_BOTH:
+ wsize = widget->w;
+ hsize = widget->h;
+ break;
+ case ROFI_SCALE_WIDTH:
+ wsize = widget->w;
+ break;
+ case ROFI_SCALE_HEIGHT:
+ hsize = widget->h;
+ break;
+ case ROFI_SCALE_NONE:
+ default:
+ break;
+ }
+ if ( p->value.image.surface_id == 0 || p->value.image.wsize != wsize || p->value.image.hsize != hsize) {
+ p->value.image.surface_id = rofi_icon_fetcher_query_advanced ( p->value.image.url, wsize, hsize );
+ p->value.image.wsize = wsize;
+ p->value.image.hsize = hsize;
}
cairo_surface_t *img = rofi_icon_fetcher_get ( p->value.image.surface_id );