mirror of
https://github.com/davatorium/rofi.git
synced 2025-02-03 15:34:54 -05:00
Port fixes from icon-cleanup branch.
- Thread for fetching icons for drun. - Fixed placing of icons instead of adding place-holder token that can mis-render. - Give textbox TB_ICON flag.
This commit is contained in:
parent
8a6bdd827d
commit
4d8784cf85
6 changed files with 86 additions and 102 deletions
|
@ -66,6 +66,7 @@ typedef struct
|
|||
guint blink_timeout;
|
||||
|
||||
PangoFontMetrics *metrics;
|
||||
int left_offset;
|
||||
//
|
||||
const char *theme_name;
|
||||
} textbox;
|
||||
|
@ -85,6 +86,7 @@ typedef enum
|
|||
TB_WRAP = 1 << 21,
|
||||
TB_PASSWORD = 1 << 22,
|
||||
TB_INDICATOR = 1 << 23,
|
||||
TB_ICON = 1<<24,
|
||||
} TextboxFlags;
|
||||
/**
|
||||
* Flags indicating current state of the textbox.
|
||||
|
|
|
@ -89,8 +89,9 @@ typedef struct
|
|||
unsigned int cmd_list_length_actual;
|
||||
unsigned int history_length;
|
||||
// List of disabled entries.
|
||||
GHashTable *disabled_entries;
|
||||
unsigned int disabled_entries_length;
|
||||
GHashTable *disabled_entries;
|
||||
unsigned int disabled_entries_length;
|
||||
GThread *thread;
|
||||
} DRunModePrivateData;
|
||||
|
||||
struct RegexEvalArg
|
||||
|
@ -418,6 +419,47 @@ static void get_apps ( DRunModePrivateData *pd )
|
|||
TICK_N ( "Get Desktop apps (system dirs)" );
|
||||
}
|
||||
|
||||
static void drun_icon_fetch ( gpointer data )
|
||||
{
|
||||
// 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] );
|
||||
if ( dr->icon_name == NULL )
|
||||
continue;
|
||||
gchar *icon_path = nk_xdg_theme_get_icon ( pd->xdg_context, NULL, "Applications", dr->icon_name, 32, 1, TRUE );
|
||||
if ( icon_path == NULL ) {
|
||||
g_free(dr->icon_name);
|
||||
dr->icon_name = NULL;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Found Icon %s(%d): %s", dr->icon_name, 32, icon_path );
|
||||
|
||||
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, 32);
|
||||
else {
|
||||
g_log ( G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Icon type not yet supported: %s", icon_path );
|
||||
char *r = dr->icon_name;
|
||||
dr->icon_name = NULL;
|
||||
g_free(r);
|
||||
}
|
||||
g_free(icon_path);
|
||||
// if ( (i%100) == 99 )
|
||||
{
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
static int drun_mode_init ( Mode *sw )
|
||||
{
|
||||
if ( mode_get_private_data ( sw ) == NULL ) {
|
||||
|
@ -426,6 +468,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 );
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -470,6 +513,10 @@ 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;
|
||||
}
|
||||
delete_entry_history ( &( rmpd->entry_list[selected_line] ) );
|
||||
drun_entry_clear ( &( rmpd->entry_list[selected_line] ) );
|
||||
memmove ( &( rmpd->entry_list[selected_line] ), &rmpd->entry_list[selected_line + 1],
|
||||
|
@ -484,6 +531,10 @@ static void drun_mode_destroy ( Mode *sw )
|
|||
{
|
||||
DRunModePrivateData *rmpd = (DRunModePrivateData *) mode_get_private_data ( sw );
|
||||
if ( rmpd != NULL ) {
|
||||
if ( rmpd->thread ){
|
||||
g_thread_join ( rmpd->thread );
|
||||
rmpd->thread = NULL;
|
||||
}
|
||||
for ( size_t i = 0; i < rmpd->cmd_list_length; i++ ) {
|
||||
drun_entry_clear ( &( rmpd->entry_list[i] ) );
|
||||
}
|
||||
|
@ -508,13 +559,12 @@ 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_printf_escaped ( "<span alpha=\"1\">\uFFFC</span>%s", dr->name );
|
||||
return g_markup_printf_escaped ( "%s", dr->name );
|
||||
}
|
||||
else {
|
||||
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 );
|
||||
return g_markup_printf_escaped ( "%s <span weight='light' size='small'><i>(%s)</i></span>", dr->name,
|
||||
dr->generic_name );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,58 +572,7 @@ 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 ( 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 );
|
||||
DRunModeEntry *dr = &( pd->entry_list[selected_line] );
|
||||
return dr->icon;
|
||||
}
|
||||
|
||||
|
|
|
@ -301,18 +301,18 @@ static client* window_client ( ModeModePrivateData *pd, xcb_window_t win )
|
|||
|
||||
c->title = window_get_text_prop ( c->window, xcb->ewmh._NET_WM_NAME );
|
||||
if ( c->title == NULL ) {
|
||||
c->title = rofi_escape_markup ( window_get_text_prop ( c->window, XCB_ATOM_WM_NAME ) );
|
||||
c->title = window_get_text_prop ( c->window, XCB_ATOM_WM_NAME );
|
||||
}
|
||||
pd->title_len = MAX ( c->title ? g_utf8_strlen ( c->title, -1 ) : 0, pd->title_len );
|
||||
|
||||
c->role = rofi_escape_markup ( window_get_text_prop ( c->window, netatoms[WM_WINDOW_ROLE] ) );
|
||||
c->role = window_get_text_prop ( c->window, netatoms[WM_WINDOW_ROLE] );
|
||||
pd->role_len = MAX ( c->role ? g_utf8_strlen ( c->role, -1 ) : 0, pd->role_len );
|
||||
|
||||
cky = xcb_icccm_get_wm_class ( xcb->connection, c->window );
|
||||
xcb_icccm_get_wm_class_reply_t wcr;
|
||||
if ( xcb_icccm_get_wm_class_reply ( xcb->connection, cky, &wcr, NULL ) ) {
|
||||
c->class = rofi_escape_markup ( rofi_latin_to_utf8_strdup ( wcr.class_name, -1 ) );
|
||||
c->name = rofi_escape_markup ( rofi_latin_to_utf8_strdup ( wcr.instance_name, -1 ) );
|
||||
c->class = rofi_latin_to_utf8_strdup ( wcr.class_name, -1 );
|
||||
c->name = rofi_latin_to_utf8_strdup ( wcr.instance_name, -1 );
|
||||
pd->name_len = MAX ( c->name ? g_utf8_strlen ( c->name, -1 ) : 0, pd->name_len );
|
||||
xcb_icccm_get_wm_class_reply_wipe ( &wcr );
|
||||
}
|
||||
|
@ -692,11 +692,6 @@ static gboolean helper_eval_cb ( const GMatchInfo *info, GString *str, gpointer
|
|||
if ( match[1] == 'w' ) {
|
||||
helper_eval_add_str ( str, d->c->wmdesktopstr, l, d->pd->wmdn_len );
|
||||
}
|
||||
else if ( match[1] == 'i' ) {
|
||||
if ( config.show_icons ) {
|
||||
g_string_append ( str, "<span alpha=\"1\">\uFFFC</span>" );
|
||||
}
|
||||
}
|
||||
else if ( match[1] == 'c' ) {
|
||||
helper_eval_add_str ( str, d->c->class, l, d->pd->clf_len );
|
||||
}
|
||||
|
@ -728,7 +723,6 @@ static char *_get_display_value ( const Mode *sw, unsigned int selected_line, in
|
|||
if ( c == NULL ) {
|
||||
return get_entry ? g_strdup ( "Window has fanished" ) : NULL;
|
||||
}
|
||||
*state |= MARKUP;
|
||||
if ( c->demands ) {
|
||||
*state |= URGENT;
|
||||
}
|
||||
|
|
|
@ -906,19 +906,11 @@ static void update_callback ( textbox *t, unsigned int index, void *udata, TextB
|
|||
else{
|
||||
list = pango_attr_list_new ();
|
||||
}
|
||||
int icon_height = textbox_get_font_height ( t );
|
||||
int icon_height = textbox_get_font_height ( t );
|
||||
|
||||
const gchar *visible_text = textbox_get_visible_text ( t );
|
||||
const gchar *icon_placeholder = g_utf8_strchr ( visible_text, -1, 0xFFFC );
|
||||
if ( icon_placeholder != NULL ) {
|
||||
cairo_surface_t *icon = mode_get_icon ( state->sw, state->line_map[index], icon_height );
|
||||
textbox_icon ( t, icon );
|
||||
cairo_surface_t *icon = mode_get_icon ( state->sw, state->line_map[index], icon_height );
|
||||
textbox_icon ( t, icon );
|
||||
|
||||
textbox_set_icon_index ( t, g_utf8_pointer_to_offset ( visible_text, icon_placeholder ) );
|
||||
}
|
||||
else {
|
||||
textbox_set_icon_index ( t, -1 );
|
||||
}
|
||||
if ( state->tokens && config.show_match ) {
|
||||
ThemeHighlight th = { HL_BOLD | HL_UNDERLINE, { 0.0, 0.0, 0.0, 0.0 } };
|
||||
th = rofi_theme_get_highlight ( WIDGET ( t ), "highlight", th );
|
||||
|
|
|
@ -243,6 +243,7 @@ static void listview_recompute_elements ( listview *lv )
|
|||
char *name = g_strjoin ( ".", lv->listview_name, "element", NULL );
|
||||
for ( unsigned int i = lv->cur_elements; i < newne; i++ ) {
|
||||
TextboxFlags flags = ( lv->multi_select ) ? TB_INDICATOR : 0;
|
||||
flags |= (config.show_icons)? TB_ICON:0;
|
||||
lv->boxes[i] = textbox_create_full ( WIDGET_TYPE_LISTVIEW_ELEMENT, name, flags, NORMAL, "" );
|
||||
widget_set_trigger_action_handler ( WIDGET ( lv->boxes[i] ), listview_element_trigger_action, lv );
|
||||
}
|
||||
|
|
|
@ -143,6 +143,9 @@ textbox* textbox_create_full ( WidgetType type, const char *name, TextboxFlags f
|
|||
tb->changed = FALSE;
|
||||
|
||||
tb->layout = pango_layout_new ( p_context );
|
||||
if ( (tb->flags&TB_ICON) == TB_ICON) {
|
||||
tb->left_offset = 1.2*textbox_get_estimated_char_height();
|
||||
}
|
||||
textbox_font ( tb, tbft );
|
||||
|
||||
tb->metrics = p_metrics;
|
||||
|
@ -186,7 +189,6 @@ textbox* textbox_create_full ( WidgetType type, const char *name, TextboxFlags f
|
|||
tb->widget.trigger_action = textbox_editable_trigger_action;
|
||||
}
|
||||
|
||||
tb->icon_index = -1; //Don't draw the icon by default
|
||||
|
||||
// Enabled by default
|
||||
tb->widget.enabled = rofi_theme_get_boolean ( WIDGET ( tb ), "enabled", TRUE );
|
||||
|
@ -269,12 +271,6 @@ void textbox_set_pango_attributes ( textbox *tb, PangoAttrList *list )
|
|||
pango_layout_set_attributes ( tb->layout, list );
|
||||
}
|
||||
|
||||
void textbox_set_icon_index ( textbox *tb, int index )
|
||||
{
|
||||
tb->icon_index = index;
|
||||
widget_queue_redraw ( WIDGET ( tb ) );
|
||||
}
|
||||
|
||||
// set the default text to display
|
||||
void textbox_text ( textbox *tb, const char *text )
|
||||
{
|
||||
|
@ -315,10 +311,9 @@ void textbox_icon ( textbox *tb, cairo_surface_t *icon )
|
|||
// within the parent handled auto width/height modes
|
||||
void textbox_moveresize ( textbox *tb, int x, int y, int w, int h )
|
||||
{
|
||||
unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
||||
unsigned int offset = tb->left_offset + ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
||||
if ( tb->flags & TB_AUTOWIDTH ) {
|
||||
pango_layout_set_width ( tb->layout, -1 );
|
||||
unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
||||
w = textbox_get_font_width ( tb ) + widget_padding_get_padding_width ( WIDGET ( tb ) ) + offset;
|
||||
}
|
||||
else {
|
||||
|
@ -371,7 +366,7 @@ static void textbox_free ( widget *wid )
|
|||
static void textbox_draw ( widget *wid, cairo_t *draw )
|
||||
{
|
||||
textbox *tb = (textbox *) wid;
|
||||
unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
||||
unsigned int offset = tb->left_offset + (( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0);
|
||||
|
||||
if ( tb->changed ) {
|
||||
__textbox_update_pango_text ( tb );
|
||||
|
@ -383,21 +378,22 @@ static void textbox_draw ( widget *wid, cairo_t *draw )
|
|||
int y = top + ( pango_font_metrics_get_ascent ( tb->metrics ) - pango_layout_get_baseline ( tb->layout ) ) / PANGO_SCALE;
|
||||
|
||||
// draw Icon
|
||||
int iconheight = textbox_get_font_height ( tb );
|
||||
int translatex = ( textbox_get_estimated_char_height () * tb->icon_index / 2 );
|
||||
if ( tb->icon != NULL && tb->icon_index != -1 ) {
|
||||
cairo_save ( draw );
|
||||
if ( (tb->flags|TB_ICON) == TB_ICON && tb->icon != NULL ) {
|
||||
int iconheight = textbox_get_font_height ( tb );
|
||||
int translatex = 0;
|
||||
cairo_save(draw);
|
||||
|
||||
/*int iconw = cairo_image_surface_get_width (tb->icon);*/
|
||||
int iconh = cairo_image_surface_get_height ( tb->icon );
|
||||
double scale = (double) iconheight / iconh;
|
||||
int iconh = cairo_image_surface_get_height (tb->icon);
|
||||
double scale = (double)iconheight / iconh;
|
||||
|
||||
cairo_translate ( draw, translatex, 0 );
|
||||
cairo_scale ( draw, scale, scale );
|
||||
cairo_set_source_surface ( draw, tb->icon, x, y );
|
||||
cairo_paint ( draw );
|
||||
cairo_restore ( draw );
|
||||
cairo_translate(draw, translatex, 0);
|
||||
cairo_scale(draw, scale, scale);
|
||||
cairo_set_source_surface(draw, tb->icon, x, y);
|
||||
cairo_paint(draw);
|
||||
cairo_restore(draw);
|
||||
}
|
||||
x+=offset;
|
||||
|
||||
if ( tb->flags & TB_RIGHT ) {
|
||||
int line_width = 0;
|
||||
|
@ -438,7 +434,7 @@ static void textbox_draw ( widget *wid, cairo_t *draw )
|
|||
pango_cairo_show_layout ( draw, tb->layout );
|
||||
|
||||
if ( ( tb->flags & TB_INDICATOR ) == TB_INDICATOR && ( tb->tbft & ( SELECTED ) ) ) {
|
||||
cairo_arc ( draw, DOT_OFFSET / 2.0, tb->widget.h / 2.0, 2.0, 0, 2.0 * G_PI );
|
||||
cairo_arc ( draw, tb->left_offset + DOT_OFFSET / 2.0, tb->widget.h / 2.0, 2.0, 0, 2.0 * M_PI );
|
||||
cairo_fill ( draw );
|
||||
}
|
||||
}
|
||||
|
@ -852,7 +848,7 @@ int textbox_get_estimated_height ( const textbox *tb, int eh )
|
|||
int textbox_get_desired_width ( widget *wid )
|
||||
{
|
||||
textbox *tb = (textbox *) wid;
|
||||
unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
||||
unsigned int offset = tb->left_offset + ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
||||
if ( tb->flags & TB_AUTOWIDTH ) {
|
||||
return textbox_get_font_width ( tb ) + widget_padding_get_padding_width ( wid ) + offset;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue