Try to support raw image data (see knopwob/dunst#151 )

This commit is contained in:
Andrew Krasichkov 2016-03-09 18:37:04 +02:00
parent b6f56be97b
commit a6d9626c54
4 changed files with 123 additions and 21 deletions

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;

64
x.c
View File

@ -286,6 +286,24 @@ static dimension_t calculate_dimensions(GSList *layouts)
return dim; return dim;
} }
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) static cairo_surface_t *get_icon_surface_from_file(const char *icon_path)
{ {
cairo_surface_t *icon_surface = NULL; cairo_surface_t *icon_surface = NULL;
@ -297,23 +315,9 @@ static cairo_surface_t *get_icon_surface_from_file(const char *icon_path)
} else { } else {
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
GError *error = NULL; GError *error = NULL;
cairo_t *cr;
cairo_format_t format;
double width, height;
pixbuf = gdk_pixbuf_new_from_file(icon_path, &error); pixbuf = gdk_pixbuf_new_from_file(icon_path, &error);
if (pixbuf != NULL) { if (pixbuf != NULL) {
if (gdk_pixbuf_get_has_alpha(pixbuf)) { icon_surface = gdk_pixbuf_to_cairo_surface(pixbuf);
format = CAIRO_FORMAT_ARGB32;
} else {
format = 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);
g_object_unref(pixbuf); g_object_unref(pixbuf);
} else { } else {
g_free(error); g_free(error);
@ -327,7 +331,7 @@ static cairo_surface_t *get_icon_surface_from_file(const char *icon_path)
return icon_surface; return icon_surface;
} }
static cairo_surface_t *get_icon_surface(char *icon_path) 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;
@ -374,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));
@ -386,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]);