diff options
Diffstat (limited to 'source/dialogs')
-rw-r--r-- | source/dialogs/drun.c | 112 |
1 files changed, 72 insertions, 40 deletions
diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index e7ec8f9e..77a6dd40 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -54,7 +54,6 @@ #define DRUN_CACHE_FILE "rofi2.druncache" -#define GET_CAT_PARSE_TIME /** * Store extra information about the entry. @@ -70,6 +69,11 @@ typedef struct char *app_id; /* Icon stuff */ char *icon_name; + /* Icon size is used to indicate what size is requested by the gui. + * secondary it indicates if the request for a lookup has been issued (0 not issued ) + */ + int icon_size; + /* Surface holding the icon. */ cairo_surface_t *icon; /* Executable */ char *exec; @@ -77,9 +81,7 @@ typedef struct char *name; /* Generic Name */ char *generic_name; -#ifdef GET_CAT_PARSE_TIME char **categories; -#endif GKeyFile *key_file; } DRunModeEntry; @@ -95,6 +97,12 @@ typedef struct GHashTable *disabled_entries; unsigned int disabled_entries_length; GThread *thread; + GAsyncQueue *icon_fetch_queue; + + unsigned int expected_line_height; + DRunModeEntry quit_entry; + // Theme + const gchar *icon_theme; } DRunModePrivateData; struct RegexEvalArg @@ -289,6 +297,7 @@ static gboolean read_desktop_file ( DRunModePrivateData *pd, const char *root, c pd->cmd_list_length_actual += 256; pd->entry_list = g_realloc ( pd->entry_list, pd->cmd_list_length_actual * sizeof ( *( pd->entry_list ) ) ); } + pd->entry_list[pd->cmd_list_length].icon_size = 0; pd->entry_list[pd->cmd_list_length].root = g_strdup ( root ); pd->entry_list[pd->cmd_list_length].path = g_strdup ( path ); pd->entry_list[pd->cmd_list_length].app_id = g_strndup ( basename, strlen ( basename ) - strlen ( ".desktop" ) ); @@ -296,9 +305,7 @@ static gboolean read_desktop_file ( DRunModePrivateData *pd, const char *root, c pd->entry_list[pd->cmd_list_length].name = n; gchar *gn = g_key_file_get_locale_string ( kf, "Desktop Entry", "GenericName", NULL, NULL ); pd->entry_list[pd->cmd_list_length].generic_name = gn; -#ifdef GET_CAT_PARSE_TIME pd->entry_list[pd->cmd_list_length].categories = g_key_file_get_locale_string_list ( kf, "Desktop Entry", "Categories", NULL, NULL, NULL ); -#endif pd->entry_list[pd->cmd_list_length].exec = g_key_file_get_string ( kf, "Desktop Entry", "Exec", NULL ); if ( config.show_icons ) { @@ -324,7 +331,7 @@ static void walk_dir ( DRunModePrivateData *pd, const char *root, const char *di { DIR *dir; - g_debug ( "Checking directory %s for desktop files.", root ); + g_debug ( "Checking directory %s for desktop files.", dirname ); dir = opendir ( dirname ); if ( dir == NULL ) { return; @@ -428,53 +435,67 @@ static void get_apps ( DRunModePrivateData *pd ) TICK_N ( "Get Desktop apps (user dir)" ); // Then read thee system data dirs. const gchar * const * sys = g_get_system_data_dirs (); - for (; *sys != NULL; ++sys ) { - dir = g_build_filename ( *sys, "applications", NULL ); - walk_dir ( pd, dir, dir ); - g_free ( dir ); + for (const gchar * const *iter = sys ; *iter != NULL; ++iter ) { + gboolean unique = TRUE; + // Stupid duplicate detection, better then walking dir. + for ( const gchar *const *iterd = sys ; iterd != iter; ++iterd ){ + if ( g_strcmp0 ( *iter, *iterd ) == 0 ) { + unique = FALSE; + } + } + // Check, we seem to be getting empty string... + if ( unique && (**iter) != '\0') { + dir = g_build_filename ( *iter, "applications", NULL ); + walk_dir ( pd, dir, dir ); + g_free ( dir ); + } } TICK_N ( "Get Desktop apps (system dirs)" ); } static gpointer drun_icon_fetch ( gpointer data ) { + g_debug ( "Starting up icon fetching thread." ); // as long as dr->icon is updated atomicly.. (is a pointer write atomic?) // this should be fine running in another thread. - GTimer *t = g_timer_new (); DRunModePrivateData *pd = (DRunModePrivateData *) data; - for ( size_t i = 0; i < pd->cmd_list_length; i++ ) { - DRunModeEntry *dr = &( pd->entry_list[i] ); + DRunModeEntry *dr; + while ( ( dr = g_async_queue_pop ( pd->icon_fetch_queue )) != &(pd->quit_entry) ) + { if ( dr->icon_name == NULL ) { continue; } gchar *icon_path = nk_xdg_theme_get_icon ( pd->xdg_context, config.drun_icon_theme, "Applications", dr->icon_name, 32, 1, TRUE ); if ( icon_path == NULL ) { - g_free ( dr->icon_name ); - dr->icon_name = NULL; + g_debug ( "Failed to get Icon %s(%d): n/a", dr->icon_name, dr->icon_size ); continue; } else{ - g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Found Icon %s(%d): %s", dr->icon_name, 32, icon_path ); + g_debug ( "Found Icon %s(%d): %s", dr->icon_name, dr->icon_size, icon_path ); } - + cairo_surface_t *icon_surf = NULL; if ( g_str_has_suffix ( icon_path, ".png" ) ) { - dr->icon = cairo_image_surface_create_from_png ( icon_path ); + icon_surf = cairo_image_surface_create_from_png ( icon_path ); } else if ( g_str_has_suffix ( icon_path, ".svg" ) ) { - dr->icon = cairo_image_surface_create_from_svg ( icon_path, 32 ); + icon_surf = cairo_image_surface_create_from_svg ( icon_path, dr->icon_size); } else { - g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Icon type not yet supported: %s", icon_path ); + g_debug ( "Icon type not yet supported: %s", icon_path ); } - g_free ( icon_path ); - // if ( (i%100) == 99 ) - { - rofi_view_reload (); + if ( icon_surf ) { + // Check if surface is valid. + if ( cairo_surface_status ( icon_surf ) != CAIRO_STATUS_SUCCESS ) { + g_debug ( "Icon failed to open: %s(%d): %s", dr->icon_name, dr->icon_size, icon_path ); + cairo_surface_destroy ( icon_surf ); + icon_surf = NULL; + } + dr->icon = icon_surf; } + g_free ( icon_path ); + rofi_view_reload (); } - rofi_view_reload (); - g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "elapsed: %f\n", g_timer_elapsed ( t, NULL ) ); - g_timer_destroy ( t ); + g_debug ( "Shutting down icon fetching thread." ); return NULL; } @@ -486,7 +507,7 @@ static int drun_mode_init ( Mode *sw ) mode_set_private_data ( sw, (void *) pd ); pd->xdg_context = nk_xdg_theme_context_new (); get_apps ( pd ); - pd->thread = g_thread_new ( "icon-fetch-drun", drun_icon_fetch, pd ); + pd->icon_fetch_queue = g_async_queue_new ( ); } return TRUE; } @@ -502,9 +523,7 @@ static void drun_entry_clear ( DRunModeEntry *e ) g_free ( e->exec ); g_free ( e->name ); g_free ( e->generic_name ); -#ifdef GET_CAT_PARSE_TIME g_strfreev ( e->categories ); -#endif g_key_file_free ( e->key_file ); } @@ -535,8 +554,13 @@ static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned i else if ( ( mretv & MENU_ENTRY_DELETE ) && selected_line < rmpd->cmd_list_length ) { if ( selected_line < rmpd->history_length ) { if ( rmpd->thread ) { - g_thread_join ( rmpd->thread ); - rmpd->thread = NULL; + g_async_queue_lock ( rmpd->icon_fetch_queue ); + DRunModeEntry *dr; + while ( (dr = g_async_queue_try_pop_unlocked ( rmpd->icon_fetch_queue )) != NULL ){ + // Reset for possible re-fetch. + dr->icon_size = 0; + } + g_async_queue_unlock ( rmpd->icon_fetch_queue ); } delete_entry_history ( &( rmpd->entry_list[selected_line] ) ); drun_entry_clear ( &( rmpd->entry_list[selected_line] ) ); @@ -553,9 +577,18 @@ static void drun_mode_destroy ( Mode *sw ) DRunModePrivateData *rmpd = (DRunModePrivateData *) mode_get_private_data ( sw ); if ( rmpd != NULL ) { if ( rmpd->thread ) { + g_async_queue_lock ( rmpd->icon_fetch_queue ); + while ( g_async_queue_try_pop_unlocked ( rmpd->icon_fetch_queue ) ); + // Make the thread quit. + g_async_queue_push_front_unlocked ( rmpd->icon_fetch_queue, (gpointer) &(rmpd->quit_entry)); + g_async_queue_unlock ( rmpd->icon_fetch_queue ); g_thread_join ( rmpd->thread ); rmpd->thread = NULL; } + if ( rmpd->icon_fetch_queue ) { + g_async_queue_unref ( rmpd->icon_fetch_queue ); + rmpd->icon_fetch_queue = NULL; + } for ( size_t i = 0; i < rmpd->cmd_list_length; i++ ) { drun_entry_clear ( &( rmpd->entry_list[i] ) ); } @@ -594,6 +627,13 @@ static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line, DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw ); g_return_val_if_fail ( pd->entry_list != NULL, NULL ); DRunModeEntry *dr = &( pd->entry_list[selected_line] ); + if ( pd->thread == NULL ) { + pd->thread = g_thread_new ( "icon-fetch-drun", drun_icon_fetch, pd ); + } + if ( dr->icon_size == 0 ) { + dr->icon_size = height; + g_async_queue_push ( pd->icon_fetch_queue, dr ); + } return dr->icon; } @@ -634,18 +674,10 @@ static int drun_token_match ( const Mode *data, GRegex **tokens, unsigned int in } // Match against category. if ( !test ) { -#ifdef GET_CAT_PARSE_TIME gchar **list = rmpd->entry_list[index].categories; for ( int iter = 0; !test && list && list[iter]; iter++ ) { test = helper_token_match ( ftokens, list[iter] ); } -#else - gchar **list = g_key_file_get_locale_string_list ( rmpd->entry_list[index].key_file, "Desktop Entry", "Categories", NULL, NULL, NULL ); - for ( int iter = 0; !test && list && list[iter]; iter++ ) { - test = helper_token_match ( ftokens, list[iter] ); - } - g_strfreev ( list ); -#endif } if ( test == 0 ) { match = 0; |