From 9cae4a9b61861dd760e40228d97369bd672ad648 Mon Sep 17 00:00:00 2001 From: lbonn Date: Mon, 11 Mar 2024 11:07:29 +0100 Subject: [PATCH 01/13] [Modes] Remove dead code in mode implems (#1960) NEXT, PREVIOUS and QUICK_SWITCH are handled in mode.c since 96cd34d24f7116c0fd37bf8571ee3ae79f9ad227 (#1184) --- source/modes/filebrowser.c | 16 ++-------------- source/modes/recursivebrowser.c | 16 ++-------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/source/modes/filebrowser.c b/source/modes/filebrowser.c index 47df45889..57791cf80 100644 --- a/source/modes/filebrowser.c +++ b/source/modes/filebrowser.c @@ -473,13 +473,7 @@ static ModeMode file_browser_mode_result(Mode *sw, int mretv, char **input, } gboolean special_command = ((mretv & MENU_CUSTOM_ACTION) == MENU_CUSTOM_ACTION); - if (mretv & MENU_NEXT) { - retv = NEXT_DIALOG; - } else if (mretv & MENU_PREVIOUS) { - retv = PREVIOUS_DIALOG; - } else if (mretv & MENU_QUICK_SWITCH) { - retv = (mretv & MENU_LOWER_MASK); - } else if (mretv & MENU_CUSTOM_COMMAND) { + if (mretv & MENU_CUSTOM_COMMAND) { retv = (mretv & MENU_LOWER_MASK); } else if ((mretv & MENU_OK)) { if (selected_line < pd->array_length) { @@ -657,13 +651,7 @@ ModeMode file_browser_mode_completer(Mode *sw, int mretv, char **input, ModeMode retv = MODE_EXIT; FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *)mode_get_private_data(sw); - if (mretv & MENU_NEXT) { - retv = NEXT_DIALOG; - } else if (mretv & MENU_PREVIOUS) { - retv = PREVIOUS_DIALOG; - } else if (mretv & MENU_QUICK_SWITCH) { - retv = (mretv & MENU_LOWER_MASK); - } else if ((mretv & MENU_OK)) { + if ((mretv & MENU_OK)) { if (selected_line < pd->array_length) { if (pd->array[selected_line].type == UP) { GFile *new = g_file_get_parent(pd->current_dir); diff --git a/source/modes/recursivebrowser.c b/source/modes/recursivebrowser.c index 206fdf854..7cbd0f96d 100644 --- a/source/modes/recursivebrowser.c +++ b/source/modes/recursivebrowser.c @@ -351,13 +351,7 @@ static ModeMode recursive_browser_mode_result(Mode *sw, int mretv, G_GNUC_UNUSED return MODE_EXIT; } - if (mretv & MENU_NEXT) { - retv = NEXT_DIALOG; - } else if (mretv & MENU_PREVIOUS) { - retv = PREVIOUS_DIALOG; - } else if (mretv & MENU_QUICK_SWITCH) { - retv = (mretv & MENU_LOWER_MASK); - } else if (mretv & MENU_CUSTOM_COMMAND) { + if (mretv & MENU_CUSTOM_COMMAND) { retv = (mretv & MENU_LOWER_MASK); } else if ((mretv & MENU_OK)) { if (selected_line < pd->array_length) { @@ -495,13 +489,7 @@ ModeMode recursive_browser_mode_completer(Mode *sw, int mretv, char **input, ModeMode retv = MODE_EXIT; FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *)mode_get_private_data(sw); - if (mretv & MENU_NEXT) { - retv = NEXT_DIALOG; - } else if (mretv & MENU_PREVIOUS) { - retv = PREVIOUS_DIALOG; - } else if (mretv & MENU_QUICK_SWITCH) { - retv = (mretv & MENU_LOWER_MASK); - } else if ((mretv & MENU_OK)) { + if ((mretv & MENU_OK)) { if (selected_line < pd->array_length) { if (pd->array[selected_line].type == RFILE) { *path = g_strescape(pd->array[selected_line].path, NULL); From 04f16052a98414b20bf83677cfef3b306d6659f6 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Mon, 11 Mar 2024 12:04:08 +0100 Subject: [PATCH 02/13] [Run] Don't re-quote history items. --- source/modes/run.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/source/modes/run.c b/source/modes/run.c index 8af097467..cb6303654 100644 --- a/source/modes/run.c +++ b/source/modes/run.c @@ -66,6 +66,7 @@ typedef struct { char *entry; uint32_t icon_fetch_uid; uint32_t icon_fetch_size; + gboolean from_history; /* Surface holding the icon. */ cairo_surface_t *icon; } RunEntry; @@ -205,6 +206,7 @@ static RunEntry *get_apps_external(RunEntry *retv, unsigned int *length, // No duplicate, add it. retv = g_realloc(retv, ((*length) + 2) * sizeof(RunEntry)); retv[(*length)].entry = g_strdup(buffer); + retv[(*length)].from_history = FALSE; retv[(*length)].icon = NULL; retv[(*length)].icon_fetch_uid = 0; retv[(*length)].icon_fetch_size = 0; @@ -221,6 +223,7 @@ static RunEntry *get_apps_external(RunEntry *retv, unsigned int *length, } } retv[(*length)].entry = NULL; + retv[(*length)].from_history = FALSE; retv[(*length)].icon = NULL; retv[(*length)].icon_fetch_uid = 0; retv[(*length)].icon_fetch_size = 0; @@ -245,6 +248,7 @@ static RunEntry *get_apps(unsigned int *length) { retv = (RunEntry *)g_malloc0((*length + 1) * sizeof(RunEntry)); for (unsigned int i = 0; i < *length; i++) { retv[i].entry = hretv[i]; + retv[i].from_history = TRUE; } g_free(hretv); g_free(path); @@ -332,10 +336,12 @@ static RunEntry *get_apps(unsigned int *length) { retv = g_realloc(retv, ((*length) + 2) * sizeof(RunEntry)); retv[(*length)].entry = name; + retv[(*length)].from_history = FALSE; retv[(*length)].icon = NULL; retv[(*length)].icon_fetch_uid = 0; retv[(*length)].icon_fetch_size = 0; retv[(*length) + 1].entry = NULL; + retv[(*length) + 1].from_history = FALSE; retv[(*length) + 1].icon = NULL; retv[(*length) + 1].icon_fetch_uid = 0; retv[(*length) + 1].icon_fetch_size = 0; @@ -447,7 +453,12 @@ static ModeMode run_mode_result(Mode *sw, int mretv, char **input, &path); if (retv == MODE_EXIT) { if (path == NULL) { - char *arg = g_shell_quote(rmpd->cmd_list[rmpd->selected_line].entry); + char *arg; + if (rmpd->cmd_list[rmpd->selected_line].from_history) { + arg = g_strdup(rmpd->cmd_list[rmpd->selected_line].entry); + } else { + arg = g_shell_quote(rmpd->cmd_list[rmpd->selected_line].entry); + } exec_cmd(arg, run_in_term, rmpd->cmd_list[rmpd->selected_line].entry); g_free(arg); } else { @@ -466,7 +477,12 @@ static ModeMode run_mode_result(Mode *sw, int mretv, char **input, } if ((mretv & MENU_OK) && rmpd->cmd_list[selected_line].entry != NULL) { - char *earg = g_shell_quote(rmpd->cmd_list[selected_line].entry); + char *earg = NULL; + if (rmpd->cmd_list[selected_line].from_history) { + earg = g_strdup(rmpd->cmd_list[selected_line].entry); + } else { + earg = g_shell_quote(rmpd->cmd_list[selected_line].entry); + } if (!exec_cmd(earg, run_in_term, rmpd->cmd_list[selected_line].entry)) { retv = RELOAD_DIALOG; } From 1063b6ec05238341180de4aa704f9e59ab6c9da0 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Mon, 11 Mar 2024 12:32:12 +0100 Subject: [PATCH 03/13] [Run] Store display and exec string --- source/modes/run.c | 49 ++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/source/modes/run.c b/source/modes/run.c index cb6303654..0d4d2b848 100644 --- a/source/modes/run.c +++ b/source/modes/run.c @@ -60,10 +60,11 @@ /** * Name of the history file where previously chosen commands are stored. */ -#define RUN_CACHE_FILE "rofi-3.runcache" +#define RUN_CACHE_FILE "rofi-4.runcache" typedef struct { char *entry; + char *exec; uint32_t icon_fetch_uid; uint32_t icon_fetch_size; gboolean from_history; @@ -114,6 +115,7 @@ static gboolean exec_cmd(const char *cmd, int run_in_term, const char *orig) { char *path = g_build_filename(cache_dir, RUN_CACHE_FILE, NULL); RofiHelperExecuteContext context = {.name = NULL}; + char *hist = g_strdup_printf("%s\x1f%s", orig, cmd); // FIXME: assume startup notification support for terminals if (helper_execute_command(NULL, lf_cmd, run_in_term, run_in_term ? &context : NULL)) { @@ -122,12 +124,14 @@ static gboolean exec_cmd(const char *cmd, int run_in_term, const char *orig) { * It is allowed to be a bit slower. */ - history_set(path, orig); + history_set(path, hist); g_free(path); g_free(lf_cmd); + g_free(hist); return TRUE; } - history_remove(path, orig); + history_remove(path, hist); + g_free(hist); g_free(path); g_free(lf_cmd); return FALSE; @@ -141,8 +145,9 @@ static gboolean exec_cmd(const char *cmd, int run_in_term, const char *orig) { static void delete_entry(const RunEntry *cmd) { char *path = g_build_filename(cache_dir, RUN_CACHE_FILE, NULL); - history_remove(path, cmd->entry); - + char *hist = g_strdup_printf("%s\x1f%s", cmd->entry, cmd->exec); + history_remove(path, hist); + g_free(hist); g_free(path); } @@ -206,6 +211,7 @@ static RunEntry *get_apps_external(RunEntry *retv, unsigned int *length, // No duplicate, add it. retv = g_realloc(retv, ((*length) + 2) * sizeof(RunEntry)); retv[(*length)].entry = g_strdup(buffer); + retv[(*length)].exec = g_shell_quote(buffer); retv[(*length)].from_history = FALSE; retv[(*length)].icon = NULL; retv[(*length)].icon_fetch_uid = 0; @@ -223,6 +229,7 @@ static RunEntry *get_apps_external(RunEntry *retv, unsigned int *length, } } retv[(*length)].entry = NULL; + retv[(*length)].exec = NULL; retv[(*length)].from_history = FALSE; retv[(*length)].icon = NULL; retv[(*length)].icon_fetch_uid = 0; @@ -247,8 +254,14 @@ static RunEntry *get_apps(unsigned int *length) { char **hretv = history_get_list(path, length); retv = (RunEntry *)g_malloc0((*length + 1) * sizeof(RunEntry)); for (unsigned int i = 0; i < *length; i++) { - retv[i].entry = hretv[i]; + gchar **rs = g_strsplit(hretv[i], "\x1f", 2); + retv[i].entry = rs[0]; + retv[i].exec = rs[1]; + if (retv[i].exec == NULL) { + retv[i].exec = g_strdup(rs[0]); + } retv[i].from_history = TRUE; + g_free(rs); } g_free(hretv); g_free(path); @@ -263,6 +276,7 @@ static RunEntry *get_apps(unsigned int *length) { g_debug("Failed to convert homedir to UTF-8: %s", error->message); for (unsigned int i = 0; retv[i].entry != NULL; i++) { g_free(retv[i].entry); + g_free(retv[i].exec); } g_free(retv); g_clear_error(&error); @@ -336,11 +350,13 @@ static RunEntry *get_apps(unsigned int *length) { retv = g_realloc(retv, ((*length) + 2) * sizeof(RunEntry)); retv[(*length)].entry = name; + retv[(*length)].exec = g_shell_quote(name); retv[(*length)].from_history = FALSE; retv[(*length)].icon = NULL; retv[(*length)].icon_fetch_uid = 0; retv[(*length)].icon_fetch_size = 0; retv[(*length) + 1].entry = NULL; + retv[(*length) + 1].exec = NULL; retv[(*length) + 1].from_history = FALSE; retv[(*length) + 1].icon = NULL; retv[(*length) + 1].icon_fetch_uid = 0; @@ -373,6 +389,8 @@ static RunEntry *get_apps(unsigned int *length) { if (g_strcmp0(retv[index].entry, retv[index + 1].entry) == 0) { g_free(retv[index].entry); retv[index].entry = NULL; + g_free(retv[index].exec); + retv[index].exec = NULL; removed++; } } @@ -403,6 +421,7 @@ static void run_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].exec); if (rmpd->cmd_list[i].icon != NULL) { cairo_surface_destroy(rmpd->cmd_list[i].icon); } @@ -453,21 +472,14 @@ static ModeMode run_mode_result(Mode *sw, int mretv, char **input, &path); if (retv == MODE_EXIT) { if (path == NULL) { - char *arg; - if (rmpd->cmd_list[rmpd->selected_line].from_history) { - arg = g_strdup(rmpd->cmd_list[rmpd->selected_line].entry); - } else { - arg = g_shell_quote(rmpd->cmd_list[rmpd->selected_line].entry); - } + char *arg = rmpd->cmd_list[rmpd->selected_line].exec; exec_cmd(arg, run_in_term, rmpd->cmd_list[rmpd->selected_line].entry); - g_free(arg); } else { - char *earg = g_shell_quote(rmpd->cmd_list[rmpd->selected_line].entry); + char *earg = rmpd->cmd_list[rmpd->selected_line].exec; char *epath = g_shell_quote(path); char *arg = g_strdup_printf("%s %s", earg, epath); exec_cmd(arg, run_in_term, arg); g_free(arg); - g_free(earg); g_free(epath); } } @@ -478,15 +490,10 @@ static ModeMode run_mode_result(Mode *sw, int mretv, char **input, if ((mretv & MENU_OK) && rmpd->cmd_list[selected_line].entry != NULL) { char *earg = NULL; - if (rmpd->cmd_list[selected_line].from_history) { - earg = g_strdup(rmpd->cmd_list[selected_line].entry); - } else { - earg = g_shell_quote(rmpd->cmd_list[selected_line].entry); - } + earg = rmpd->cmd_list[selected_line].exec; if (!exec_cmd(earg, run_in_term, rmpd->cmd_list[selected_line].entry)) { retv = RELOAD_DIALOG; } - g_free(earg); } else if ((mretv & MENU_CUSTOM_INPUT) && *input != NULL && *input[0] != '\0') { if (!exec_cmd(*input, run_in_term, *input)) { From 76154cc1ff47ad47ecc8477cf631304616f5b6da Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Mon, 11 Mar 2024 15:48:25 +0100 Subject: [PATCH 04/13] [Doc] Fix typo in issue template. --- .github/ISSUE_TEMPLATE/bug_report.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 39b3dd4dd..df1c8031c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -13,7 +13,7 @@ body: consider you’re wrong and still fill the full report. Any report missing required informations will be labeled as “Incomplete Report - Please follow the guidelines” and will be closed. If you ask a - question, enter dummy information in required fields to get passed the + question, enter dummy information in required fields to get past the checks or in general completely ignore the guidelines, the issue will be closed and locked as spam. @@ -37,21 +37,26 @@ body: - type: input attributes: label: "Configuration" - description: "Please use https://gist.github.com and include output of `rofi -dump-config`." + description: | + Please use https://gist.github.com and include output of `rofi -dump-config`. + n/a is not a valid theme. placeholder: "Gist URL" validations: required: true - type: input attributes: label: "Theme" - description: "Please use https://gist.github.com and include output of `rofi -dump-theme`." + description: | + Please use https://gist.github.com and include output of `rofi -dump-theme`. + n/a is not a valid config. placeholder: "Gist URL" validations: required: true - type: input attributes: label: "Timing report" - description: "Please use https://gist.github.com and include output of your command with G_MESSAGES_DEBUG=Timings set." + description: | + Please use https://gist.github.com and include output of your command with G_MESSAGES_DEBUG=Timings set. placeholder: "Gist URL" validations: required: false From 839ee0d7d9a88a4133e6e520f5ef679c727ee689 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Mon, 11 Mar 2024 15:49:19 +0100 Subject: [PATCH 05/13] [Doc] Fix copy/paste error in template. --- .github/ISSUE_TEMPLATE/bug_report.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index df1c8031c..59d4e4714 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -39,7 +39,7 @@ body: label: "Configuration" description: | Please use https://gist.github.com and include output of `rofi -dump-config`. - n/a is not a valid theme. + n/a is not a valid config. placeholder: "Gist URL" validations: required: true @@ -48,7 +48,7 @@ body: label: "Theme" description: | Please use https://gist.github.com and include output of `rofi -dump-theme`. - n/a is not a valid config. + n/a is not a valid theme. placeholder: "Gist URL" validations: required: true From 81e06d715786219c66d20289e17cd8867ecee70c Mon Sep 17 00:00:00 2001 From: Qball Cow Date: Wed, 13 Mar 2024 07:18:08 +0100 Subject: [PATCH 06/13] [github] bump lock-threads flow version --- .github/workflows/lock.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index fd536cb27..fdc2a3191 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -8,7 +8,7 @@ jobs: lock: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v2 + - uses: dessant/lock-threads@v5 with: github-token: ${{ secrets.GITHUB_TOKEN }} issue-lock-inactive-days: '31' From 94f8c88336fcfe81bd9c51dcd9628add8b34aeca Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Fri, 15 Mar 2024 10:29:04 +0100 Subject: [PATCH 07/13] [github] update lock config. --- .github/workflows/lock.yml | 47 +++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index fdc2a3191..2636ca100 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -1,32 +1,41 @@ -name: 'Lock threads' +name: 'Lock Threads' on: schedule: - cron: '0 0 * * *' + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + discussions: write + +concurrency: + group: lock-threads jobs: - lock: + action: runs-on: ubuntu-latest steps: - uses: dessant/lock-threads@v5 with: - github-token: ${{ secrets.GITHUB_TOKEN }} - issue-lock-inactive-days: '31' - issue-exclude-created-before: '' - issue-exclude-labels: '' - issue-lock-labels: '' - issue-lock-reason: 'resolved' - issue-lock-comment: > - This issue has been automatically locked since there - has not been any recent activity after it was closed. - Please open a new issue for related bugs. - pr-lock-inactive-days: '31' - pr-exclude-created-before: '' - pr-exclude-labels: '' - pr-lock-labels: '' - pr-lock-reason: 'resolved' - pr-lock-comment: > + process-only: 'issues' + github-token: ${{ github.token }} + issue-inactive-days: '31' + exclude-issue-created-before: '' + exclude-issue-created-after: '' + exclude-issue-created-between: '' + exclude-issue-closed-before: '' + exclude-issue-closed-after: '' + exclude-issue-closed-between: '' + include-any-issue-labels: '' + include-all-issue-labels: '' + exclude-any-issue-labels: '' + add-issue-labels: '' + remove-issue-labels: '' + issue-comment: > This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. - process-only: '' + issue-lock-reason: 'resolved' + log-output: false From 6c38a49d543633e736d4e1653c0b02fe29e46ffd Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Sat, 16 Mar 2024 11:53:12 +0100 Subject: [PATCH 08/13] [Doc] Fix typo, thx to @Nickwiz --- doc/rofi-script.5.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rofi-script.5.markdown b/doc/rofi-script.5.markdown index 53a463d2f..527c07a0d 100644 --- a/doc/rofi-script.5.markdown +++ b/doc/rofi-script.5.markdown @@ -143,7 +143,7 @@ The following options are supported: - **nonselectable**: If true the row cannot activated. -- **permantent**: If true the row always shows, independent of filter. +- **permanent**: If true the row always shows, independent of filter. - **info**: Info that, on selection, gets placed in the `ROFI_INFO` environment variable. This entry does not get searched for filtering. From 4f098751cd8a328e5b8d034113aae1420fee1c8d Mon Sep 17 00:00:00 2001 From: martinsifrar <53146732+martinsifrar@users.noreply.github.com> Date: Mon, 15 Apr 2024 12:56:09 +0200 Subject: [PATCH 09/13] [IconFetcher] Fix failing decode of animated GIFs. (#1975) --- source/rofi-icon-fetcher.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/rofi-icon-fetcher.c b/source/rofi-icon-fetcher.c index ef19bf5ff..106f8f10a 100644 --- a/source/rofi-icon-fetcher.c +++ b/source/rofi-icon-fetcher.c @@ -365,6 +365,17 @@ static void rofi_icon_fetcher_worker(thread_state *sdata, GError *error = NULL; GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale( icon_path, sentry->wsize, sentry->hsize, TRUE, &error); + + /* + * The GIF codec throws GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION if it's closed + * without decoding all the frames. Since gdk_pixbuf_new_from_file_at_scale + * only decodes the first frame, this specific error needs to be ignored. + */ + if (error != NULL && g_error_matches( + error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION)) { + g_clear_error(&error); + } + if (error != NULL) { g_warning("Failed to load image: |%s| %d %d %s (%p)", icon_path, sentry->wsize, sentry->hsize, error->message, (void *)pb); From 9b6e70b365116935158413034cf2aeb16affd9d4 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Thu, 18 Apr 2024 22:32:50 +0200 Subject: [PATCH 10/13] [IconFetcher] Don't check for extension for image file. Issue: 1977 --- source/rofi-icon-fetcher.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/rofi-icon-fetcher.c b/source/rofi-icon-fetcher.c index 106f8f10a..ef5847a93 100644 --- a/source/rofi-icon-fetcher.c +++ b/source/rofi-icon-fetcher.c @@ -354,6 +354,7 @@ static void rofi_icon_fetcher_worker(thread_state *sdata, } cairo_surface_t *icon_surf = NULL; +#if 0 // unsure why added in past? const char *suf = strrchr(icon_path, '.'); if (suf == NULL) { sentry->query_done = TRUE; @@ -361,6 +362,7 @@ static void rofi_icon_fetcher_worker(thread_state *sdata, rofi_view_reload(); return; } +#endif GError *error = NULL; GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale( @@ -371,9 +373,9 @@ static void rofi_icon_fetcher_worker(thread_state *sdata, * without decoding all the frames. Since gdk_pixbuf_new_from_file_at_scale * only decodes the first frame, this specific error needs to be ignored. */ - if (error != NULL && g_error_matches( - error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION)) { - g_clear_error(&error); + if (error != NULL && g_error_matches(error, GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION)) { + g_clear_error(&error); } if (error != NULL) { From 5b9939b287b86255f9dcac1b10f3990b187875f9 Mon Sep 17 00:00:00 2001 From: ortango <8408464+ortango@users.noreply.github.com> Date: Thu, 25 Apr 2024 10:14:39 -0400 Subject: [PATCH 11/13] Add border_width to window coordinates (#1969) * Update xcb.c window coors relative to border_width. * Add border_width to window coordinates Normalize the geometry between reparenting and non- window managers. * remove WM_ROOT_WINDOW_OFFSET * remove WM_ROOT_WINDOW_OFFSET * only translate reparent --- include/xcb.h | 2 -- source/xcb.c | 61 +++++++++++++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/include/xcb.h b/include/xcb.h index d56b2cf36..b4a7a3bad 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -209,8 +209,6 @@ typedef enum { WM_DO_NOT_CHANGE_CURRENT_DESKTOP = 1, /** PANGO WORKSPACE NAMES */ WM_PANGO_WORKSPACE_NAMES = 2, - /** Root window offset (for bspwm) */ - WM_ROOT_WINDOW_OFFSET = 4, } WindowManagerQuirk; /** diff --git a/source/xcb.c b/source/xcb.c index ccdec05af..2b50ccb0c 100644 --- a/source/xcb.c +++ b/source/xcb.c @@ -881,37 +881,38 @@ static int monitor_active_from_id_focused(int mon_id, workarea *mon) { free(tree_reply); return retv; } - xcb_translate_coordinates_cookie_t ct = xcb_translate_coordinates( - xcb->connection, tree_reply->parent, r->root, r->x, r->y); - xcb_translate_coordinates_reply_t *t = - xcb_translate_coordinates_reply(xcb->connection, ct, NULL); - if (t) { - if (mon_id == -2) { - // place the menu above the window - // if some window is focused, place menu above window, else fall - // back to selected monitor. - mon->x = t->dst_x - r->x; - mon->y = t->dst_y - r->y; - mon->w = r->width; - mon->h = r->height; - retv = TRUE; - if ((current_window_manager & WM_ROOT_WINDOW_OFFSET) == - WM_ROOT_WINDOW_OFFSET) { - mon->x += r->x; - mon->y += r->y; - } - g_debug("mon pos: %d %d %d-%d", mon->x, mon->y, mon->w, mon->h); - } else if (mon_id == -4) { - g_debug("Find monitor at location: %d %d", t->dst_x, t->dst_y); - monitor_dimensions(t->dst_x, t->dst_y, mon); - g_debug("Monitor found pos: %d %d %d-%d", mon->x, mon->y, mon->w, mon->h); - retv = TRUE; + if (tree_reply->parent != r->root) { + xcb_translate_coordinates_cookie_t ct = xcb_translate_coordinates( + xcb->connection, tree_reply->parent, r->root, r->x, r->y); + xcb_translate_coordinates_reply_t *t = + xcb_translate_coordinates_reply(xcb->connection, ct, NULL); + if (t) { + r->x = t->dst_x; + r->y = t->dst_y; + free(t); + } else { + g_debug("Failed to get translate position of active window, falling back " + "to mouse location (-5)."); + free(r); + free(tree_reply); + return retv; } - free(t); - } else { - g_debug("Failed to get translate position of active window, falling back " - "to mouse location (-5)."); } + if (mon_id == -2) { + // place the menu above the window + // if some window is focused, place menu above window, else fall + // back to selected monitor. + mon->x = r->x + r->border_width; + mon->y = r->y + r->border_width; + mon->w = r->width; + mon->h = r->height; + retv = TRUE; + } else if (mon_id == -4) { + g_debug("Find monitor at location: %d %d", r->x, r->y); + monitor_dimensions(r->x, r->y, mon); + retv = TRUE; + } + g_debug("mon pos: %d %d %d-%d", mon->x, mon->y, mon->w, mon->h); free(r); free(tree_reply); return retv; @@ -1642,8 +1643,6 @@ static void x11_helper_discover_window_manager(void) { if (g_strcmp0(str, "i3") == 0) { current_window_manager = WM_DO_NOT_CHANGE_CURRENT_DESKTOP | WM_PANGO_WORKSPACE_NAMES; - } else if (g_strcmp0(str, "bspwm") == 0) { - current_window_manager = WM_ROOT_WINDOW_OFFSET; } g_free(str); } From 9580c4a1915c68cd52211a6906c83a0d957d6728 Mon Sep 17 00:00:00 2001 From: Qball Cow Date: Sun, 12 May 2024 13:41:32 +0200 Subject: [PATCH 12/13] [RecursiveBrowser] Make implementation not recursive. Do stat when DT_UNKNOWN is given back when reading directory. Issue: #1954 --- source/modes/recursivebrowser.c | 202 ++++++++++++++++++++------------ 1 file changed, 128 insertions(+), 74 deletions(-) diff --git a/source/modes/recursivebrowser.c b/source/modes/recursivebrowser.c index 7cbd0f96d..4a4ce6d5e 100644 --- a/source/modes/recursivebrowser.c +++ b/source/modes/recursivebrowser.c @@ -178,81 +178,134 @@ static void recursive_browser_mode_init_current_dir(Mode *sw) { } static void scan_dir(FileBrowserModePrivateData *pd, GFile *path) { - char *cdir = g_file_get_path(path); - DIR *dir = opendir(cdir); - if (dir) { - struct dirent *rd = NULL; - while (pd->end_thread == FALSE && (rd = readdir(dir)) != NULL) { - if (g_strcmp0(rd->d_name, "..") == 0) { - continue; - } - if (g_strcmp0(rd->d_name, ".") == 0) { - continue; - } - if (pd->filter_regex && - g_regex_match(pd->filter_regex, rd->d_name, 0, NULL)) { - continue; - } - switch (rd->d_type) { - case DT_BLK: - case DT_CHR: - case DT_FIFO: - case DT_UNKNOWN: - case DT_SOCK: - default: - break; - case DT_REG: { - FBFile *f = g_malloc0(sizeof(FBFile)); - // Rofi expects utf-8, so lets convert the filename. - f->path = g_build_filename(cdir, rd->d_name, NULL); - f->name = g_filename_to_utf8(f->path, -1, NULL, NULL, NULL); - if (f->name == NULL) { - f->name = rofi_force_utf8(rd->d_name, -1); - } - f->type = (rd->d_type == DT_DIR) ? DIRECTORY : RFILE; - f->icon_fetch_uid = 0; - f->icon_fetch_size = 0; - f->link = FALSE; - - g_async_queue_push(pd->async_queue, f); - if (g_async_queue_length(pd->async_queue) > 10000) { - write(pd->pipefd2[1], "r", 1); - } - break; - } - case DT_DIR: { - char *d = g_build_filename(cdir, rd->d_name, NULL); - GFile *dirp = g_file_new_for_path(d); - scan_dir(pd, dirp); - g_object_unref(dirp); - g_free(d); - break; - } - case DT_LNK: { - FBFile *f = g_malloc0(sizeof(FBFile)); - // Rofi expects utf-8, so lets convert the filename. - f->path = g_build_filename(cdir, rd->d_name, NULL); - f->name = g_filename_to_utf8(f->path, -1, NULL, NULL, NULL); - if (f->name == NULL) { - f->name = rofi_force_utf8(rd->d_name, -1); - } - f->icon_fetch_uid = 0; - f->icon_fetch_size = 0; - f->link = TRUE; - // Default to file. - f->type = RFILE; - g_async_queue_push(pd->async_queue, f); - if (g_async_queue_length(pd->async_queue) > 10000) { - write(pd->pipefd2[1], "r", 1); - } - break; - } - } - } - closedir(dir); + GQueue *dirs_to_scan = g_queue_new(); + g_queue_push_tail(dirs_to_scan, g_object_ref(path)); + GFile *dir_to_scan = NULL; + while ( (dir_to_scan = g_queue_pop_head(dirs_to_scan)) != NULL) { + char *cdir = g_file_get_path(dir_to_scan); + DIR *dir = opendir(cdir); + g_object_unref(dir_to_scan); + if (dir) { + struct dirent *rd = NULL; + while (pd->end_thread == FALSE && (rd = readdir(dir)) != NULL) { + if (g_strcmp0(rd->d_name, "..") == 0) { + continue; + } + if (g_strcmp0(rd->d_name, ".") == 0) { + continue; + } + if (pd->filter_regex && + g_regex_match(pd->filter_regex, rd->d_name, 0, NULL)) { + continue; + } + switch (rd->d_type) { + case DT_BLK: + case DT_CHR: + case DT_FIFO: + case DT_SOCK: + default: + break; + case DT_REG: { + FBFile *f = g_malloc0(sizeof(FBFile)); + // Rofi expects utf-8, so lets convert the filename. + f->path = g_build_filename(cdir, rd->d_name, NULL); + f->name = g_filename_to_utf8(f->path, -1, NULL, NULL, NULL); + if (f->name == NULL) { + f->name = rofi_force_utf8(rd->d_name, -1); + } + if (f->name == NULL) { + f->name = g_strdup("n/a"); + } + f->type = (rd->d_type == DT_DIR) ? DIRECTORY : RFILE; + f->icon_fetch_uid = 0; + f->icon_fetch_size = 0; + f->link = FALSE; + + g_async_queue_push(pd->async_queue, f); + if (g_async_queue_length(pd->async_queue) > 10000) { + write(pd->pipefd2[1], "r", 1); + } + break; + } + case DT_DIR: { + char *d = g_build_filename(cdir, rd->d_name, NULL); + GFile *dirp = g_file_new_for_path(d); + g_queue_push_tail(dirs_to_scan, dirp); + g_free(d); + break; + } + case DT_UNKNOWN: + case DT_LNK: { + FBFile *f = g_malloc0(sizeof(FBFile)); + // Rofi expects utf-8, so lets convert the filename. + f->path = g_build_filename(cdir, rd->d_name, NULL); + f->name = g_filename_to_utf8(f->path, -1, NULL, NULL, NULL); + if (f->name == NULL) { + f->name = rofi_force_utf8(rd->d_name, -1); + } + if (f->name == NULL) { + f->name = g_strdup("n/a"); + } + f->icon_fetch_uid = 0; + f->icon_fetch_size = 0; + // Default to file. + f->type = RFILE; + if (rd->d_type == DT_LNK) { + f->link = TRUE; + } else { + f->link = FALSE; + } + { + // If we have link, use a stat to fine out what it is, if we fail, we + // mark it as file. + // TODO have a 'broken link' mode? + // Convert full path to right encoding. + // DD: Path should be in file encoding, not utf-8 + // char *file = + // g_filename_from_utf8(pd->array[pd->array_length].path, + // -1, NULL, NULL, NULL); + // TODO: How to handle loops in links. + if (f->path) { + GStatBuf statbuf; + if (g_stat(f->path, &statbuf) == 0) { + if (S_ISDIR(statbuf.st_mode)) { + char *new_full_path = g_build_filename(cdir, rd->d_name, NULL); + g_free(f->path); + g_free(f->name); + g_free(f); + f = NULL; + GFile *dirp = g_file_new_for_path(new_full_path); + g_queue_push_tail(dirs_to_scan, dirp); + g_free(new_full_path); + break; + } else if (S_ISREG(statbuf.st_mode)) { + f->type = RFILE; + } + + } else { + g_warning("Failed to stat file: %s, %s", f->path, + strerror(errno)); + } + + // g_free(file); + } + } + if (f != NULL) { + g_async_queue_push(pd->async_queue, f); + if (g_async_queue_length(pd->async_queue) > 10000) { + write(pd->pipefd2[1], "r", 1); + } + } + break; + } + } + } + closedir(dir); + } + g_free(cdir); } - g_free(cdir); + g_queue_free(dirs_to_scan); } static gpointer recursive_browser_input_thread(gpointer userdata) { FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *)userdata; @@ -335,7 +388,8 @@ static unsigned int recursive_browser_mode_get_num_entries(const Mode *sw) { return pd->array_length; } -static ModeMode recursive_browser_mode_result(Mode *sw, int mretv, G_GNUC_UNUSED char **input, +static ModeMode recursive_browser_mode_result(Mode *sw, int mretv, + G_GNUC_UNUSED char **input, unsigned int selected_line) { ModeMode retv = MODE_EXIT; FileBrowserModePrivateData *pd = From dee97eb540506a3de2946bf5b7f2533a9480d427 Mon Sep 17 00:00:00 2001 From: Qball Cow Date: Sun, 12 May 2024 21:35:26 +0200 Subject: [PATCH 13/13] [Script] Fix keep-selection add keep-filter Fixes: #1962 --- doc/rofi-script.5.markdown | 2 ++ source/modes/script.c | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/doc/rofi-script.5.markdown b/doc/rofi-script.5.markdown index 527c07a0d..4e1a31e03 100644 --- a/doc/rofi-script.5.markdown +++ b/doc/rofi-script.5.markdown @@ -109,6 +109,8 @@ The following extra options exists: - **keep-selection**: If set, the selection is not moved to the first entry, but the current position is maintained. The filter is cleared. +- **keep-filter**: If set, the filter is not cleared. + - **new-selection**: If `keep-selection` is set, this allows you to override the selected entry (absolute position). diff --git a/source/modes/script.c b/source/modes/script.c index f98117041..6ca29813e 100644 --- a/source/modes/script.c +++ b/source/modes/script.c @@ -72,6 +72,8 @@ typedef struct { char delim; /** no custom */ gboolean no_custom; + /** keep filter */ + gboolean keep_filter; gboolean use_hot_keys; } ScriptModePrivateData; @@ -157,6 +159,8 @@ static void parse_header_entry(Mode *sw, char *line, ssize_t length) { pd->use_hot_keys = (strcasecmp(value, "true") == 0); } else if (strcasecmp(line, "keep-selection") == 0) { pd->keep_selection = (strcasecmp(value, "true") == 0); + } else if (strcasecmp(line, "keep-filter") == 0) { + pd->keep_filter = (strcasecmp(value, "true") == 0); } else if (strcasecmp(line, "new-selection") == 0) { pd->new_selection = (int64_t)g_ascii_strtoll(value, NULL, 0); } else if (strcasecmp(line, "data") == 0) { @@ -184,6 +188,7 @@ static DmenuScriptEntry *execute_executor(Mode *sw, char *arg, // Reset these between runs. pd->new_selection = -1; pd->keep_selection = 0; + pd->keep_filter = 0; // Environment char **env = g_get_environ(); @@ -320,6 +325,9 @@ static ModeMode script_mode_result(Mode *sw, int mretv, char **input, ModeMode retv = MODE_EXIT; DmenuScriptEntry *new_list = NULL; unsigned int new_length = 0; + // store them as they might be different on next executor and reset. + gboolean keep_filter = rmpd->keep_filter; + gboolean keep_selection = rmpd->keep_selection; if ((mretv & MENU_CUSTOM_COMMAND)) { if (rmpd->use_hot_keys) { @@ -370,7 +378,7 @@ static ModeMode script_mode_result(Mode *sw, int mretv, char **input, rmpd->cmd_list = new_list; rmpd->cmd_list_length = new_length; - if (rmpd->keep_selection) { + if (keep_selection) { if (rmpd->new_selection >= 0 && rmpd->new_selection < rmpd->cmd_list_length) { rofi_view_set_selected_line(rofi_view_get_active(), @@ -378,12 +386,14 @@ static ModeMode script_mode_result(Mode *sw, int mretv, char **input, } else { rofi_view_set_selected_line(rofi_view_get_active(), selected_line); } + } else { + rofi_view_set_selected_line(rofi_view_get_active(), 0); + } + if (keep_filter == FALSE) { g_free(*input); *input = NULL; - retv = RELOAD_DIALOG; - } else { - retv = RESET_DIALOG; } + retv = RELOAD_DIALOG; } return retv; }