From 407992b5b545745d42e36bced4e38104cd104725 Mon Sep 17 00:00:00 2001 From: geommer Date: Tue, 12 Apr 2016 16:23:12 +0200 Subject: [PATCH] Add initial icon support --- Makefile | 6 ++-- include/yabar.h | 15 ++++++++- src/ya_draw.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ya_parse.c | 26 ++++++++++++++++ 4 files changed, 125 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 7338197..8a8915b 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = $(shell git describe) CPPFLAGS += -DVERSION=\"$(VERSION)\" -D_POSIX_C_SOURCE=199309L -DYA_INTERNAL -DYA_DYN_COL \ - -DYA_ENV_VARS -DYA_INTERNAL_EWMH -CFLAGS += -std=c99 -Iinclude -pedantic -Wall -Os `pkg-config --cflags pango pangocairo libconfig` -LDLIBS := -lxcb -lpthread -lxcb-randr -lxcb-ewmh `pkg-config --libs pango pangocairo libconfig` + -DYA_ENV_VARS -DYA_INTERNAL_EWMH -DYA_ICON +CFLAGS += -std=c99 -Iinclude -pedantic -Wall -Os `pkg-config --cflags pango pangocairo libconfig gdk-pixbuf-2.0` +LDLIBS := -lxcb -lpthread -lxcb-randr -lxcb-ewmh `pkg-config --libs pango pangocairo libconfig gdk-pixbuf-2.0` PROGRAM := yabar PREFIX ?= /usr BINPREFIX ?= $(PREFIX)/bin diff --git a/include/yabar.h b/include/yabar.h index 91e24f3..16143ad 100644 --- a/include/yabar.h +++ b/include/yabar.h @@ -32,6 +32,8 @@ #include #include +#include + //just to suppress gcc syntastic warnings in vim //VERSION is obtained from Makefile #ifndef VERSION @@ -86,7 +88,8 @@ enum { BLKA_UNDERLINE = 1<<12, BLKA_OVERLINE = 1<<13, BLKA_INHERIT = 1<<14, - BLKA_INTERN_X_EV = 1<<15 + BLKA_INTERN_X_EV = 1<<15, + BLKA_ICON = 1<<16 }; @@ -182,6 +185,14 @@ struct ya_block { uint32_t ulcolor_old; //initial underline color uint32_t olcolor_old; //initial overline color #endif + +#ifdef YA_ICON + char *icon_path; + uint16_t ic_x; + uint16_t ic_y; + double ic_scale_w; + double ic_scale_h; +#endif //YA_ICON }; @@ -278,4 +289,6 @@ ya_block_t * ya_get_blk_from_event( xcb_button_press_event_t *eb); void ya_get_cur_window_title(ya_block_t * blk); void ya_handle_button( xcb_button_press_event_t *eb); void ya_handle_prop_notify(xcb_property_notify_event_t *ep); + +cairo_surface_t * ya_draw_graphics(ya_block_t *blk); #endif /*YABAR_H*/ diff --git a/src/ya_draw.c b/src/ya_draw.c index 69b123d..ae78415 100644 --- a/src/ya_draw.c +++ b/src/ya_draw.c @@ -179,6 +179,20 @@ void ya_draw_pango_text(struct ya_block *blk) { xcb_poly_fill_rectangle(ya.c, blk->pixmap, blk->gc, 1, (const xcb_rectangle_t[]) { {0,0,blk->width, blk->bar->height} }); cairo_surface_t *surface = cairo_xcb_surface_create(ya.c, blk->pixmap, ya.visualtype, blk->width, blk->bar->height); cairo_t *cr = cairo_create(surface); +#ifdef YA_ICON + if((blk->attr & BLKA_ICON)) { + cairo_surface_t *iconsrf = ya_draw_graphics(blk); + if (iconsrf) { + cairo_scale(cr, blk->ic_scale_w, blk->ic_scale_h); + cairo_set_source_surface(cr, iconsrf, + (double)(blk->ic_x)/(blk->ic_scale_w), + (double)(blk->ic_y)/(blk->ic_scale_h)); + cairo_paint(cr); + cairo_surface_destroy(iconsrf); + cairo_scale(cr, 1.0/(blk->ic_scale_w), 1.0/(blk->ic_scale_h)); + } + } +#endif //YA_ICON PangoContext *context = pango_cairo_create_context(cr); PangoLayout *layout = pango_layout_new(context); pango_layout_set_font_description(layout, blk->bar->desc); @@ -347,3 +361,71 @@ inline void ya_get_cur_window_title(ya_block_t * blk) { } #endif //YA_INTERNAL_EWMH + +#ifdef YA_ICON +//This function is obtained from Awesome WM code. +//I actually did not know how to copy pixbuf to surface. +static cairo_surface_t * ya_draw_surface_from_pixbuf(GdkPixbuf *buf) { + int width = gdk_pixbuf_get_width(buf); + int height = gdk_pixbuf_get_height(buf); + int pix_stride = gdk_pixbuf_get_rowstride(buf); + guchar *pixels = gdk_pixbuf_get_pixels(buf); + int channels = gdk_pixbuf_get_n_channels(buf); + cairo_surface_t *surface; + int cairo_stride; + unsigned char *cairo_pixels; + + + cairo_format_t format = CAIRO_FORMAT_ARGB32; + if (channels == 3) + format = CAIRO_FORMAT_RGB24; + + surface = cairo_image_surface_create(format, width, height); + cairo_surface_flush(surface); + cairo_stride = cairo_image_surface_get_stride(surface); + cairo_pixels = cairo_image_surface_get_data(surface); + + for (int y = 0; y < height; y++) { + guchar *row = pixels; + uint32_t *cairo = (uint32_t *) cairo_pixels; + for (int x = 0; x < width; x++) { + if (channels == 3) { + uint8_t r = *row++; + uint8_t g = *row++; + uint8_t b = *row++; + *cairo++ = (r << 16) | (g << 8) | b; + } + else { + uint8_t r = *row++; + uint8_t g = *row++; + uint8_t b = *row++; + uint8_t a = *row++; + double alpha = a / 255.0; + r = r * alpha; + g = g * alpha; + b = b * alpha; + *cairo++ = (a << 24) | (r << 16) | (g << 8) | b; + } + } + pixels += pix_stride; + cairo_pixels += cairo_stride; + } + + cairo_surface_mark_dirty(surface); + return surface; +} + + +cairo_surface_t * ya_draw_graphics(ya_block_t *blk) { + GError *gerr =NULL; + cairo_surface_t *ret = NULL; + GdkPixbuf *gbuf = gdk_pixbuf_new_from_file(blk->icon_path, &gerr); + if(gbuf == NULL) { + fprintf(stderr, "Cannot allocate pixbuf for block (%s.%s)\n. %s\n", blk->bar->name, blk->name, gerr->message); + return NULL; + } + ret = ya_draw_surface_from_pixbuf(gbuf); + g_object_unref(gbuf); + return ret; +} +#endif //YA_ICON diff --git a/src/ya_parse.c b/src/ya_parse.c index e3f05f8..9c9ab2e 100644 --- a/src/ya_parse.c +++ b/src/ya_parse.c @@ -498,6 +498,32 @@ skip_type: if(retcnf == CONFIG_TRUE) { blk->button_cmd[4] = strdup(retstr); } +#ifdef YA_ICON + retcnf = config_setting_lookup_string(set, "image", &retstr); + if(retcnf == CONFIG_TRUE) { + blk->icon_path = strdup(retstr); + blk->attr |= BLKA_ICON; + double retflt; + if(config_setting_lookup_float(set, "image-scale-width", &retflt)==CONFIG_TRUE) { + blk->ic_scale_w = retflt; + } + else { + blk->ic_scale_w = 1.0; + } + if(config_setting_lookup_float(set, "image-scale-height", &retflt)==CONFIG_TRUE) { + blk->ic_scale_h = retflt; + } + else { + blk->ic_scale_h = 1.0; + } + if(config_setting_lookup_int(set, "image-shift-x", &retint)==CONFIG_TRUE) { + blk->ic_x = retint; + } + if(config_setting_lookup_int(set, "image-shift-y", &retint)==CONFIG_TRUE) { + blk->ic_y = retint; + } + } +#endif //YA_ICON retcnf = config_setting_lookup_string(set, "align", &retstr); if(retcnf == CONFIG_FALSE) { if(NOT_INHERIT_BLK(blk))