summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Dalessio <mike.dalessio@gmail.com>2020-08-26 15:10:04 -0400
committerGitHub <noreply@github.com>2020-08-26 21:10:04 +0200
commit5bec191d2ef3f7083573a99b4f9dd4fcc4a68208 (patch)
tree3bd26df111d7c0ea16a3bd71cfe62d81c0d58ed1
parent120ce36055e3144ebb12493daed239f42fa7f755 (diff)
Follow Type=Link standard desktop entries with drun (#1168)
* [DRun] Introduce data structure changes for Link desktop entries From the [freedesktop spec][1]: > This specification defines 3 types of desktop entries: > Application (type 1), Link (type 2) and Directory (type 3). To allow > the addition of new types in the future, implementations should > ignore desktop entries with an unknown type. This commit adds an enum to capture these types, and adds `type` to DRunModeEntry. [1]: https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html part of #1166 * [DRun] Sanity check Link entries and capture the URL Note that we're introducing some logic that will differ depending on the Desktop entry type (Application or Link). The logic is: - if entry is Application type, - then Exec is required - and the value is saved in .exec - and drun_mode_result calls exec_cmd_entry - if entry is Link type, - then URL is required (but is not saved in the DRunModeEntry) - and drun_mode_result calls new function launch_link_entry part of #1166 * [DRun] Launch desktop links via xdg-open Note that this introduces a new dependency on xdg-open, which may not be installed. In that case, rofi will display an error dialog with something like: "Failed to execute child process xdg-open (No such file or directory)" which hopefully is explanatory enough for folks. part of #1166 * Make drun options comments consistent and add a bit of whitespace * [DRun] new config option drun-url-launcher for opening links In previous commit, this was a hard-coded string. part of #1166
-rw-r--r--config/config.c15
-rw-r--r--include/settings.h6
-rw-r--r--source/dialogs/drun.c91
-rw-r--r--source/xrmoptions.c4
4 files changed, 102 insertions, 14 deletions
diff --git a/config/config.c b/config/config.c
index fe8fcc42..6e256e53 100644
--- a/config/config.c
+++ b/config/config.c
@@ -116,14 +116,18 @@ Settings config = {
.tokenize = TRUE,
.matching = "normal",
.matching_method = MM_NORMAL,
- /** Desktop entry fields to match*/
+
+ /** Desktop entries to match in drun */
.drun_match_fields = "name,generic,exec,categories,keywords",
+ /** Only show entries in this category */
.drun_categories = NULL,
- /** Desktop format display */
- .drun_display_format = "{name} [<span weight='light' size='small'><i>({generic})</i></span>]",
/** Desktop entry show actions */
.drun_show_actions = FALSE,
- /** Desktop entry show actions */
+ /** Desktop format display */
+ .drun_display_format = "{name} [<span weight='light' size='small'><i>({generic})</i></span>]",
+ /** Desktop Link launch command */
+ .drun_url_launcher = "xdg-open",
+
/** Window fields to match in window mode*/
.window_match_fields = "all",
/** Monitor */
@@ -160,8 +164,11 @@ Settings config = {
.cache_dir = NULL,
.window_thumbnail = FALSE,
+
+ /** drun cache */
.drun_use_desktop_cache = FALSE,
.drun_reload_desktop_cache = FALSE,
+
/** Benchmarks */
.benchmark_ui = FALSE
};
diff --git a/include/settings.h b/include/settings.h
index 7c57080d..cecb9c34 100644
--- a/include/settings.h
+++ b/include/settings.h
@@ -119,14 +119,18 @@ typedef struct
SortingMethod sorting_method_enum;
/** Sorting method. */
char * sorting_method;
+
/** Desktop entries to match in drun */
char * drun_match_fields;
/** Only show entries in this category */
char * drun_categories;
/** Desktop entry show actions */
unsigned int drun_show_actions;
- /** Desktop entry show */
+ /** Desktop format display */
char * drun_display_format;
+ /** Desktop Link launch command */
+ char * drun_url_launcher;
+
/** Search case sensitivity */
unsigned int case_sensitive;
/** Cycle through in the element list */
diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c
index afc19ba6..26fe73a1 100644
--- a/source/dialogs/drun.c
+++ b/source/dialogs/drun.c
@@ -61,6 +61,15 @@
char *DRUN_GROUP_NAME = "Desktop Entry";
typedef struct _DRunModePrivateData DRunModePrivateData;
+
+typedef enum
+{
+ DRUN_DESKTOP_ENTRY_TYPE_UNDETERMINED = 0,
+ DRUN_DESKTOP_ENTRY_TYPE_APPLICATION,
+ DRUN_DESKTOP_ENTRY_TYPE_LINK,
+ DRUN_DESKTOP_ENTRY_TYPE_DIRECTORY,
+} DRunDesktopEntryType;
+
/**
* Store extra information about the entry.
* Currently the executable and if it should run in terminal.
@@ -86,7 +95,7 @@ typedef struct
int icon_size;
/* Surface holding the icon. */
cairo_surface_t *icon;
- /* Executable */
+ /* Executable - for Application entries only */
char *exec;
/* Name of the Entry */
char *name;
@@ -104,6 +113,8 @@ typedef struct
gint sort_index;
uint32_t icon_fetch_uid;
+
+ DRunDesktopEntryType type;
} DRunModeEntry;
typedef struct
@@ -209,6 +220,43 @@ static gboolean drun_helper_eval_cb ( const GMatchInfo *info, GString *res, gpoi
// Continue replacement.
return FALSE;
}
+static void launch_link_entry ( DRunModeEntry *e )
+{
+ if ( e->key_file == NULL ) {
+ GKeyFile *kf = g_key_file_new ();
+ GError *error = NULL;
+ gboolean res = g_key_file_load_from_file ( kf, e->path, 0, &error );
+ if ( res ) {
+ e->key_file = kf;
+ }
+ else {
+ g_warning ( "[%s] [%s] Failed to parse desktop file because: %s.", e->app_id, e->path, error->message );
+ g_error_free ( error );
+ g_key_file_free ( kf );
+ return;
+ }
+ }
+
+ gchar *url = g_key_file_get_string ( e->key_file, e->action, "URL", NULL );
+ if ( url == NULL || strlen ( url ) == 0 ) {
+ g_warning ( "[%s] [%s] No URL found.", e->app_id, e->path );
+ g_free ( url );
+ return ;
+ }
+
+ gsize command_len = strlen( config.drun_url_launcher ) + strlen( url ) + 2; // space + terminator = 2
+ gchar *command = g_newa ( gchar, command_len );
+ g_snprintf( command, command_len, "%s %s", config.drun_url_launcher, url );
+ g_free ( url );
+
+ g_debug ( "Link launch command: |%s|", command );
+ if ( helper_execute_command ( NULL, command, FALSE, NULL ) ) {
+ char *path = g_build_filename ( cache_dir, DRUN_CACHE_FILE, NULL );
+ // Store it based on the unique identifiers (desktop_id).
+ history_set ( path, e->desktop_id );
+ g_free ( path );
+ }
+}
static void exec_cmd_entry ( DRunModeEntry *e )
{
GError *error = NULL;
@@ -300,6 +348,7 @@ static gboolean rofi_strv_contains ( const char * const *categories, const char
*/
static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const char *path, const gchar *basename, const char *action )
{
+ DRunDesktopEntryType desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_UNDETERMINED;
int parse_action = ( config.drun_show_actions && action != DRUN_GROUP_NAME );
// Create ID on stack.
// We know strlen (path ) > strlen(root)+1
@@ -342,8 +391,12 @@ static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const
g_key_file_free ( kf );
return;
}
- if ( g_strcmp0 ( key, "Application" ) ) {
- g_debug ( "[%s] [%s] Skipping desktop file: Not of type application (%s)", id, path, key );
+ if ( !g_strcmp0 ( key, "Application" ) ) {
+ desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_APPLICATION;
+ } else if ( !g_strcmp0 ( key, "Link" ) ) {
+ desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_LINK;
+ } else {
+ g_debug ( "[%s] [%s] Skipping desktop file: Not of type Application or Link (%s)", id, path, key );
g_free ( key );
g_key_file_free ( kf );
return;
@@ -407,9 +460,17 @@ static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const
g_hash_table_add ( pd->disabled_entries, g_strdup ( id ) );
return;
}
+
// We need Exec, don't support DBusActivatable
- if ( !g_key_file_has_key ( kf, DRUN_GROUP_NAME, "Exec", NULL ) ) {
- g_debug ( "[%s] [%s] Unsupported desktop file: no 'Exec' key present.", id, path );
+ if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_APPLICATION
+ && !g_key_file_has_key ( kf, DRUN_GROUP_NAME, "Exec", NULL ) ) {
+ g_debug ( "[%s] [%s] Unsupported desktop file: no 'Exec' key present for type Application.", id, path );
+ g_key_file_free ( kf );
+ return;
+ }
+ if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_LINK
+ && !g_key_file_has_key ( kf, DRUN_GROUP_NAME, "URL", NULL ) ) {
+ g_debug ( "[%s] [%s] Unsupported desktop file: no 'URL' key present for type Link.", id, path );
g_key_file_free ( kf );
return;
}
@@ -499,7 +560,12 @@ static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const
}
g_strfreev ( categories );
- pd->entry_list[pd->cmd_list_length].exec = g_key_file_get_string ( kf, action, "Exec", NULL );
+ pd->entry_list[pd->cmd_list_length].type = desktop_entry_type;
+ if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_APPLICATION ) {
+ pd->entry_list[pd->cmd_list_length].exec = g_key_file_get_string ( kf, action, "Exec", NULL );
+ } else {
+ pd->entry_list[pd->cmd_list_length].exec = NULL;
+ }
if ( matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled ) {
pd->entry_list[pd->cmd_list_length].comment = g_key_file_get_locale_string ( kf,
@@ -953,7 +1019,16 @@ static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned i
retv = ( mretv & MENU_LOWER_MASK );
}
else if ( ( mretv & MENU_OK ) ) {
- exec_cmd_entry ( &( rmpd->entry_list[selected_line] ) );
+ switch ( rmpd->entry_list[selected_line].type ) {
+ case DRUN_DESKTOP_ENTRY_TYPE_APPLICATION:
+ exec_cmd_entry ( &( rmpd->entry_list[selected_line] ) );
+ break;
+ case DRUN_DESKTOP_ENTRY_TYPE_LINK:
+ launch_link_entry ( &( rmpd->entry_list[selected_line] ) );
+ break;
+ default:
+ g_assert_not_reached ();
+ }
}
else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) {
retv = RELOAD_DIALOG;
@@ -1096,7 +1171,7 @@ static int drun_token_match ( const Mode *data, rofi_int_matcher **tokens, unsig
}
if ( matching_entry_fields[DRUN_MATCH_FIELD_EXEC].enabled ) {
// Match executable name.
- if ( test == tokens[j]->invert ) {
+ if ( test == tokens[j]->invert && rmpd->entry_list[index].exec ) {
test = helper_token_match ( ftokens, rmpd->entry_list[index].exec );
}
}
diff --git a/source/xrmoptions.c b/source/xrmoptions.c
index 18b925f4..94322edc 100644
--- a/source/xrmoptions.c
+++ b/source/xrmoptions.c
@@ -135,13 +135,15 @@ static XrmOption xrmOptions[] = {
{ xrm_String, "drun-match-fields", { .str = &config.drun_match_fields }, NULL,
"Desktop entry fields to match in drun", CONFIG_DEFAULT },
-
{ xrm_String, "drun-categories", { .str = &config.drun_categories }, NULL,
"Only show Desktop entry from these categories", CONFIG_DEFAULT },
{ xrm_Boolean, "drun-show-actions", { .num = &config.drun_show_actions }, NULL,
"Desktop entry show actions.", CONFIG_DEFAULT },
{ xrm_String, "drun-display-format", { .str = &config.drun_display_format }, NULL,
"DRUN format string. (Supports: generic,name,comment,exec,categories)", CONFIG_DEFAULT },
+ { xrm_String, "drun-url-launcher", { .str = &config.drun_url_launcher }, NULL,
+ "Command to open an Desktop Entry that is a Link.", CONFIG_DEFAULT },
+
{ xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL,
"Disable history in run/ssh", CONFIG_DEFAULT },
{ xrm_String, "ignored-prefixes", { .str = &config.ignored_prefixes }, NULL,