Try to support raw image data (see knopwob/dunst#151 )
This commit is contained in:
parent
b6f56be97b
commit
a6d9626c54
54
dbus.c
54
dbus.c
@ -74,6 +74,7 @@ static void onGetServerInformation(GDBusConnection * connection,
|
||||
const gchar * sender,
|
||||
const GVariant * parameters,
|
||||
GDBusMethodInvocation * invocation);
|
||||
static RawImage * get_raw_image_from_data_hint(GVariant *icon_data);
|
||||
|
||||
void handle_method_call(GDBusConnection * connection,
|
||||
const gchar * sender,
|
||||
@ -140,6 +141,7 @@ static void onNotify(GDBusConnection * connection,
|
||||
gchar *fgcolor = NULL;
|
||||
gchar *bgcolor = NULL;
|
||||
gchar *category = NULL;
|
||||
RawImage *raw_icon = NULL;
|
||||
|
||||
actions->actions = NULL;
|
||||
actions->count = 0;
|
||||
@ -232,6 +234,23 @@ static void onNotify(GDBusConnection * connection,
|
||||
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 =
|
||||
g_variant_lookup_value(content,
|
||||
"value",
|
||||
@ -283,6 +302,7 @@ static void onNotify(GDBusConnection * connection,
|
||||
n->summary = summary;
|
||||
n->body = body;
|
||||
n->icon = icon;
|
||||
n->raw_icon = raw_icon;
|
||||
n->timeout = timeout;
|
||||
n->allow_markup = settings.allow_markup;
|
||||
n->plain_text = settings.plain_text;
|
||||
@ -412,6 +432,40 @@ static void on_name_lost(GDBusConnection * connection,
|
||||
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)
|
||||
{
|
||||
guint owner_id;
|
||||
|
@ -161,6 +161,12 @@ void notification_free(notification * n)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -442,11 +448,12 @@ int notification_init(notification * n, int id)
|
||||
n->timeout == -1 ? settings.timeouts[n->urgency] : n->timeout;
|
||||
n->start = 0;
|
||||
|
||||
if (n->icon == NULL) {
|
||||
n->icon = strdup(settings.icons[n->urgency]);
|
||||
}
|
||||
else if (strlen(n->icon) <= 0) {
|
||||
if (strlen(n->icon) <= 0) {
|
||||
free(n->icon);
|
||||
n->icon = NULL;
|
||||
}
|
||||
|
||||
if (n->raw_icon == NULL && n->icon == NULL) {
|
||||
n->icon = strdup(settings.icons[n->urgency]);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,16 @@
|
||||
#define NORM 1
|
||||
#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 {
|
||||
char **actions;
|
||||
char *dmenu_str;
|
||||
@ -18,6 +28,7 @@ typedef struct _notification {
|
||||
char *summary;
|
||||
char *body;
|
||||
char *icon;
|
||||
RawImage *raw_icon;
|
||||
char *msg; /* formatted message */
|
||||
char *category;
|
||||
char *text_to_render;
|
||||
|
64
x.c
64
x.c
@ -286,6 +286,24 @@ static dimension_t calculate_dimensions(GSList *layouts)
|
||||
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)
|
||||
{
|
||||
cairo_surface_t *icon_surface = NULL;
|
||||
@ -297,23 +315,9 @@ static cairo_surface_t *get_icon_surface_from_file(const char *icon_path)
|
||||
} else {
|
||||
GdkPixbuf *pixbuf;
|
||||
GError *error = NULL;
|
||||
cairo_t *cr;
|
||||
cairo_format_t format;
|
||||
double width, height;
|
||||
pixbuf = gdk_pixbuf_new_from_file(icon_path, &error);
|
||||
if (pixbuf != NULL) {
|
||||
if (gdk_pixbuf_get_has_alpha(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);
|
||||
icon_surface = gdk_pixbuf_to_cairo_surface(pixbuf);
|
||||
g_object_unref(pixbuf);
|
||||
} else {
|
||||
g_free(error);
|
||||
@ -327,7 +331,7 @@ static cairo_surface_t *get_icon_surface_from_file(const char *icon_path)
|
||||
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;
|
||||
gchar *uri_path = NULL;
|
||||
@ -374,6 +378,28 @@ static cairo_surface_t *get_icon_surface(char *icon_path)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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->bg = x_string_to_color_t(n->color_strings[ColBG]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user