summaryrefslogtreecommitdiffstats
path: root/source/dialogs
diff options
context:
space:
mode:
Diffstat (limited to 'source/dialogs')
-rw-r--r--source/dialogs/drun.c112
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;