diff options
author | Dave Davenport <qball@gmpclient.org> | 2017-05-31 11:18:30 +0200 |
---|---|---|
committer | Dave Davenport <qball@gmpclient.org> | 2017-05-31 11:18:30 +0200 |
commit | d8b0e24b09e6e0aa9aaaf17e6ee9c92e0ebdc05e (patch) | |
tree | ed961b08bed65b4adc4ff14978282c2ad506d641 /source | |
parent | 9a6fd1c6c3d54c4a6db6ba7d15f317927f4036ec (diff) | |
parent | 4d8784cf85a5108340a2b2a684e2bd1d9f77269d (diff) |
Merge remote-tracking branch 'origin/master' into barview
Diffstat (limited to 'source')
-rw-r--r-- | source/dialogs/combi.c | 13 | ||||
-rw-r--r-- | source/dialogs/drun.c | 104 | ||||
-rw-r--r-- | source/dialogs/window.c | 118 | ||||
-rw-r--r-- | source/helper.c | 10 | ||||
-rw-r--r-- | source/mode.c | 12 | ||||
-rw-r--r-- | source/view.c | 4 | ||||
-rw-r--r-- | source/widgets/listview.c | 1 | ||||
-rw-r--r-- | source/widgets/textbox.c | 43 | ||||
-rw-r--r-- | source/x11-helper.c | 24 | ||||
-rw-r--r-- | source/xrmoptions.c | 5 |
10 files changed, 314 insertions, 20 deletions
diff --git a/source/dialogs/combi.c b/source/dialogs/combi.c index 8fa4a438..5631c519 100644 --- a/source/dialogs/combi.c +++ b/source/dialogs/combi.c @@ -247,6 +247,18 @@ static char * combi_get_completion ( const Mode *sw, unsigned int index ) return NULL; } +static cairo_surface_t * combi_get_icon ( const Mode *sw, unsigned int index, int height ) +{ + CombiModePrivateData *pd = mode_get_private_data ( sw ); + for ( unsigned i = 0; i < pd->num_switchers; i++ ) { + if ( index >= pd->starts[i] && index < ( pd->starts[i] + pd->lengths[i] ) ) { + cairo_surface_t *icon = mode_get_icon ( pd->switchers[i].mode, index - pd->starts[i], height ); + return icon; + } + } + return NULL; +} + static char * combi_preprocess_input ( Mode *sw, const char *input ) { CombiModePrivateData *pd = mode_get_private_data ( sw ); @@ -285,6 +297,7 @@ Mode combi_mode = ._token_match = combi_mode_match, ._get_completion = combi_get_completion, ._get_display_value = combi_mgrv, + ._get_icon = combi_get_icon, ._preprocess_input = combi_preprocess_input, .private_data = NULL, .free = NULL diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index f17fa1ae..a10057e6 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -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" @@ -61,31 +62,36 @@ typedef struct { /* Root */ - char *root; + char *root; /* Path to desktop file */ - char *path; + char *path; + /* Icon stuff */ + char *icon_name; + cairo_surface_t *icon; /* Executable */ - char *exec; + char *exec; /* Name of the Entry */ - char *name; + char *name; /* Generic Name */ - char *generic_name; + char *generic_name; #ifdef GET_CAT_PARSE_TIME - char **categories; + char **categories; #endif - GKeyFile *key_file; + GKeyFile *key_file; } DRunModeEntry; typedef struct { - DRunModeEntry *entry_list; - unsigned int cmd_list_length; - unsigned int cmd_list_length_actual; - unsigned int history_length; + NkXdgThemeContext *xdg_context; + DRunModeEntry *entry_list; + unsigned int cmd_list_length; + unsigned int cmd_list_length_actual; + unsigned int history_length; // List of disabled entries. GHashTable *disabled_entries; unsigned int disabled_entries_length; + GThread *thread; } DRunModePrivateData; struct RegexEvalArg @@ -279,6 +285,14 @@ 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 ); + if ( config.show_icons ) { + pd->entry_list[pd->cmd_list_length].icon_name = g_key_file_get_locale_string ( kf, "Desktop Entry", "Icon", NULL, NULL ); + } + else{ + pd->entry_list[pd->cmd_list_length].icon_name = 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. @@ -405,13 +419,56 @@ 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 ) { 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 ); + pd->thread = g_thread_new ( "icon-fetch-drun", drun_icon_fetch, pd ); } return TRUE; } @@ -419,6 +476,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 ); @@ -452,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], @@ -466,11 +531,16 @@ 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] ) ); } 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 ); } @@ -490,13 +560,22 @@ static char *_get_display_value ( const Mode *sw, unsigned int selected_line, in /* Free temp storage. */ DRunModeEntry *dr = &( pd->entry_list[selected_line] ); if ( dr->generic_name == NULL ) { - return g_markup_escape_text ( dr->name, -1 ); + return g_markup_printf_escaped ( "%s", dr->name ); } else { return g_markup_printf_escaped ( "%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] ); + return dr->icon; +} + static char *drun_get_completion ( const Mode *sw, unsigned int index ) { DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw ); @@ -572,6 +651,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 diff --git a/source/dialogs/window.c b/source/dialogs/window.c index 535c2e72..d19e1c61 100644 --- a/source/dialogs/window.c +++ b/source/dialogs/window.c @@ -33,6 +33,7 @@ #include <stdlib.h> #include <stdio.h> +#include <stdint.h> #include <unistd.h> #include <strings.h> #include <string.h> @@ -77,6 +78,8 @@ typedef struct long hint_flags; uint32_t wmdesktop; char *wmdesktopstr; + cairo_surface_t *icon; + gboolean icon_checked; } client; // window lists @@ -149,6 +152,9 @@ static void winlist_empty ( winlist *l ) while ( l->len > 0 ) { client *c = l->data[--l->len]; if ( c != NULL ) { + if ( c->icon ) { + cairo_surface_destroy ( c->icon ); + } g_free ( c->title ); g_free ( c->class ); g_free ( c->name ); @@ -726,6 +732,116 @@ static char *_get_display_value ( const Mode *sw, unsigned int selected_line, in return get_entry ? _generate_display_string ( rmpd, c ) : NULL; } +/** + * Icon code borrowed from https://github.com/olejorgenb/extract-window-icon + */ +static cairo_user_data_key_t data_key; + +/** Create a surface object from this image data. + * \param width The width of the image. + * \param height The height of the image + * \param data The image's data in ARGB format, will be copied by this function. + */ +static cairo_surface_t * draw_surface_from_data ( int width, int height, uint32_t *data ) +{ + unsigned long int len = width * height; + unsigned long int i; + uint32_t *buffer = g_new0 ( uint32_t, len ); + cairo_surface_t *surface; + + /* Cairo wants premultiplied alpha, meh :( */ + for ( i = 0; i < len; i++ ) { + uint8_t a = ( data[i] >> 24 ) & 0xff; + double alpha = a / 255.0; + uint8_t r = ( ( data[i] >> 16 ) & 0xff ) * alpha; + uint8_t g = ( ( data[i] >> 8 ) & 0xff ) * alpha; + uint8_t b = ( ( data[i] >> 0 ) & 0xff ) * alpha; + buffer[i] = ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b; + } + + surface = cairo_image_surface_create_for_data ( (unsigned char *) buffer, + CAIRO_FORMAT_ARGB32, + width, + height, + width * 4 ); + /* This makes sure that buffer will be freed */ + cairo_surface_set_user_data ( surface, &data_key, buffer, g_free ); + + return surface; +} +static cairo_surface_t * ewmh_window_icon_from_reply ( xcb_get_property_reply_t *r, uint32_t preferred_size ) +{ + uint32_t *data, *end, *found_data = 0; + uint32_t found_size = 0; + + if ( !r || r->type != XCB_ATOM_CARDINAL || r->format != 32 || r->length < 2 ) { + return 0; + } + + data = (uint32_t *) xcb_get_property_value ( r ); + if ( !data ) { + return 0; + } + + end = data + r->length; + + /* Goes over the icon data and picks the icon that best matches the size preference. + * In case the size match is not exact, picks the closest bigger size if present, + * closest smaller size otherwise. + */ + while ( data + 1 < end ) { + /* check whether the data size specified by width and height fits into the array we got */ + uint64_t data_size = (uint64_t) data[0] * data[1]; + if ( data_size > (uint64_t) ( end - data - 2 ) ) { + break; + } + + /* use the greater of the two dimensions to match against the preferred size */ + uint32_t size = MAX ( data[0], data[1] ); + + /* pick the icon if it's a better match than the one we already have */ + gboolean found_icon_too_small = found_size < preferred_size; + gboolean found_icon_too_large = found_size > preferred_size; + gboolean icon_empty = data[0] == 0 || data[1] == 0; + gboolean better_because_bigger = found_icon_too_small && size > found_size; + gboolean better_because_smaller = found_icon_too_large && + size >= preferred_size && size < found_size; + if ( !icon_empty && ( better_because_bigger || better_because_smaller || found_size == 0 ) ) { + found_data = data; + found_size = size; + } + + data += data_size + 2; + } + + if ( !found_data ) { + return 0; + } + + return draw_surface_from_data ( found_data[0], found_data[1], found_data + 2 ); +} +/** Get NET_WM_ICON. */ +static cairo_surface_t * get_net_wm_icon ( xcb_window_t xid, uint32_t preferred_size ) +{ + xcb_get_property_cookie_t cookie = xcb_get_property_unchecked ( + xcb->connection, FALSE, xid, + xcb->ewmh._NET_WM_ICON, XCB_ATOM_CARDINAL, 0, UINT32_MAX ); + xcb_get_property_reply_t *r = xcb_get_property_reply ( xcb->connection, cookie, NULL ); + cairo_surface_t *surface = ewmh_window_icon_from_reply ( r, preferred_size ); + free ( r ); + return surface; +} +static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line, int size ) +{ + ModeModePrivateData *rmpd = mode_get_private_data ( sw ); + client *c = window_client ( rmpd, rmpd->ids->array[selected_line] ); + if ( c->icon_checked == FALSE ) { + c->icon = get_net_wm_icon ( rmpd->ids->array[selected_line], size ); + c->icon_checked = TRUE; + } + return c->icon; +} + #include "mode-private.h" Mode window_mode = { @@ -737,6 +853,7 @@ Mode window_mode = ._destroy = window_mode_destroy, ._token_match = window_match, ._get_display_value = _get_display_value, + ._get_icon = _get_icon, ._get_completion = NULL, ._preprocess_input = NULL, .private_data = NULL, @@ -752,6 +869,7 @@ Mode window_mode_cd = ._destroy = window_mode_destroy, ._token_match = window_match, ._get_display_value = _get_display_value, + ._get_icon = _get_icon, ._get_completion = NULL, ._preprocess_input = NULL, .private_data = NULL, diff --git a/source/helper.c b/source/helper.c index f6b3b74d..5299ced3 100644 --- a/source/helper.c +++ b/source/helper.c @@ -730,6 +730,16 @@ char * rofi_latin_to_utf8_strdup ( const char *input, gssize length ) return g_convert_with_fallback ( input, length, "UTF-8", "latin1", "\uFFFD", NULL, &slength, NULL ); } +gchar *rofi_escape_markup ( gchar *text ) +{ + if ( text == NULL ) { + return NULL; + } + gchar *ret = g_markup_escape_text ( text, -1 ); + g_free ( text ); + return ret; +} + char * rofi_force_utf8 ( const gchar *data, ssize_t length ) { if ( data == NULL ) { diff --git a/source/mode.c b/source/mode.c index a7e552d3..5e070e3c 100644 --- a/source/mode.c +++ b/source/mode.c @@ -70,6 +70,18 @@ char * mode_get_display_value ( const Mode *mode, unsigned int selected_line, in return mode->_get_display_value ( mode, selected_line, state, attribute_list, get_entry ); } +cairo_surface_t * mode_get_icon ( const Mode *mode, unsigned int selected_line, int height ) +{ + g_assert ( mode != NULL ); + + if ( mode->_get_icon != NULL ) { + return mode->_get_icon ( mode, selected_line, height ); + } + else { + return NULL; + } +} + char * mode_get_completion ( const Mode *mode, unsigned int selected_line ) { g_assert ( mode != NULL ); diff --git a/source/view.c b/source/view.c index 7250b2b9..5020eb00 100644 --- a/source/view.c +++ b/source/view.c @@ -906,6 +906,10 @@ 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 ); + + cairo_surface_t *icon = mode_get_icon ( state->sw, state->line_map[index], icon_height ); + textbox_icon ( t, icon ); if ( state->tokens && config.show_match ) { ThemeHighlight th = { HL_BOLD | HL_UNDERLINE, { 0.0, 0.0, 0.0, 0.0 } }; diff --git a/source/widgets/listview.c b/source/widgets/listview.c index af06001f..547df049 100644 --- a/source/widgets/listview.c +++ b/source/widgets/listview.c @@ -367,6 +367,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 ); } diff --git a/source/widgets/textbox.c b/source/widgets/textbox.c index c17ca575..8b9b0c47 100644 --- a/source/widgets/textbox.c +++ b/source/widgets/textbox.c @@ -144,6 +144,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; @@ -315,13 +318,19 @@ void textbox_text ( textbox *tb, const char *text ) widget_queue_redraw ( WIDGET ( tb ) ); } +void textbox_icon ( textbox *tb, cairo_surface_t *icon ) +{ + tb->icon = icon; + + widget_queue_redraw ( WIDGET ( tb ) ); +} + // 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 { @@ -380,14 +389,34 @@ static void textbox_draw ( widget *wid, cairo_t *draw ) return; } 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 ); } // Skip the side MARGIN on the X axis. - int x = widget_padding_get_left ( WIDGET ( tb ) ) + offset; + int x = widget_padding_get_left ( WIDGET ( tb ) ) + offset; + int top = widget_padding_get_top ( WIDGET ( tb ) ); + int y = top + ( pango_font_metrics_get_ascent ( tb->metrics ) - pango_layout_get_baseline ( tb->layout ) ) / PANGO_SCALE; + + // draw Icon + 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; + + 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; @@ -400,7 +429,6 @@ static void textbox_draw ( widget *wid, cairo_t *draw ) x = ( ( tb->widget.w - tw - widget_padding_get_padding_width ( WIDGET ( tb ) ) - offset ) ) / 2; } - int top = widget_padding_get_top ( WIDGET ( tb ) ); if ( tb->yalign > 0.001 ) { int height = (pango_font_metrics_get_ascent ( tb->metrics ) + pango_font_metrics_get_descent ( tb->metrics ))/PANGO_SCALE; int bottom = widget_padding_get_bottom ( WIDGET ( tb ) ); @@ -412,7 +440,6 @@ static void textbox_draw ( widget *wid, cairo_t *draw ) rofi_theme_get_color ( WIDGET ( tb ), "text", draw ); // draw the cursor if ( tb->flags & TB_EDITABLE && tb->blink ) { - int y = top + ( pango_font_metrics_get_ascent ( tb->metrics ) - pango_layout_get_baseline ( tb->layout ) ) / PANGO_SCALE; // We want to place the cursor based on the text shown. const char *text = pango_layout_get_text ( tb->layout ); // Clamp the position, should not be needed, but we are paranoid. @@ -437,7 +464,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 ); } } @@ -866,7 +893,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 ( wid->expand && tb->flags & TB_AUTOWIDTH ) { return textbox_get_font_width ( tb ) + widget_padding_get_padding_width ( wid ) + offset; } diff --git a/source/x11-helper.c b/source/x11-helper.c index 689d0519..94b5b53d 100644 --- a/source/x11-helper.c +++ b/source/x11-helper.c @@ -133,6 +133,30 @@ cairo_surface_t * x11_helper_get_bg_surface ( void ) xcb->screen->width_in_pixels, xcb->screen->height_in_pixels ); } +cairo_surface_t* cairo_image_surface_create_from_svg ( const gchar* file, int height ) +{ + cairo_surface_t *surface; + cairo_t *cr; + RsvgHandle * handle; + RsvgDimensionData dimensions; + + handle = rsvg_handle_new_from_file ( file, NULL ); + rsvg_handle_get_dimensions ( handle, &dimensions ); + double scale = (double) height / dimensions.height; + surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, + (double) dimensions.width * scale, + (double) dimensions.height * scale ); + cr = cairo_create ( surface ); + cairo_scale ( cr, scale, scale ); + rsvg_handle_render_cairo ( handle, cr ); + cairo_destroy ( cr ); + + rsvg_handle_close ( handle, NULL ); + g_object_unref ( handle ); + + return surface; +} + // retrieve a text property from a window // technically we could use window_get_prop(), but this is better for character set support char* window_get_text_prop ( xcb_window_t w, xcb_atom_t atom ) diff --git a/source/xrmoptions.c b/source/xrmoptions.c index ef0c7dfe..7fd87e56 100644 --- a/source/xrmoptions.c +++ b/source/xrmoptions.c @@ -105,6 +105,9 @@ static XrmOption xrmOptions[] = { { xrm_Boolean, "fixed-num-lines", { .num = &config.fixed_num_lines }, NULL, "Always show number of lines", CONFIG_DEFAULT }, + { xrm_Boolean, "show-icons", { .snum = &config.show_icons }, NULL, + "Whether to load and show icons", CONFIG_DEFAULT }, + { xrm_String, "terminal", { .str = &config.terminal_emulator }, NULL, "Terminal to use", CONFIG_DEFAULT }, { xrm_String, "ssh-client", { .str = &config.ssh_client }, NULL, @@ -119,6 +122,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 }, |