diff options
author | Phil Jones <philj56@gmail.com> | 2022-07-27 15:00:05 +0100 |
---|---|---|
committer | Phil Jones <philj56@gmail.com> | 2022-07-27 15:12:26 +0100 |
commit | df3495a160878fd28e3642b47087024429bd512f (patch) | |
tree | 2f784c35706fec01fa34e410765deed61480b921 | |
parent | cf9669976601697be36e21e3359709f09c31d9da (diff) |
Fix window workspaces in drun mode.
Previously, tofi-drun would print the filename of the selected
.desktop file to stdout. This could then be passed to
`xargs swaymsg exec gio launch` to be executed.
The problem is that this ends up defeating the purpose of passing the
command to swaymsg exec, and the workspace the command was selected on
may not be the one that it starts up on, if for example it takes a long
time and the user switches workspaces in the meantime.
The solution is to instead print the Exec= line from the .desktop file,
and pass that directly to `xargs swaymsg exec --` for execution.
To avoid too much breaking of configs for the few people who use tofi
currently, this commit adds a new option, --drun-print-exec, to enable
the fixed behaviour. A future release will change this to be the
default, however.
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | completions/tofi | 1 | ||||
-rw-r--r-- | doc/tofi.1.md | 6 | ||||
-rw-r--r-- | doc/tofi.1.scd | 6 | ||||
-rw-r--r-- | doc/tofi.5.md | 11 | ||||
-rw-r--r-- | doc/tofi.5.scd | 9 | ||||
-rw-r--r-- | src/config.c | 2 | ||||
-rw-r--r-- | src/drun.c | 64 | ||||
-rw-r--r-- | src/drun.h | 1 | ||||
-rw-r--r-- | src/main.c | 20 | ||||
-rw-r--r-- | src/tofi.h | 1 |
11 files changed, 125 insertions, 4 deletions
@@ -57,6 +57,12 @@ executables under the user's `$PATH`. list of applications found in desktop files as described by the [Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html). +**WARNING**: Currently, when a selection is made in drun mode, the +filename of the selected desktop file is printed to stdout. In the next +version of tofi, this will change to an executable command line, to be +passed to swaymsg exec or similar. The new behaviour can be enabled now +by passing --drun-print-exec=true to tofi-drun. + To use as a launcher for Sway, add something similar to the following to your Sway config file: ``` @@ -67,7 +73,7 @@ bindsym $mod+d exec $menu For `tofi-drun`, there are two possible methods: ``` # Launch via Sway -set $drun tofi-drun | xargs swaymsg exec gio launch +set $drun tofi-drun --drun-print-exec=true | xargs swaymsg exec -- bindsym $mod+Shift+d exec $drun # Launch directly diff --git a/completions/tofi b/completions/tofi index 5a1d392..aa2b999 100644 --- a/completions/tofi +++ b/completions/tofi @@ -39,6 +39,7 @@ _tofi() --hide-cursor --history --drun-launch + --drun-print-exec --hint-font --late-keyboard-init ) diff --git a/doc/tofi.1.md b/doc/tofi.1.md index 6de0027..4529dda 100644 --- a/doc/tofi.1.md +++ b/doc/tofi.1.md @@ -27,6 +27,12 @@ When invoked via the name **tofi-drun**, **tofi** will not accept items on stdin, and will generate a list of applications from desktop files as described in the Desktop Entry Specification. +**WARNING**: Currently, when a selection is made in drun mode, the +filename of the selected desktop file is printed to stdout. In the next +version of tofi, this will change to an executable command line, to be +passed to swaymsg exec or similar. The new behaviour can be enabled now +by passing --drun-print-exec=true to tofi-drun. + **tofi-compgen** just prints the list of executables used by **tofi-run**. diff --git a/doc/tofi.1.scd b/doc/tofi.1.scd index d15d394..38ed290 100644 --- a/doc/tofi.1.scd +++ b/doc/tofi.1.scd @@ -27,6 +27,12 @@ When invoked via the name *tofi-drun*, *tofi* will not accept items on stdin, and will generate a list of applications from desktop files as described in the Desktop Entry Specification. +*WARNING*: Currently, when a selection is made in drun mode, the filename of +the selected desktop file is printed to stdout. In the next version of tofi, +this will change to an executable command line, to be passed to swaymsg exec or +similar. The new behaviour can be enabled now by passing --drun-print-exec=true +to tofi-drun. + *tofi-compgen* just prints the list of executables used by *tofi-run*. # OPTIONS diff --git a/doc/tofi.5.md b/doc/tofi.5.md index 916fc22..9a76a5d 100644 --- a/doc/tofi.5.md +++ b/doc/tofi.5.md @@ -224,6 +224,17 @@ options. > > Default: false +**drun-print-exec**=*true\|false* + +> If true, print an executable command line for the selected application +> when in drun mode. Otherwise, just print the path of the .desktop +> file. +> +> **WARNING**: In the next version of tofi, this will change to always +> be true, as it should have been from the start. +> +> Default: false + **hint-font**=*true\|false* > Perform font hinting. Only applies when a path to a font has been diff --git a/doc/tofi.5.scd b/doc/tofi.5.scd index 3ad7015..5a977d3 100644 --- a/doc/tofi.5.scd +++ b/doc/tofi.5.scd @@ -194,6 +194,15 @@ options. Default: false +*drun-print-exec*=_true|false_ + If true, print an executable command line for the selected application + when in drun mode. Otherwise, just print the path of the .desktop file. + + *WARNING*: In the next version of tofi, this will change to always be + true, as it should have been from the start. + + Default: false + *hint-font*=_true|false_ Perform font hinting. Only applies when a path to a font has been specified via *font-name*. Disabling font hinting speeds up text diff --git a/src/config.c b/src/config.c index a2e0f03..aebb8e1 100644 --- a/src/config.c +++ b/src/config.c @@ -293,6 +293,8 @@ bool parse_option(struct tofi *tofi, const char *filename, size_t lineno, const tofi->use_history = parse_bool(filename, lineno, value, &err); } else if (strcasecmp(option, "drun-launch") == 0) { tofi->drun_launch = parse_bool(filename, lineno, value, &err); + } else if (strcasecmp(option, "drun-print-exec") == 0) { + tofi->drun_print_exec = parse_bool(filename, lineno, value, &err); } else if (strcasecmp(option, "hint-font") == 0) { tofi->window.entry.harfbuzz.disable_hinting = !parse_bool(filename, lineno, value, &err); } else if (strcasecmp(option, "late-keyboard-init") == 0) { @@ -278,6 +278,70 @@ struct desktop_vec drun_generate_cached() return apps; } +void drun_print(const char *filename) +{ + GKeyFile *file = g_key_file_new(); + if (!g_key_file_load_from_file(file, filename, G_KEY_FILE_NONE, NULL)) { + log_error("Failed to open %s.\n", filename); + return; + } + const char *group = "Desktop Entry"; + + char *exec = g_key_file_get_string(file, group, "Exec", NULL); + if (exec == NULL) { + log_error("Failed to get Exec key from %s.\n", filename); + g_key_file_unref(file); + return; + } + + /* + * Build a string vector from the command line, replacing % field codes + * with the appropriate values. + */ + struct string_vec pieces = string_vec_create(); + char *search = exec; + char *last = search; + while ((search = strchr(search, '%')) != NULL) { + /* Add the string up to here to our vector. */ + search[0] = '\0'; + string_vec_add(&pieces, last); + search++; + last = search; + + switch (search[0]) { + case 'i': + if (g_key_file_has_key(file, group, "Icon", NULL)) { + string_vec_add(&pieces, "--icon "); + string_vec_add(&pieces, g_key_file_get_string(file, group, "Icon", NULL)); + } + break; + case 'c': + string_vec_add(&pieces, g_key_file_get_locale_string(file, group, "Name", NULL, NULL)); + break; + case 'k': + string_vec_add(&pieces, filename); + break; + } + } + if (last == exec) { + /* + * We didn't find any field codes, so just use the full exec + * string. + */ + fputs(exec, stdout); + } else { + /* Build the command line from our vector. */ + for (size_t i = 0; i < pieces.count; i++) { + fputs(pieces.buf[i].string, stdout); + } + } + fputc('\n', stdout); + + string_vec_destroy(&pieces); + free(exec); + g_key_file_unref(file); +} + void drun_launch(const char *filename) { GDesktopAppInfo *info = g_desktop_app_info_new_from_filename(filename); @@ -8,6 +8,7 @@ struct desktop_vec drun_generate(void); struct desktop_vec drun_generate_cached(void); void drun_history_sort(struct desktop_vec *apps, struct history *history); +void drun_print(const char *filename); void drun_launch(const char *filename); #endif /* DRUN_H */ @@ -707,6 +707,8 @@ static void usage() " --horizontal <true|false> List results horizontally.\n" " --history <true|false> Sort results by number of usages.\n" " --drun-launch <true|false> Launch apps directly in drun mode.\n" +" --drun-print-exec <true|false> Print a command line in drun mode.\n" +" This will become the default in future.\n" " --hint-font <true|false> Perform font hinting.\n" " --late-keyboard-init (EXPERIMENTAL) Delay keyboard\n" " initialisation until after the first\n" @@ -748,6 +750,7 @@ const struct option long_options[] = { {"hide-cursor", required_argument, NULL, 0}, {"history", required_argument, NULL, 0}, {"drun-launch", required_argument, NULL, 0}, + {"drun-print-exec", required_argument, NULL, 0}, {"hint-font", required_argument, NULL, 0}, {"output", required_argument, NULL, 'o'}, {"late-keyboard-init", no_argument, NULL, 'k'}, @@ -1257,12 +1260,23 @@ int main(int argc, char *argv[]) struct desktop_entry *app = desktop_vec_find(&tofi.window.entry.apps, res); if (app == NULL) { log_error("Couldn't find application file! This shouldn't happen.\n"); + break; } else { res = app->path; } - }; - if (tofi.window.entry.drun && tofi.drun_launch) { - drun_launch(res); + if (tofi.drun_launch) { + drun_launch(res); + } else if (tofi.drun_print_exec) { + drun_print(res); + } else { + log_warning("Using drun mode without --drun-print-exec=true is deprecated.\n" + " In the next version of tofi, this will become the default behaviour,\n" + " so fix your compositor configs now e.g. by replacing\n" + " tofi-drun | xargs swaymsg exec gio launch\n" + " with\n" + " tofi-drun --drun-print-exec=true | xargs swaymsg exec --\n"); + printf("%s\n", res); + } } else { printf("%s\n", res); } @@ -67,6 +67,7 @@ struct tofi { bool use_history; bool late_keyboard_init; bool drun_launch; + bool drun_print_exec; char target_output_name[MAX_OUTPUT_NAME_LEN]; }; |