Merge icon handling from buglloc/master
This commit is contained in:
commit
33ab80f1a9
@ -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
54
dbus.c
@ -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;
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
100
x.c
@ -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]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user