Wofi now loads modes multi-threaded, this should decrease startup times
This commit is contained in:
parent
5c59d8317c
commit
1393306c26
@ -6,6 +6,7 @@ pkgcfg = import('pkgconfig')
|
|||||||
inc = include_directories('inc')
|
inc = include_directories('inc')
|
||||||
gtk = dependency('gtk+-3.0')
|
gtk = dependency('gtk+-3.0')
|
||||||
wayland = dependency('wayland-client')
|
wayland = dependency('wayland-client')
|
||||||
|
threads = dependency('threads')
|
||||||
dl = cc.find_library('dl')
|
dl = cc.find_library('dl')
|
||||||
|
|
||||||
hg = find_program('hg', native : true, required : false)
|
hg = find_program('hg', native : true, required : false)
|
||||||
@ -30,7 +31,7 @@ sources = ['src/config.c',
|
|||||||
'proto/xdg-output-unstable-v1-protocol.c',
|
'proto/xdg-output-unstable-v1-protocol.c',
|
||||||
'proto/xdg-shell-protocol.c']
|
'proto/xdg-shell-protocol.c']
|
||||||
|
|
||||||
deps = [gtk, wayland, dl]
|
deps = [gtk, wayland, dl, threads]
|
||||||
|
|
||||||
if get_option('enable_run')
|
if get_option('enable_run')
|
||||||
sources += 'modes/run.c'
|
sources += 'modes/run.c'
|
||||||
|
126
modes/drun.c
126
modes/drun.c
@ -32,12 +32,13 @@ static const char* arg_names[] = {"print_command", "display_generic"};
|
|||||||
|
|
||||||
static struct mode* mode;
|
static struct mode* mode;
|
||||||
|
|
||||||
struct node {
|
struct desktop_entry {
|
||||||
struct widget* widget;
|
char* full_path;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct wl_list widgets;
|
static struct map* entries;
|
||||||
|
static struct wl_list desktop_entries;
|
||||||
|
|
||||||
static bool print_command;
|
static bool print_command;
|
||||||
static bool display_generic;
|
static bool display_generic;
|
||||||
@ -191,7 +192,46 @@ static char* get_id(char* path) {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void insert_dir(char* app_dir, struct map* entries) {
|
static struct widget* create_widget(char* full_path) {
|
||||||
|
char* id = get_id(full_path);
|
||||||
|
|
||||||
|
if(map_contains(entries, id)) {
|
||||||
|
free(id);
|
||||||
|
free(full_path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t action_count;
|
||||||
|
char** text = get_action_text(full_path, &action_count);
|
||||||
|
map_put(entries, id, "true");
|
||||||
|
if(text == NULL) {
|
||||||
|
wofi_remove_cache(mode, full_path);
|
||||||
|
free(id);
|
||||||
|
free(full_path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char** actions = get_action_actions(full_path, &action_count);
|
||||||
|
|
||||||
|
char* search_text = get_search_text(full_path);
|
||||||
|
|
||||||
|
struct widget* ret = wofi_create_widget(mode, text, search_text, actions, action_count);
|
||||||
|
|
||||||
|
for(size_t count = 0; count < action_count; ++count) {
|
||||||
|
free(actions[count]);
|
||||||
|
free(text[count]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(id);
|
||||||
|
free(text);
|
||||||
|
free(actions);
|
||||||
|
free(full_path);
|
||||||
|
free(search_text);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insert_dir(char* app_dir) {
|
||||||
DIR* dir = opendir(app_dir);
|
DIR* dir = opendir(app_dir);
|
||||||
if(dir == NULL) {
|
if(dir == NULL) {
|
||||||
return;
|
return;
|
||||||
@ -207,7 +247,7 @@ static void insert_dir(char* app_dir, struct map* entries) {
|
|||||||
struct stat info;
|
struct stat info;
|
||||||
stat(full_path, &info);
|
stat(full_path, &info);
|
||||||
if(S_ISDIR(info.st_mode)) {
|
if(S_ISDIR(info.st_mode)) {
|
||||||
insert_dir(full_path, entries);
|
insert_dir(full_path);
|
||||||
free(id);
|
free(id);
|
||||||
free(full_path);
|
free(full_path);
|
||||||
continue;
|
continue;
|
||||||
@ -217,33 +257,12 @@ static void insert_dir(char* app_dir, struct map* entries) {
|
|||||||
free(full_path);
|
free(full_path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
size_t action_count;
|
|
||||||
char** text = get_action_text(full_path, &action_count);
|
|
||||||
map_put(entries, id, "true");
|
|
||||||
if(text == NULL) {
|
|
||||||
free(id);
|
|
||||||
free(full_path);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char** actions = get_action_actions(full_path, &action_count);
|
struct desktop_entry* entry = malloc(sizeof(struct desktop_entry));
|
||||||
|
entry->full_path = full_path;
|
||||||
char* search_text = get_search_text(full_path);
|
wl_list_insert(&desktop_entries, &entry->link);
|
||||||
|
|
||||||
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]);
|
|
||||||
free(text[count]);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(id);
|
free(id);
|
||||||
free(text);
|
|
||||||
free(actions);
|
|
||||||
free(search_text);
|
|
||||||
free(full_path);
|
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
@ -312,49 +331,24 @@ void wofi_drun_init(struct mode* this, struct map* config) {
|
|||||||
print_command = strcmp(config_get(config, "print_command", "false"), "true") == 0;
|
print_command = strcmp(config_get(config, "print_command", "false"), "true") == 0;
|
||||||
display_generic = strcmp(config_get(config, "display_generic", "false"), "true") == 0;
|
display_generic = strcmp(config_get(config, "display_generic", "false"), "true") == 0;
|
||||||
|
|
||||||
struct map* entries = map_init();
|
entries = map_init();
|
||||||
struct wl_list* cache = wofi_read_cache(mode);
|
struct wl_list* cache = wofi_read_cache(mode);
|
||||||
|
|
||||||
wl_list_init(&widgets);
|
wl_list_init(&desktop_entries);
|
||||||
|
|
||||||
struct cache_line* node, *tmp;
|
struct cache_line* node, *tmp;
|
||||||
wl_list_for_each_safe(node, tmp, cache, link) {
|
wl_list_for_each_safe(node, tmp, cache, link) {
|
||||||
if(should_invalidate_cache(node->line)) {
|
if(should_invalidate_cache(node->line)) {
|
||||||
wofi_remove_cache(mode, node->line);
|
wofi_remove_cache(mode, node->line);
|
||||||
|
free(node->line);
|
||||||
goto cache_cont;
|
goto cache_cont;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t action_count;
|
struct desktop_entry* entry = malloc(sizeof(struct desktop_entry));
|
||||||
char** text = get_action_text(node->line, &action_count);
|
entry->full_path = node->line;
|
||||||
if(text == NULL) {
|
wl_list_insert(&desktop_entries, &entry->link);
|
||||||
wofi_remove_cache(mode, node->line);
|
|
||||||
goto cache_cont;
|
|
||||||
}
|
|
||||||
|
|
||||||
char** actions = get_action_actions(node->line, &action_count);
|
|
||||||
|
|
||||||
char* search_text = get_search_text(node->line);
|
|
||||||
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);
|
|
||||||
|
|
||||||
map_put(entries, id, "true");
|
|
||||||
|
|
||||||
free(id);
|
|
||||||
|
|
||||||
free(search_text);
|
|
||||||
|
|
||||||
for(size_t count = 0; count < action_count; ++count) {
|
|
||||||
free(text[count]);
|
|
||||||
free(actions[count]);
|
|
||||||
}
|
|
||||||
free(text);
|
|
||||||
free(actions);
|
|
||||||
|
|
||||||
cache_cont:
|
cache_cont:
|
||||||
free(node->line);
|
|
||||||
wl_list_remove(&node->link);
|
wl_list_remove(&node->link);
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
@ -371,19 +365,21 @@ void wofi_drun_init(struct mode* this, struct map* config) {
|
|||||||
char* str = strtok_r(dirs, ":", &save_ptr);
|
char* str = strtok_r(dirs, ":", &save_ptr);
|
||||||
do {
|
do {
|
||||||
char* app_dir = utils_concat(2, str, "/applications");
|
char* app_dir = utils_concat(2, str, "/applications");
|
||||||
insert_dir(app_dir, entries);
|
insert_dir(app_dir);
|
||||||
free(app_dir);
|
free(app_dir);
|
||||||
} while((str = strtok_r(NULL, ":", &save_ptr)) != NULL);
|
} while((str = strtok_r(NULL, ":", &save_ptr)) != NULL);
|
||||||
free(dirs);
|
free(dirs);
|
||||||
map_free(entries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct widget* wofi_drun_get_widget(void) {
|
struct widget* wofi_drun_get_widget(void) {
|
||||||
struct node* node, *tmp;
|
struct desktop_entry* node, *tmp;
|
||||||
wl_list_for_each_reverse_safe(node, tmp, &widgets, link) {
|
wl_list_for_each_reverse_safe(node, tmp, &desktop_entries, link) {
|
||||||
struct widget* widget = node->widget;
|
struct widget* widget = create_widget(node->full_path);
|
||||||
wl_list_remove(&node->link);
|
wl_list_remove(&node->link);
|
||||||
free(node);
|
free(node);
|
||||||
|
if(widget == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
38
src/wofi.c
38
src/wofi.c
@ -100,6 +100,8 @@ static GdkRectangle resolution = {0};
|
|||||||
static bool resize_expander = false;
|
static bool resize_expander = false;
|
||||||
static uint32_t line_count = 0;
|
static uint32_t line_count = 0;
|
||||||
static bool dynamic_lines;
|
static bool dynamic_lines;
|
||||||
|
static struct wl_list mode_list;
|
||||||
|
static pthread_t mode_thread;
|
||||||
|
|
||||||
static struct map* keys;
|
static struct map* keys;
|
||||||
|
|
||||||
@ -568,9 +570,9 @@ static gboolean _insert_widget(gpointer data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean insert_all_widgets(gpointer data) {
|
static gboolean insert_all_widgets(gpointer data) {
|
||||||
|
pthread_join(mode_thread, NULL);
|
||||||
struct wl_list* modes = data;
|
struct wl_list* modes = data;
|
||||||
if(modes->prev == modes) {
|
if(modes->prev == modes) {
|
||||||
free(modes);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
} else {
|
} else {
|
||||||
struct mode* mode = wl_container_of(modes->prev, mode, link);
|
struct mode* mode = wl_container_of(modes->prev, mode, link);
|
||||||
@ -1420,6 +1422,22 @@ static struct mode* add_mode(char* _mode) {
|
|||||||
return mode_ptr;
|
return mode_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* start_mode_thread(void* data) {
|
||||||
|
char* mode = data;
|
||||||
|
if(strchr(mode, ',') != NULL) {
|
||||||
|
char* save_ptr;
|
||||||
|
char* str = strtok_r(mode, ",", &save_ptr);
|
||||||
|
do {
|
||||||
|
struct mode* mode_ptr = add_mode(str);
|
||||||
|
wl_list_insert(&mode_list, &mode_ptr->link);
|
||||||
|
} while((str = strtok_r(NULL, ",", &save_ptr)) != NULL);
|
||||||
|
} else {
|
||||||
|
struct mode* mode_ptr = add_mode(mode);
|
||||||
|
wl_list_insert(&mode_list, &mode_ptr->link);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_mods(char* key, void (*action)(void)) {
|
static void parse_mods(char* key, void (*action)(void)) {
|
||||||
char* tmp = strdup(key);
|
char* tmp = strdup(key);
|
||||||
char* save_ptr;
|
char* save_ptr;
|
||||||
@ -1743,21 +1761,11 @@ void wofi_init(struct map* _config) {
|
|||||||
do_percent_size(geo_str);
|
do_percent_size(geo_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_list* modes = malloc(sizeof(struct wl_list));
|
wl_list_init(&mode_list);
|
||||||
wl_list_init(modes);
|
|
||||||
|
|
||||||
if(strchr(mode, ',') != NULL) {
|
pthread_create(&mode_thread, NULL, start_mode_thread, mode);
|
||||||
char* save_ptr;
|
|
||||||
char* str = strtok_r(mode, ",", &save_ptr);
|
gdk_threads_add_idle(insert_all_widgets, &mode_list);
|
||||||
do {
|
|
||||||
struct mode* mode_ptr = add_mode(str);
|
|
||||||
wl_list_insert(modes, &mode_ptr->link);
|
|
||||||
} while((str = strtok_r(NULL, ",", &save_ptr)) != NULL);
|
|
||||||
} else {
|
|
||||||
struct mode* mode_ptr = add_mode(mode);
|
|
||||||
wl_list_insert(modes, &mode_ptr->link);
|
|
||||||
}
|
|
||||||
gdk_threads_add_idle(insert_all_widgets, modes);
|
|
||||||
|
|
||||||
gtk_window_set_title(GTK_WINDOW(window), prompt);
|
gtk_window_set_title(GTK_WINDOW(window), prompt);
|
||||||
gtk_widget_show_all(window);
|
gtk_widget_show_all(window);
|
||||||
|
Loading…
Reference in New Issue
Block a user