diff --git a/inc/wofi.h b/inc/wofi.h index d8cefef..44385f5 100644 --- a/inc/wofi.h +++ b/inc/wofi.h @@ -52,7 +52,7 @@ void wofi_remove_cache(const gchar* mode, const gchar* cmd); struct wl_list* wofi_read_cache(char* mode); -void wofi_insert_widget(char* mode, char** text, char* search_text, char** actions, size_t action_count); +struct widget* wofi_create_widget(char* mode, char** text, char* search_text, char** actions, size_t action_count); bool wofi_allow_images(void); diff --git a/modes/dmenu.c b/modes/dmenu.c index 1554d76..3d97e26 100644 --- a/modes/dmenu.c +++ b/modes/dmenu.c @@ -23,9 +23,18 @@ static const char* arg_names[] = {"parse_action"}; static bool parse_action; +struct node { + struct widget* widget; + struct wl_list link; +}; + +static struct wl_list widgets; + void wofi_dmenu_init(struct map* config) { parse_action = strcmp(config_get(config, "parse_action", "false"), "true") == 0; + wl_list_init(&widgets); + struct map* cached = map_init(); struct wl_list* cache = wofi_read_cache(MODE); @@ -52,7 +61,9 @@ void wofi_dmenu_init(struct map* config) { wl_list_for_each_safe(node, tmp, cache, link) { if(map_contains(entry_map, node->line)) { map_put(cached, node->line, "true"); - wofi_insert_widget(MODE, &node->line, node->line, &node->line, 1); + struct node* widget = malloc(sizeof(struct node)); + widget->widget = wofi_create_widget(MODE, &node->line, node->line, &node->line, 1); + wl_list_insert(&widgets, &widget->link); } else { wofi_remove_cache(MODE, node->line); } @@ -66,7 +77,9 @@ void wofi_dmenu_init(struct map* config) { wl_list_for_each_reverse_safe(node, tmp, &entries, link) { if(!map_contains(cached, node->line)) { - wofi_insert_widget(MODE, &node->line, node->line, &node->line, 1); + struct node* widget = malloc(sizeof(struct node)); + widget->widget = wofi_create_widget(MODE, &node->line, node->line, &node->line, 1); + wl_list_insert(&widgets, &widget->link); } free(node->line); wl_list_remove(&node->link); @@ -75,6 +88,17 @@ void wofi_dmenu_init(struct map* config) { map_free(cached); } +struct widget* wofi_dmenu_get_widget() { + struct node* node, *tmp; + wl_list_for_each_reverse_safe(node, tmp, &widgets, link) { + struct widget* widget = node->widget; + wl_list_remove(&node->link); + free(node); + return widget; + } + return NULL; +} + void wofi_dmenu_exec(const gchar* cmd) { char* action = strdup(cmd); if(parse_action) { diff --git a/modes/drun.c b/modes/drun.c index 9c288d9..3ebcbad 100644 --- a/modes/drun.c +++ b/modes/drun.c @@ -19,6 +19,13 @@ #define MODE "drun" +struct node { + struct widget* widget; + struct wl_list link; +}; + +static struct wl_list widgets; + static char* get_text(char* file, char* action) { GDesktopAppInfo* info = g_desktop_app_info_new_from_filename(file); if(info == NULL || g_desktop_app_info_get_is_hidden(info) || g_desktop_app_info_get_nodisplay(info)) { @@ -197,7 +204,10 @@ static void insert_dir(char* app_dir, struct map* cached, struct map* entries) { char** actions = get_action_actions(full_path, &action_count); char* search_text = get_search_text(full_path); - wofi_insert_widget(MODE, text, search_text, actions, action_count); + + struct node* node = malloc(sizeof(struct node)); + node->widget = wofi_create_widget(MODE, text, search_text, actions, action_count); + wl_list_insert(&widgets, &node->link); for(size_t count = 0; count < action_count; ++count) { free(actions[count]); @@ -218,6 +228,8 @@ void wofi_drun_init(void) { struct map* entries = map_init(); struct wl_list* cache = wofi_read_cache(MODE); + wl_list_init(&widgets); + struct cache_line* node, *tmp; wl_list_for_each_safe(node, tmp, cache, link) { size_t action_count; @@ -230,7 +242,9 @@ void wofi_drun_init(void) { char** actions = get_action_actions(node->line, &action_count); char* search_text = get_search_text(node->line); - wofi_insert_widget(MODE, text, search_text, actions, action_count); + struct node* widget = malloc(sizeof(struct node)); + widget->widget = wofi_create_widget(MODE, text, search_text, actions, action_count); + wl_list_insert(&widgets, &widget->link); char* id = get_id(node->line); @@ -280,6 +294,17 @@ void wofi_drun_init(void) { map_free(entries); } +struct widget* wofi_drun_get_widget() { + struct node* node, *tmp; + wl_list_for_each_reverse_safe(node, tmp, &widgets, link) { + struct widget* widget = node->widget; + wl_list_remove(&node->link); + free(node); + return widget; + } + return NULL; +} + static void launch_done(GObject* obj, GAsyncResult* result, gpointer data) { if(g_app_info_launch_uris_finish(G_APP_INFO(obj), result, NULL)) { exit(0); diff --git a/modes/run.c b/modes/run.c index 8379f63..29795fa 100644 --- a/modes/run.c +++ b/modes/run.c @@ -24,10 +24,19 @@ static const char* arg_names[] = {"always_parse_args", "show_all"}; static bool always_parse_args; static bool show_all; +struct node { + struct widget* widget; + struct wl_list link; +}; + +static struct wl_list widgets; + void wofi_run_init(struct map* config) { always_parse_args = strcmp(config_get(config, arg_names[0], "false"), "true") == 0; show_all = strcmp(config_get(config, arg_names[1], "true"), "true") == 0; + wl_list_init(&widgets); + struct map* cached = map_init(); struct wl_list* cache = wofi_read_cache(MODE); @@ -45,7 +54,9 @@ void wofi_run_init(struct map* config) { struct stat info; stat(node->line, &info); if(access(node->line, X_OK) == 0 && S_ISREG(info.st_mode)) { - wofi_insert_widget(MODE, &text, text, &node->line, 1); + struct node* widget = malloc(sizeof(struct node)); + widget->widget = wofi_create_widget(MODE, &text, text, &node->line, 1); + wl_list_insert(&widgets, &widget->link); map_put(cached, node->line, "true"); map_put(entries, text, "true"); } else { @@ -78,7 +89,9 @@ void wofi_run_init(struct map* config) { if(access(full_path, X_OK) == 0 && S_ISREG(info.st_mode) && !map_contains(cached, full_path) && (show_all || !map_contains(entries, entry->d_name))) { char* text = strdup(entry->d_name); map_put(entries, text, "true"); - wofi_insert_widget(MODE, &text, text, &full_path, 1); + struct node* widget = malloc(sizeof(struct node)); + widget->widget = wofi_create_widget(MODE, &text, text, &full_path, 1); + wl_list_insert(&widgets, &widget->link); free(text); } free(full_path); @@ -90,6 +103,17 @@ void wofi_run_init(struct map* config) { map_free(entries); } +struct widget* wofi_run_get_widget() { + struct node* node, *tmp; + wl_list_for_each_reverse_safe(node, tmp, &widgets, link) { + struct widget* widget = node->widget; + wl_list_remove(&node->link); + free(node); + return widget; + } + return NULL; +} + void wofi_run_exec(const gchar* cmd) { if(wofi_mod_shift()) { wofi_write_cache(MODE, cmd); diff --git a/src/wofi.c b/src/wofi.c index 2124b80..17031d4 100644 --- a/src/wofi.c +++ b/src/wofi.c @@ -62,13 +62,14 @@ static struct map* config; static enum locations location; static bool no_actions; -struct node { - size_t action_count; - char* mode, **text, *search_text, **actions; -}; - struct mode { void (*mode_exec)(const gchar* cmd); + struct widget* (*mode_get_widget)(); +}; + +struct widget { + size_t action_count; + char* mode, **text, *search_text, **actions; }; static void nop() {} @@ -355,7 +356,16 @@ static void expand(GtkExpander* expander, gpointer data) { } static gboolean _insert_widget(gpointer data) { - struct node* node = data; + struct mode* mode = data; + struct widget* node; + if(mode->mode_get_widget == NULL) { + return FALSE; + } else { + node = mode->mode_get_widget(); + } + if(node == NULL) { + return FALSE; + } GtkWidget* parent; if(node->action_count > 1 && !no_actions) { parent = gtk_expander_new(""); @@ -393,7 +403,7 @@ static gboolean _insert_widget(gpointer data) { } free(node->actions); free(node); - return FALSE; + return TRUE; } void wofi_write_cache(const gchar* mode, const gchar* cmd) { @@ -539,8 +549,8 @@ struct wl_list* wofi_read_cache(char* mode) { return cache; } -void wofi_insert_widget(char* mode, char** text, char* search_text, char** actions, size_t action_count) { - struct node* widget = malloc(sizeof(struct node)); +struct widget* wofi_create_widget(char* mode, char** text, char* search_text, char** actions, size_t action_count) { + struct widget* widget = malloc(sizeof(struct widget)); widget->mode = strdup(mode); widget->text = malloc(action_count * sizeof(char*)); for(size_t count = 0; count < action_count; ++count) { @@ -552,8 +562,7 @@ void wofi_insert_widget(char* mode, char** text, char* search_text, char** actio for(size_t count = 0; count < action_count; ++count) { widget->actions[count] = strdup(actions[count]); } - g_idle_add(_insert_widget, widget); - utils_sleep_millis(1); + return widget; } bool wofi_allow_images(void) { @@ -757,6 +766,7 @@ static void add_mode(char* mode) { get_arg_names = get_plugin_proc(mode, "_get_arg_names"); get_arg_count = get_plugin_proc(mode, "_get_arg_count"); mode_ptr->mode_exec = get_plugin_proc(mode, "_exec"); + mode_ptr->mode_get_widget = get_plugin_proc(mode, "_get_widget"); } else { char* plugins_dir = utils_concat(2, config_dir, "/plugins/"); char* full_name = utils_concat(2, plugins_dir, mode); @@ -767,6 +777,7 @@ static void add_mode(char* mode) { get_arg_names = dlsym(plugin, "get_arg_names"); get_arg_count = dlsym(plugin, "get_arg_count"); mode_ptr->mode_exec = dlsym(plugin, "exec"); + mode_ptr->mode_get_widget = dlsym(plugin, "get_widget"); } const char** arg_names = NULL; @@ -786,6 +797,7 @@ static void add_mode(char* mode) { if(init != NULL) { init(props); + gdk_threads_add_idle(_insert_widget, mode_ptr); } else { fprintf(stderr, "I would love to show %s but Idk what it is\n", mode); exit(1);