diff options
-rw-r--r-- | doc/rofi-script.5.markdown | 2 | ||||
-rw-r--r-- | include/xcb.h | 2 | ||||
-rw-r--r-- | source/modes/recursivebrowser.c | 202 | ||||
-rw-r--r-- | source/modes/script.c | 18 | ||||
-rw-r--r-- | source/rofi-icon-fetcher.c | 8 | ||||
-rw-r--r-- | source/xcb.c | 61 |
6 files changed, 179 insertions, 114 deletions
diff --git a/doc/rofi-script.5.markdown b/doc/rofi-script.5.markdown index 527c07a0..4e1a31e0 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/include/xcb.h b/include/xcb.h index d56b2cf3..b4a7a3ba 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/modes/recursivebrowser.c b/source/modes/recursivebrowser.c index 7cbd0f96..4a4ce6d5 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 = diff --git a/source/modes/script.c b/source/modes/script.c index f9811704..6ca29813 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; } diff --git a/source/rofi-icon-fetcher.c b/source/rofi-icon-fetcher.c index 106f8f10..ef5847a9 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) { diff --git a/source/xcb.c b/source/xcb.c index ccdec05a..2b50ccb0 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); } |