-
Notifications
You must be signed in to change notification settings - Fork 657
[Dmenu][Script] Add support for fallback icons #2122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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"