summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/rofi-script.5.markdown2
-rw-r--r--include/xcb.h2
-rw-r--r--source/modes/recursivebrowser.c202
-rw-r--r--source/modes/script.c18
-rw-r--r--source/rofi-icon-fetcher.c8
-rw-r--r--source/xcb.c61
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);
}