mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
[DRun] Add desktop cache
Add a desktop cache file. Usable for system with slow filesystems. * -drun-use-desktop-cache * -drun-reload-desktop-cache Fixes: #1040
This commit is contained in:
parent
f8be880b45
commit
a35a898816
5 changed files with 244 additions and 30 deletions
|
@ -160,4 +160,6 @@ Settings config = {
|
|||
|
||||
.cache_dir = NULL,
|
||||
.window_thumbnail = FALSE,
|
||||
.drun_use_desktop_cache = FALSE,
|
||||
.drun_reload_desktop_cache = FALSE
|
||||
};
|
||||
|
|
|
@ -676,6 +676,14 @@ Message can be multi-line.
|
|||
|
||||
### Other
|
||||
|
||||
`-drun-use-desktop-cache`
|
||||
|
||||
Build and use a cache with the content of desktop files. Usable for systems with slow harddrives.
|
||||
|
||||
`-drun-reload-desktop-cache`
|
||||
|
||||
If `drun-use-desktop-cache` is enbled, rebuild a cache with the content of desktop files.
|
||||
|
||||
`-pid` *path*
|
||||
|
||||
Make **rofi** create a pid file and check this on startup. The pid file prevents multiple **rofi** instances from running simultaneously. This is useful when running **rofi** from a key-binding daemon.
|
||||
|
|
|
@ -192,6 +192,10 @@ typedef struct
|
|||
|
||||
/** Window Thumbnails */
|
||||
gboolean window_thumbnail;
|
||||
|
||||
/** drun cache */
|
||||
gboolean drun_use_desktop_cache;
|
||||
gboolean drun_reload_desktop_cache;
|
||||
} Settings;
|
||||
/** Global Settings structure. */
|
||||
extern Settings config;
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "rofi-icon-fetcher.h"
|
||||
|
||||
#define DRUN_CACHE_FILE "rofi3.druncache"
|
||||
#define DRUN_DESKTOP_CACHE_FILE "rofi-drun-desktop.cache"
|
||||
|
||||
char *DRUN_GROUP_NAME = "Desktop Entry";
|
||||
|
||||
|
@ -66,7 +67,6 @@ typedef struct _DRunModePrivateData DRunModePrivateData;
|
|||
*/
|
||||
typedef struct
|
||||
{
|
||||
thread_state st;
|
||||
DRunModePrivateData *pd;
|
||||
/* category */
|
||||
char *action;
|
||||
|
@ -233,6 +233,23 @@ static void exec_cmd_entry ( DRunModeEntry *e )
|
|||
return;
|
||||
}
|
||||
|
||||
if ( e->key_file == NULL ) {
|
||||
GKeyFile *kf = g_key_file_new ();
|
||||
GError *error = NULL;
|
||||
gboolean res = g_key_file_load_from_file ( kf, e->path, 0, &error );
|
||||
if ( res )
|
||||
{
|
||||
e->key_file = kf;
|
||||
}
|
||||
else {
|
||||
g_warning ( "[%s] [%s] Failed to parse desktop file because: %s.", e->app_id, e->path, error->message );
|
||||
g_error_free ( error );
|
||||
g_key_file_free ( kf );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const gchar *fp = g_strstrip ( str );
|
||||
gchar *exec_path = g_key_file_get_string ( e->key_file, e->action, "Path", NULL );
|
||||
if ( exec_path != NULL && strlen ( exec_path ) == 0 ) {
|
||||
|
@ -629,9 +646,182 @@ static gint drun_int_sort_list ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Cache voodoo *
|
||||
*******************************************/
|
||||
|
||||
#define CACHE_VERSION 1
|
||||
static void drun_write_str ( FILE *fd, const char *str )
|
||||
{
|
||||
size_t l = (str == NULL? 0 : strlen(str));
|
||||
fwrite ( &l, sizeof(l),1, fd );
|
||||
// Only write string if it is not NULL or empty.
|
||||
if ( l > 0 ) {
|
||||
// Also writeout terminating '\0'
|
||||
fwrite ( str, 1, l+1, fd );
|
||||
}
|
||||
}
|
||||
static void drun_read_string ( FILE *fd, char **str )
|
||||
{
|
||||
size_t l = 0;
|
||||
|
||||
if ( fread ( &l, sizeof(l), 1, fd ) != 1 ){
|
||||
g_warning( "Failed to read entry, cache corrupt?" );
|
||||
return;
|
||||
}
|
||||
(*str) = NULL;
|
||||
if ( l > 0 ) {
|
||||
// Include \0
|
||||
l++;
|
||||
(*str) = g_malloc(l);
|
||||
if ( fread ( (*str), 1, l, fd ) != l ){
|
||||
g_warning( "Failed to read entry, cache corrupt?" );
|
||||
}
|
||||
}
|
||||
}
|
||||
static void drun_write_strv ( FILE *fd, char **str )
|
||||
{
|
||||
guint vl = (str == NULL? 0 : g_strv_length ( str ));
|
||||
fwrite ( &vl, sizeof(vl),1, fd );
|
||||
for ( guint index = 0; index < vl ; index++ ) {
|
||||
drun_write_str ( fd, str[index] );
|
||||
}
|
||||
}
|
||||
static void drun_read_stringv ( FILE *fd, char ***str )
|
||||
{
|
||||
guint vl = 0;
|
||||
(*str) = NULL;
|
||||
if ( fread ( &vl, sizeof(vl), 1, fd ) != 1 ){
|
||||
g_warning( "Failed to read entry, cache corrupt?" );
|
||||
return;
|
||||
}
|
||||
if ( vl > 0 ){
|
||||
// Include terminating NULL entry.
|
||||
(*str) = g_malloc0((vl+1)*sizeof(**str));
|
||||
for ( guint index = 0; index < vl; index++ ) {
|
||||
drun_read_string ( fd, &((*str)[index]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write_cache ( DRunModePrivateData *pd, const char *cache_file )
|
||||
{
|
||||
if ( cache_file == NULL || config.drun_use_desktop_cache == FALSE ) return;
|
||||
TICK_N ( "DRUN Write CACHE: start" );
|
||||
|
||||
FILE *fd = fopen ( cache_file, "w" );
|
||||
if ( fd == NULL ){
|
||||
g_warning ( "Failed to write to cache file" );
|
||||
return;
|
||||
}
|
||||
uint8_t version = CACHE_VERSION;
|
||||
fwrite ( &version, sizeof(version),1, fd );
|
||||
|
||||
fwrite ( &(pd->cmd_list_length), sizeof(pd->cmd_list_length),1,fd );
|
||||
for ( unsigned int index = 0; index < pd->cmd_list_length; index ++ )
|
||||
{
|
||||
DRunModeEntry *entry = & ( pd->entry_list[index] );
|
||||
|
||||
drun_write_str ( fd, entry->action );
|
||||
drun_write_str ( fd, entry->root );
|
||||
drun_write_str ( fd, entry->path );
|
||||
drun_write_str ( fd, entry->app_id );
|
||||
drun_write_str ( fd, entry->desktop_id );
|
||||
drun_write_str ( fd, entry->icon_name );
|
||||
drun_write_str ( fd, entry->exec );
|
||||
drun_write_str ( fd, entry->name );
|
||||
drun_write_str ( fd, entry->generic_name );
|
||||
|
||||
drun_write_strv ( fd, entry->categories );
|
||||
drun_write_strv ( fd, entry->keywords );
|
||||
|
||||
drun_write_str ( fd, entry->comment );
|
||||
|
||||
}
|
||||
|
||||
fclose ( fd) ;
|
||||
TICK_N ( "DRUN Write CACHE: end" );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read cache file. returns FALSE when success.
|
||||
*/
|
||||
static gboolean drun_read_cache ( DRunModePrivateData *pd, const char *cache_file )
|
||||
{
|
||||
if ( cache_file == NULL || config.drun_use_desktop_cache == FALSE ) return TRUE;
|
||||
|
||||
if ( config.drun_reload_desktop_cache ) {
|
||||
return TRUE;
|
||||
}
|
||||
TICK_N ( "DRUN Read CACHE: start" );
|
||||
FILE *fd = fopen ( cache_file, "r" );
|
||||
if ( fd == NULL ) {
|
||||
TICK_N ( "DRUN Read CACHE: stop" );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Read version.
|
||||
uint8_t version = 0;
|
||||
|
||||
if ( fread ( &version, sizeof(version),1, fd ) != 1 )
|
||||
{
|
||||
fclose ( fd );
|
||||
g_warning ( "Cache corrupt, ignoring." );
|
||||
TICK_N ( "DRUN Read CACHE: stop" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( version != CACHE_VERSION ) {
|
||||
fclose ( fd );
|
||||
g_warning ( "Cache file wrong version, ignoring." );
|
||||
TICK_N ( "DRUN Read CACHE: stop" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( fread ( &(pd->cmd_list_length), sizeof(pd->cmd_list_length),1,fd ) != 1 ){
|
||||
fclose ( fd );
|
||||
g_warning ( "Cache corrupt, ignoring." );
|
||||
TICK_N ( "DRUN Read CACHE: stop" );
|
||||
return FALSE;
|
||||
}
|
||||
// set actual length to length;
|
||||
pd->cmd_list_length_actual = pd->cmd_list_length;
|
||||
|
||||
pd->entry_list = g_malloc0 ( pd->cmd_list_length_actual * sizeof ( *( pd->entry_list ) ));
|
||||
|
||||
for ( unsigned int index = 0; index < pd->cmd_list_length; index++ )
|
||||
{
|
||||
DRunModeEntry *entry = & ( pd->entry_list[index] );
|
||||
|
||||
drun_read_string ( fd, &(entry->action) );
|
||||
drun_read_string ( fd, &(entry->root) );
|
||||
drun_read_string ( fd, &(entry->path) );
|
||||
drun_read_string ( fd, &(entry->app_id) );
|
||||
drun_read_string ( fd, &(entry->desktop_id) );
|
||||
drun_read_string ( fd, &(entry->icon_name) );
|
||||
drun_read_string ( fd, &(entry->exec) );
|
||||
drun_read_string ( fd, &(entry->name) );
|
||||
drun_read_string ( fd, &(entry->generic_name) );
|
||||
|
||||
drun_read_stringv ( fd, &(entry->categories) );
|
||||
drun_read_stringv ( fd, &(entry->keywords) );
|
||||
|
||||
drun_read_string ( fd, &(entry->comment) );
|
||||
}
|
||||
|
||||
|
||||
fclose ( fd );
|
||||
TICK_N ( "DRUN Read CACHE: stop" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void get_apps ( DRunModePrivateData *pd )
|
||||
{
|
||||
char *cache_file = g_build_filename ( cache_dir, DRUN_DESKTOP_CACHE_FILE, NULL );
|
||||
TICK_N ( "Get Desktop apps (start)" );
|
||||
if ( drun_read_cache ( pd, cache_file ) )
|
||||
{
|
||||
|
||||
gchar *dir;
|
||||
// First read the user directory.
|
||||
|
@ -662,6 +852,10 @@ static void get_apps ( DRunModePrivateData *pd )
|
|||
g_qsort_with_data ( pd->entry_list, pd->cmd_list_length, sizeof ( DRunModeEntry ), drun_int_sort_list, NULL );
|
||||
|
||||
TICK_N ( "Sorting done." );
|
||||
|
||||
write_cache ( pd, cache_file );
|
||||
}
|
||||
g_free ( cache_file );
|
||||
}
|
||||
|
||||
static void drun_mode_parse_entry_fields ()
|
||||
|
@ -739,7 +933,9 @@ static void drun_entry_clear ( DRunModeEntry *e )
|
|||
}
|
||||
g_strfreev ( e->categories );
|
||||
g_strfreev ( e->keywords );
|
||||
if ( e->key_file ) {
|
||||
g_key_file_free ( e->key_file );
|
||||
}
|
||||
}
|
||||
|
||||
static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned int selected_line )
|
||||
|
|
|
@ -225,6 +225,10 @@ static XrmOption xrmOptions[] = {
|
|||
"Directory where history and temporary files are stored.", CONFIG_DEFAULT },
|
||||
{ xrm_Boolean, "window-thumbnail", { .snum = &config.window_thumbnail }, NULL,
|
||||
"Show window thumbnail in window switcher if availalbe.", CONFIG_DEFAULT },
|
||||
{ xrm_Boolean, "drun-use-desktop-cache", { .snum = &config.drun_use_desktop_cache }, NULL,
|
||||
"DRUN: build and use a cache with desktop file content.", CONFIG_DEFAULT },
|
||||
{ xrm_Boolean, "drun-reload-desktop-cache", { .snum = &config.drun_reload_desktop_cache}, NULL,
|
||||
"DRUN: If enabled, reload the cache with desktop file content.", CONFIG_DEFAULT },
|
||||
};
|
||||
|
||||
/** Dynamic array of extra options */
|
||||
|
|
Loading…
Reference in a new issue