[Dmenu][Script] Add support for fallback icons#2122
[Dmenu][Script] Add support for fallback icons#2122DaveDavenport merged 4 commits intodavatorium:nextfrom
Conversation
This adds support for fallback icons in dmenu mode using comma-separated values in the icon metadata. When the primary icon is not found, subsequent icons in the list will be tried until one is successfully loaded. Example usage: "Firefox\0icon\x1ffirefox,web-browser,application-x-executable"
|
Rebased now that @lbonn's branch has been merged, to add a missing field assignment for HiDPI scaling. @DaveDavenport, any blockers? |
|
@DaveDavenport that looks reasonable, what do you think? |
|
I am not sure this one is correct. The fetch is async, so the check if an icon is available needs to be done on successive calls. |
|
@DaveDavenport, async dmenu icon fetching wasn't implemented originally. That said, it has been addressed now, pending your review. |
|
As mentioned in my previous comment, to do this correctly, we need to extend the api to show the internal cache state. After the next release (that is focussed on wayland) I will work on this. |
|
I was about to get back to this one, started to add the option.. and it seems I completely blanked out that I already added this option in 2022 to check if a query was done and failed, and that you used that...... apologies. |
|
Should we copy the logic from dmenu_.get_icon to the script._get_icon so they behave the same? A quick, untested, patch that that strsplits on once on loading the entry so the logic later can be simpler. What do you think? diff --git a/include/modes/dmenuscriptshared.h b/include/modes/dmenuscriptshared.h
index 041219c2..1c706ceb 100644
--- a/include/modes/dmenuscriptshared.h
+++ b/include/modes/dmenuscriptshared.h
@@ -13,7 +13,7 @@ typedef struct {
char *display;
/** Icon name to display. */
- char *icon_name;
+ char **icon_name;
/** Async icon fetch handler. */
uint32_t icon_fetch_uid;
uint32_t icon_fetch_size;
diff --git a/source/modes/dmenu.c b/source/modes/dmenu.c
index c896d7ba..3637170a 100644
--- a/source/modes/dmenu.c
+++ b/source/modes/dmenu.c
@@ -26,6 +26,7 @@
*/
/** The log domain of this dialog. */
+#include "glib.h"
#define G_LOG_DOMAIN "Modes.DMenu"
#include "config.h"
@@ -488,7 +489,7 @@ static void dmenu_mode_free(Mode *sw) {
for (size_t i = 0; i < pd->cmd_list_length; i++) {
if (pd->cmd_list[i].entry) {
g_free(pd->cmd_list[i].entry);
- g_free(pd->cmd_list[i].icon_name);
+ g_strfreev(pd->cmd_list[i].icon_name);
g_free(pd->cmd_list[i].display);
g_free(pd->cmd_list[i].meta);
g_free(pd->cmd_list[i].info);
@@ -741,27 +742,18 @@ static cairo_surface_t *dmenu_get_icon(const Mode *sw,
}
}
- char *icon_name_copy = g_strdup(dr->icon_name);
- char *icon_iter = icon_name_copy;
char *current_icon = NULL;
- int current_index = 0;
-
- // Try each icon in the comma-separated list until one is found
- while ((current_icon = strsep(&icon_iter, ",")) != NULL) {
- if (current_index == dr->icon_fallback_index) {
- dr->icon_fetch_uid = rofi_icon_fetcher_query(current_icon, height);
- dr->icon_fetch_size = height;
- dr->icon_fetch_scale = scale;
- break;
- }
- current_index++;
- }
- if (current_icon == NULL) {
+ current_icon = dr->icon_name[dr->icon_fallback_index];
+ if ( current_icon ){
+ dr->icon_fetch_uid = rofi_icon_fetcher_query(current_icon, height);
+ dr->icon_fetch_size = height;
+ dr->icon_fetch_scale = scale;
+
+ } else {
dr->icon_fetch_uid = 0;
}
- g_free(icon_name_copy);
return NULL;
}
diff --git a/source/modes/script.c b/source/modes/script.c
index 1db6d878..0c2c5794 100644
--- a/source/modes/script.c
+++ b/source/modes/script.c
@@ -26,6 +26,7 @@
*/
/** The log domain of this dialog. */
+#include "glib.h"
#define G_LOG_DOMAIN "Modes.Script"
#include "modes/script.h"
@@ -94,7 +95,8 @@ void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw,
*(extra) = NULL;
*(extra + 1) = NULL;
if (strcasecmp(key, "icon") == 0) {
- entry->icon_name = value;
+ entry->icon_name = g_strsplit(value,",", -1);
+ g_free(value);
} else if (strcasecmp(key, "display") == 0) {
entry->display = value;
} else if (strcasecmp(key, "meta") == 0) {
@@ -409,7 +411,7 @@ static void script_mode_destroy(Mode *sw) {
if (rmpd != NULL) {
for (unsigned int i = 0; i < rmpd->cmd_list_length; i++) {
g_free(rmpd->cmd_list[i].entry);
- g_free(rmpd->cmd_list[i].icon_name);
+ g_strfreev(rmpd->cmd_list[i].icon_name);
g_free(rmpd->cmd_list[i].display);
g_free(rmpd->cmd_list[i].meta);
}
@@ -518,20 +520,42 @@ static cairo_surface_t *script_get_icon(const Mode *sw,
unsigned int height) {
ScriptModePrivateData *pd =
(ScriptModePrivateData *)mode_get_private_data(sw);
+
const guint scale = display_scale();
+
g_return_val_if_fail(pd->cmd_list != NULL, NULL);
DmenuScriptEntry *dr = &(pd->cmd_list[selected_line]);
if (dr->icon_name == NULL) {
return NULL;
}
- if (dr->icon_fetch_uid > 0 && dr->icon_fetch_size == height &&
- dr->icon_fetch_scale == scale) {
- return rofi_icon_fetcher_get(dr->icon_fetch_uid);
+
+ if (dr->icon_fetch_uid > 0) {
+ cairo_surface_t *surface = NULL;
+ gboolean query_done = rofi_icon_fetcher_get_ex(dr->icon_fetch_uid, &surface);
+
+ if (surface != NULL) {
+ return surface;
+ } else if (query_done) {
+ dr->icon_fallback_index++;
+ dr->icon_fetch_uid = 0;
+ } else {
+ return NULL;
+ }
}
- dr->icon_fetch_uid = rofi_icon_fetcher_query(dr->icon_name, height);
- dr->icon_fetch_size = height;
- dr->icon_fetch_scale = scale;
- return rofi_icon_fetcher_get(dr->icon_fetch_uid);
+
+ char *current_icon = NULL;
+
+ current_icon = dr->icon_name[dr->icon_fallback_index];
+ if ( current_icon ){
+ dr->icon_fetch_uid = rofi_icon_fetcher_query(current_icon, height);
+ dr->icon_fetch_size = height;
+ dr->icon_fetch_scale = scale;
+
+ } else {
+ dr->icon_fetch_uid = 0;
+ }
+
+ return NULL;
}
#include "mode-private.h" |
|
Sounds good to me. Just added a check to prevent |
This adds support for fallback icons in dmenu mode using comma-separated values in the icon metadata. When the primary icon is not found, subsequent icons in the list will be tried until one is successfully loaded.
Example usage: "Firefox\0icon\x1ffirefox,web-browser,application-x-executable"