Add initial icon support

This commit is contained in:
geommer 2016-04-12 16:23:12 +02:00
parent 5019670ea5
commit 407992b5b5
4 changed files with 125 additions and 4 deletions

View file

@ -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

View file

@ -32,6 +32,8 @@
#include <xcb/randr.h>
#include <xcb/xcb_ewmh.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
//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*/

View file

@ -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

View file

@ -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))