mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
drun: Implement icon support
Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
This commit is contained in:
parent
fb37aaa70d
commit
03eb4a3abb
6 changed files with 100 additions and 17 deletions
|
@ -58,6 +58,8 @@ Settings config = {
|
|||
.run_shell_command = "{terminal} -e {cmd}",
|
||||
/** Command executed on accep-entry-custom for window modus */
|
||||
.window_command = "xkill -id {window}",
|
||||
/** Sane default for an icon theme */
|
||||
.drun_icon_theme = "gnome",
|
||||
/**
|
||||
* Location of the window.
|
||||
* Enumeration indicating location or gravity of window.
|
||||
|
|
|
@ -116,7 +116,7 @@ PKG_PROG_PKG_CONFIG
|
|||
dnl ---------------------------------------------------------------------
|
||||
dnl PKG_CONFIG based dependencies
|
||||
dnl ---------------------------------------------------------------------
|
||||
NK_INIT([bindings])
|
||||
NK_INIT([bindings xdg-theme])
|
||||
PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.40 gio-unix-2.0 gmodule-2.0])
|
||||
GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-xrm xcb-randr xcb-xinerama])
|
||||
PKG_CHECK_MODULES([pango], [pango pangocairo])
|
||||
|
|
|
@ -111,6 +111,8 @@ typedef struct
|
|||
char * run_list_command;
|
||||
/** Command for window */
|
||||
char * window_command;
|
||||
/** Theme for icons */
|
||||
char * drun_icon_theme;
|
||||
|
||||
/** Windows location/gravity */
|
||||
WindowLocation location;
|
||||
|
|
|
@ -104,6 +104,7 @@ config_h = configure_file(output: 'config.h', configuration: header_conf)
|
|||
|
||||
nk_modules = [
|
||||
'bindings=true',
|
||||
'xdg-theme=true',
|
||||
]
|
||||
nk = subproject('libnkutils', default_options: nk_modules)
|
||||
nk_options = nk.get_variable('nk_options')
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "widgets/textbox.h"
|
||||
#include "history.h"
|
||||
#include "dialogs/drun.h"
|
||||
#include "nkutils-xdg-theme.h"
|
||||
|
||||
#define DRUN_CACHE_FILE "rofi2.druncache"
|
||||
|
||||
|
@ -64,6 +65,9 @@ typedef struct
|
|||
char *root;
|
||||
/* Path to desktop file */
|
||||
char *path;
|
||||
/* Icon stuff */
|
||||
char *icon_name;
|
||||
cairo_surface_t *icon;
|
||||
/* Executable */
|
||||
char *exec;
|
||||
/* Name of the Entry */
|
||||
|
@ -79,6 +83,7 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
NkXdgThemeContext *xdg_context;
|
||||
DRunModeEntry *entry_list;
|
||||
unsigned int cmd_list_length;
|
||||
unsigned int cmd_list_length_actual;
|
||||
|
@ -279,6 +284,9 @@ static gboolean read_desktop_file ( DRunModePrivateData *pd, const char *root, c
|
|||
#endif
|
||||
pd->entry_list[pd->cmd_list_length].exec = g_key_file_get_string ( kf, "Desktop Entry", "Exec", NULL );
|
||||
|
||||
pd->entry_list[pd->cmd_list_length].icon_name = g_key_file_get_locale_string ( kf, "Desktop Entry", "Icon", NULL, NULL );
|
||||
pd->entry_list[pd->cmd_list_length].icon = NULL;
|
||||
|
||||
// Keep keyfile around.
|
||||
pd->entry_list[pd->cmd_list_length].key_file = kf;
|
||||
// We don't want to parse items with this id anymore.
|
||||
|
@ -411,6 +419,7 @@ static int drun_mode_init ( Mode *sw )
|
|||
DRunModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
|
||||
pd->disabled_entries = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL );
|
||||
mode_set_private_data ( sw, (void *) pd );
|
||||
pd->xdg_context = nk_xdg_theme_context_new ();
|
||||
get_apps ( pd );
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -419,6 +428,10 @@ static void drun_entry_clear ( DRunModeEntry *e )
|
|||
{
|
||||
g_free ( e->root );
|
||||
g_free ( e->path );
|
||||
if ( e->icon != NULL ) {
|
||||
cairo_surface_destroy ( e->icon );
|
||||
}
|
||||
g_free ( e->icon_name );
|
||||
g_free ( e->exec );
|
||||
g_free ( e->name );
|
||||
g_free ( e->generic_name );
|
||||
|
@ -471,6 +484,7 @@ static void drun_mode_destroy ( Mode *sw )
|
|||
}
|
||||
g_hash_table_destroy ( rmpd->disabled_entries );
|
||||
g_free ( rmpd->entry_list );
|
||||
nk_xdg_theme_context_free ( rmpd->xdg_context );
|
||||
g_free ( rmpd );
|
||||
mode_set_private_data ( sw, NULL );
|
||||
}
|
||||
|
@ -489,14 +503,75 @@ static char *_get_display_value ( const Mode *sw, unsigned int selected_line, in
|
|||
}
|
||||
/* Free temp storage. */
|
||||
DRunModeEntry *dr = &( pd->entry_list[selected_line] );
|
||||
/* We use '\t' as the icon placeholder for now */
|
||||
if ( dr->generic_name == NULL ) {
|
||||
return g_markup_escape_text ( dr->name, -1 );
|
||||
return g_markup_printf_escaped ( "<span alpha=\"1\">\uFFFC</span>%s", dr->name );
|
||||
}
|
||||
else {
|
||||
return g_markup_printf_escaped ( "%s <span weight='light' size='small'><i>(%s)</i></span>", dr->name,
|
||||
dr->generic_name );
|
||||
return g_markup_printf_escaped ( "<span alpha=\"1\">\uFFFC</span>%s <span weight='light' size='small'><i>(%s)</i></span>",
|
||||
dr->name, dr->generic_name );
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line, int height )
|
||||
{
|
||||
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 ( dr->icon != NULL ) {
|
||||
return dr->icon;
|
||||
}
|
||||
if ( dr->icon_name == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gchar *icon_path;
|
||||
|
||||
if ( g_path_is_absolute ( dr->icon_name ) ) {
|
||||
icon_path = dr->icon_name;
|
||||
}
|
||||
else {
|
||||
const gchar *name = dr->icon_name;
|
||||
if ( g_str_has_suffix ( name, ".png" ) || g_str_has_suffix ( name, ".svg" ) || g_str_has_suffix ( name, ".xpm" ) ) {
|
||||
/* We truncate the extension if the .desktop file is not compliant
|
||||
* We cannot just strip at '.' because D-Bus-styled names are now common.
|
||||
*/
|
||||
gchar *c = g_utf8_strrchr ( name, -1, '.' );
|
||||
g_assert_nonnull ( c );
|
||||
*c = '\0';
|
||||
c = g_utf8_strchr ( name, -1, G_DIR_SEPARATOR );
|
||||
if ( c != NULL ) {
|
||||
/* And just in case, we strip any path component too */
|
||||
*c = '\0';
|
||||
name = ++c;
|
||||
}
|
||||
}
|
||||
icon_path = nk_xdg_theme_get_icon ( pd->xdg_context, config.drun_icon_theme, "Applications", name, height, 1, TRUE );
|
||||
if ( icon_path != NULL ) {
|
||||
g_debug ( "Found Icon %s(%d): %s", name, height, icon_path );
|
||||
}
|
||||
g_free ( dr->icon_name );
|
||||
}
|
||||
dr->icon_name = NULL;
|
||||
|
||||
if ( icon_path == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( g_str_has_suffix ( icon_path, ".png" ) ) {
|
||||
dr->icon = 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, height );
|
||||
}
|
||||
else {
|
||||
g_debug ( "Icon type not yet supported: %s", icon_path );
|
||||
}
|
||||
|
||||
g_free ( icon_path );
|
||||
return dr->icon;
|
||||
}
|
||||
|
||||
static char *drun_get_completion ( const Mode *sw, unsigned int index )
|
||||
{
|
||||
DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw );
|
||||
|
@ -572,6 +647,7 @@ Mode drun_mode =
|
|||
._token_match = drun_token_match,
|
||||
._get_completion = drun_get_completion,
|
||||
._get_display_value = _get_display_value,
|
||||
._get_icon = _get_icon,
|
||||
._preprocess_input = NULL,
|
||||
.private_data = NULL,
|
||||
.free = NULL
|
||||
|
|
|
@ -119,6 +119,8 @@ static XrmOption xrmOptions[] = {
|
|||
"Run command to execute that runs in shell", CONFIG_DEFAULT },
|
||||
{ xrm_String, "window-command", { .str = &config.window_command }, NULL,
|
||||
"Command executed on accep-entry-custom for window modus", CONFIG_DEFAULT },
|
||||
{ xrm_String, "drun-icon-theme", { .str = &config.drun_icon_theme }, NULL,
|
||||
"Theme to use to look for icons", CONFIG_DEFAULT },
|
||||
|
||||
{ xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL,
|
||||
"Disable history in run/ssh", CONFIG_DEFAULT },
|
||||
|
|
Loading…
Reference in a new issue