Merge icon handling from buglloc/master

This commit is contained in:
Johannes M. Griebler 2016-10-13 19:18:00 +02:00
commit 33ab80f1a9
5 changed files with 166 additions and 18 deletions

View File

@ -27,7 +27,7 @@ CFLAGS += -g --std=gnu99 -pedantic -Wall -Wno-overlength-strings -Os ${STATIC}
pkg_config_packs := dbus-1 x11 freetype2 xext xft xscrnsaver \ pkg_config_packs := dbus-1 x11 freetype2 xext xft xscrnsaver \
"glib-2.0 >= 2.36" gio-2.0 \ "glib-2.0 >= 2.36" gio-2.0 \
pango cairo pangocairo pango cairo pangocairo gdk-2.0
# check if we need libxdg-basedir # check if we need libxdg-basedir
ifeq (,$(findstring STATIC_CONFIG,$(CFLAGS))) ifeq (,$(findstring STATIC_CONFIG,$(CFLAGS)))

54
dbus.c
View File

@ -74,6 +74,7 @@ static void onGetServerInformation(GDBusConnection * connection,
const gchar * sender, const gchar * sender,
const GVariant * parameters, const GVariant * parameters,
GDBusMethodInvocation * invocation); GDBusMethodInvocation * invocation);
static RawImage * get_raw_image_from_data_hint(GVariant *icon_data);
void handle_method_call(GDBusConnection * connection, void handle_method_call(GDBusConnection * connection,
const gchar * sender, const gchar * sender,
@ -140,6 +141,7 @@ static void onNotify(GDBusConnection * connection,
gchar *fgcolor = NULL; gchar *fgcolor = NULL;
gchar *bgcolor = NULL; gchar *bgcolor = NULL;
gchar *category = NULL; gchar *category = NULL;
RawImage *raw_icon = NULL;
actions->actions = NULL; actions->actions = NULL;
actions->count = 0; actions->count = 0;
@ -232,6 +234,23 @@ static void onNotify(GDBusConnection * connection,
dict_value, NULL); dict_value, NULL);
} }
dict_value =
g_variant_lookup_value(content,
"image-data",
G_VARIANT_TYPE("(iiibiiay)"));
if (!dict_value) {
dict_value =
g_variant_lookup_value(content,
"icon_data",
G_VARIANT_TYPE("(iiibiiay)"));
}
if (dict_value) {
raw_icon =
get_raw_image_from_data_hint(
dict_value);
}
dict_value = dict_value =
g_variant_lookup_value(content, g_variant_lookup_value(content,
"value", "value",
@ -283,6 +302,7 @@ static void onNotify(GDBusConnection * connection,
n->summary = summary; n->summary = summary;
n->body = body; n->body = body;
n->icon = icon; n->icon = icon;
n->raw_icon = raw_icon;
n->timeout = timeout; n->timeout = timeout;
n->allow_markup = settings.allow_markup; n->allow_markup = settings.allow_markup;
n->plain_text = settings.plain_text; n->plain_text = settings.plain_text;
@ -412,6 +432,40 @@ static void on_name_lost(GDBusConnection * connection,
exit(1); exit(1);
} }
static RawImage * get_raw_image_from_data_hint(GVariant *icon_data)
{
RawImage *image = malloc(sizeof(RawImage));
GVariant *data_variant;
gsize expected_len;
g_variant_get (icon_data,
"(iiibii@ay)",
&image->width,
&image->height,
&image->rowstride,
&image->has_alpha,
&image->bits_per_sample,
&image->n_channels,
&data_variant);
expected_len = (image->height - 1) * image->rowstride + image->width
* ((image->n_channels * image->bits_per_sample + 7) / 8);
if (expected_len != g_variant_get_size (data_variant)) {
fprintf(stderr, "Expected image data to be of length %" G_GSIZE_FORMAT
" but got a " "length of %" G_GSIZE_FORMAT,
expected_len,
g_variant_get_size (data_variant));
free(image);
return NULL;
}
image->data = (guchar *) g_memdup (g_variant_get_data (data_variant),
g_variant_get_size (data_variant));
return image;
}
int initdbus(void) int initdbus(void)
{ {
guint owner_id; guint owner_id;

View File

@ -161,6 +161,12 @@ void notification_free(notification * n)
free(n->actions->dmenu_str); free(n->actions->dmenu_str);
} }
if (n->raw_icon) {
if (n->raw_icon->data)
free(n->raw_icon->data);
free(n->raw_icon);
}
free(n); free(n);
} }
@ -442,11 +448,12 @@ int notification_init(notification * n, int id)
n->timeout == -1 ? settings.timeouts[n->urgency] : n->timeout; n->timeout == -1 ? settings.timeouts[n->urgency] : n->timeout;
n->start = 0; n->start = 0;
if (n->icon == NULL) { if (strlen(n->icon) <= 0) {
n->icon = strdup(settings.icons[n->urgency]);
}
else if (strlen(n->icon) <= 0) {
free(n->icon); free(n->icon);
n->icon = NULL;
}
if (n->raw_icon == NULL && n->icon == NULL) {
n->icon = strdup(settings.icons[n->urgency]); n->icon = strdup(settings.icons[n->urgency]);
} }

View File

@ -7,6 +7,16 @@
#define NORM 1 #define NORM 1
#define CRIT 2 #define CRIT 2
typedef struct _raw_image {
int width;
int height;
int rowstride;
int has_alpha;
int bits_per_sample;
int n_channels;
unsigned char *data;
} RawImage;
typedef struct _actions { typedef struct _actions {
char **actions; char **actions;
char *dmenu_str; char *dmenu_str;
@ -18,6 +28,7 @@ typedef struct _notification {
char *summary; char *summary;
char *body; char *body;
char *icon; char *icon;
RawImage *raw_icon;
char *msg; /* formatted message */ char *msg; /* formatted message */
char *category; char *category;
char *text_to_render; char *text_to_render;

100
x.c
View File

@ -14,6 +14,7 @@
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <pango/pangocairo.h> #include <pango/pangocairo.h>
#include <cairo-xlib.h> #include <cairo-xlib.h>
#include <gdk/gdk.h>
#include "x.h" #include "x.h"
#include "utils.h" #include "utils.h"
@ -191,6 +192,17 @@ static bool have_dynamic_width(void)
return (xctx.geometry.mask & WidthValue && xctx.geometry.w == 0); return (xctx.geometry.mask & WidthValue && xctx.geometry.w == 0);
} }
static bool is_readable_file(const char *filename)
{
return (access(filename, R_OK) != -1);
}
const char *get_filename_ext(const char *filename) {
const char *dot = strrchr(filename, '.');
if(!dot || dot == filename) return "";
return dot + 1;
}
static dimension_t calculate_dimensions(GSList *layouts) static dimension_t calculate_dimensions(GSList *layouts)
{ {
dimension_t dim; dimension_t dim;
@ -274,7 +286,52 @@ static dimension_t calculate_dimensions(GSList *layouts)
return dim; return dim;
} }
static cairo_surface_t *get_icon_surface(char *icon_path) static cairo_surface_t *gdk_pixbuf_to_cairo_surface(const GdkPixbuf *pixbuf)
{
cairo_surface_t *icon_surface = NULL;
cairo_t *cr;
cairo_format_t format;
double width, height;
format = gdk_pixbuf_get_has_alpha(pixbuf) ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24;
width = gdk_pixbuf_get_width(pixbuf);
height = gdk_pixbuf_get_height(pixbuf);
icon_surface = cairo_image_surface_create(format, width, height);
cr = cairo_create(icon_surface);
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
cairo_paint(cr);
free(cr);
return icon_surface;
}
static cairo_surface_t *get_icon_surface_from_file(const char *icon_path)
{
cairo_surface_t *icon_surface = NULL;
if (is_readable_file(icon_path)) {
char *img_type;
img_type = get_filename_ext(icon_path);
if (strcmp(img_type, "png") == 0) {
icon_surface = cairo_image_surface_create_from_png(icon_path);
} else {
GdkPixbuf *pixbuf;
GError *error = NULL;
pixbuf = gdk_pixbuf_new_from_file(icon_path, &error);
if (pixbuf != NULL) {
icon_surface = gdk_pixbuf_to_cairo_surface(pixbuf);
g_object_unref(pixbuf);
} else {
g_free(error);
}
}
if (cairo_surface_status(icon_surface) != CAIRO_STATUS_SUCCESS) {
cairo_surface_destroy(icon_surface);
icon_surface = NULL;
}
}
return icon_surface;
}
static cairo_surface_t *get_icon_surface_from_path(char *icon_path)
{ {
cairo_surface_t *icon_surface = NULL; cairo_surface_t *icon_surface = NULL;
gchar *uri_path = NULL; gchar *uri_path = NULL;
@ -287,11 +344,7 @@ static cairo_surface_t *get_icon_surface(char *icon_path)
} }
/* absolute path? */ /* absolute path? */
if (icon_path[0] == '/' || icon_path[0] == '~') { if (icon_path[0] == '/' || icon_path[0] == '~') {
icon_surface = cairo_image_surface_create_from_png(icon_path); icon_surface = get_icon_surface_from_file(icon_path);
if (cairo_surface_status(icon_surface) != CAIRO_STATUS_SUCCESS) {
cairo_surface_destroy(icon_surface);
icon_surface = NULL;
}
} }
/* search in icon_folders */ /* search in icon_folders */
if (icon_surface == NULL) { if (icon_surface == NULL) {
@ -305,13 +358,10 @@ static cairo_surface_t *get_icon_surface(char *icon_path)
maybe_icon_path = g_strconcat(current_folder, "/", icon_path, ".png", NULL); maybe_icon_path = g_strconcat(current_folder, "/", icon_path, ".png", NULL);
free(current_folder); free(current_folder);
icon_surface = cairo_image_surface_create_from_png(maybe_icon_path); icon_surface = get_icon_surface_from_file(maybe_icon_path);
free(maybe_icon_path); free(maybe_icon_path);
if (cairo_surface_status(icon_surface) == CAIRO_STATUS_SUCCESS) { if (icon_surface != NULL) {
return icon_surface; return icon_surface;
} else {
cairo_surface_destroy(icon_surface);
icon_surface = NULL;
} }
start = end + 1; start = end + 1;
@ -328,6 +378,28 @@ static cairo_surface_t *get_icon_surface(char *icon_path)
return icon_surface; return icon_surface;
} }
static cairo_surface_t *get_icon_surface_from_raw_image(const RawImage *raw_image)
{
cairo_surface_t *icon_surface = NULL;
GdkPixbuf *pixbuf;
pixbuf = gdk_pixbuf_new_from_data(raw_image->data,
GDK_COLORSPACE_RGB,
raw_image->has_alpha,
raw_image->bits_per_sample,
raw_image->width,
raw_image->height,
raw_image->rowstride,
NULL,
NULL);
if (pixbuf != NULL) {
icon_surface = gdk_pixbuf_to_cairo_surface(pixbuf);
g_object_unref(pixbuf);
}
return icon_surface;
}
static colored_layout *r_init_shared(cairo_t *c, notification *n) static colored_layout *r_init_shared(cairo_t *c, notification *n)
{ {
colored_layout *cl = malloc(sizeof(colored_layout)); colored_layout *cl = malloc(sizeof(colored_layout));
@ -340,7 +412,11 @@ static colored_layout *r_init_shared(cairo_t *c, notification *n)
pango_layout_set_ellipsize(cl->l, PANGO_ELLIPSIZE_MIDDLE); pango_layout_set_ellipsize(cl->l, PANGO_ELLIPSIZE_MIDDLE);
} }
cl->icon = get_icon_surface(n->icon); if (n->icon) {
cl->icon = get_icon_surface_from_path(n->icon);
} else if (n->raw_icon) {
cl->icon = get_icon_surface_from_raw_image(n->raw_icon);
}
cl->fg = x_string_to_color_t(n->color_strings[ColFG]); cl->fg = x_string_to_color_t(n->color_strings[ColFG]);
cl->bg = x_string_to_color_t(n->color_strings[ColBG]); cl->bg = x_string_to_color_t(n->color_strings[ColBG]);