Add icon support
- icons are displayed at the top left corner - disabed by default, fully backwards-compatible - no additional dependencies, only cairo used - TODO: only supports png (but all default images are png) - TODO: message formatting is sometimes buggy
This commit is contained in:
parent
2638178e5a
commit
c2801181f8
6
dunstrc
6
dunstrc
@ -138,6 +138,12 @@
|
|||||||
# Browser for opening urls in context menu.
|
# Browser for opening urls in context menu.
|
||||||
browser = /usr/bin/firefox -new-tab
|
browser = /usr/bin/firefox -new-tab
|
||||||
|
|
||||||
|
# Show icons in notifications.
|
||||||
|
show_icons = no
|
||||||
|
|
||||||
|
# Path to default icons.
|
||||||
|
icon_path = /usr/share/icons/gnome/32x32/status/%s.png
|
||||||
|
|
||||||
[frame]
|
[frame]
|
||||||
width = 3
|
width = 3
|
||||||
color = "#aaaaaa"
|
color = "#aaaaaa"
|
||||||
|
@ -281,6 +281,11 @@ int notification_init(notification * n, int id)
|
|||||||
|
|
||||||
n->urls = notification_extract_markup_urls(&(n->body));
|
n->urls = notification_extract_markup_urls(&(n->body));
|
||||||
|
|
||||||
|
/* Add icon path if relative */
|
||||||
|
if (strlen(n->icon) > 0 && n->icon[0] != '/' && n->icon[0] != '~') {
|
||||||
|
n->icon = string_replace("%s", n->icon, settings.icon_path);
|
||||||
|
}
|
||||||
|
|
||||||
n->msg = string_replace("%a", n->appname, g_strdup(n->format));
|
n->msg = string_replace("%a", n->appname, g_strdup(n->format));
|
||||||
n->msg = string_replace("%s", n->summary, n->msg);
|
n->msg = string_replace("%s", n->summary, n->msg);
|
||||||
if (n->icon) {
|
if (n->icon) {
|
||||||
|
@ -192,6 +192,15 @@ void load_settings(char *cmdline_config_path)
|
|||||||
option_get_string("global", "browser", "-browser", browser,
|
option_get_string("global", "browser", "-browser", browser,
|
||||||
"path to browser");
|
"path to browser");
|
||||||
|
|
||||||
|
settings.show_icons =
|
||||||
|
option_get_bool("global", "show_icons",
|
||||||
|
"-show_icons", false,
|
||||||
|
"show icons in notifications");
|
||||||
|
|
||||||
|
settings.icon_path =
|
||||||
|
option_get_string("global", "icon_path", "-icon_path", icon_path,
|
||||||
|
"path to default icons");
|
||||||
|
|
||||||
settings.frame_width =
|
settings.frame_width =
|
||||||
option_get_int("frame", "width", "-frame_width", frame_width,
|
option_get_int("frame", "width", "-frame_width", frame_width,
|
||||||
"Width of frame around window");
|
"Width of frame around window");
|
||||||
|
@ -42,6 +42,8 @@ typedef struct _settings {
|
|||||||
char *dmenu;
|
char *dmenu;
|
||||||
char **dmenu_cmd;
|
char **dmenu_cmd;
|
||||||
char *browser;
|
char *browser;
|
||||||
|
bool show_icons;
|
||||||
|
char *icon_path;
|
||||||
enum follow_mode f_mode;
|
enum follow_mode f_mode;
|
||||||
keyboard_shortcut close_ks;
|
keyboard_shortcut close_ks;
|
||||||
keyboard_shortcut close_all_ks;
|
keyboard_shortcut close_all_ks;
|
||||||
|
40
x.c
40
x.c
@ -40,6 +40,7 @@ typedef struct _colored_layout {
|
|||||||
color_t bg;
|
color_t bg;
|
||||||
char *text;
|
char *text;
|
||||||
PangoAttrList *attr;
|
PangoAttrList *attr;
|
||||||
|
cairo_surface_t *icon;
|
||||||
} colored_layout;
|
} colored_layout;
|
||||||
|
|
||||||
cairo_ctx_t cairo_ctx;
|
cairo_ctx_t cairo_ctx;
|
||||||
@ -166,6 +167,7 @@ static void free_colored_layout(void *data)
|
|||||||
g_object_unref(cl->l);
|
g_object_unref(cl->l);
|
||||||
pango_attr_list_unref(cl->attr);
|
pango_attr_list_unref(cl->attr);
|
||||||
g_free(cl->text);
|
g_free(cl->text);
|
||||||
|
if (cl->icon) cairo_surface_destroy(cl->icon);
|
||||||
g_free(cl);
|
g_free(cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,11 +205,20 @@ static dimension_t calculate_dimensions(GSList *layouts)
|
|||||||
dim.h += (g_slist_length(layouts) - 1) * settings.separator_height;
|
dim.h += (g_slist_length(layouts) - 1) * settings.separator_height;
|
||||||
dim.h += g_slist_length(layouts) * settings.padding * 2;
|
dim.h += g_slist_length(layouts) * settings.padding * 2;
|
||||||
|
|
||||||
|
/* text_width: width of the widest content so far
|
||||||
|
* total_width: width of the widest notification so far, with padding
|
||||||
|
* dim.w: width of the window, with frame
|
||||||
|
* Also call r_setup_pango_layout() when changing text_width.
|
||||||
|
*/
|
||||||
int text_width = 0, total_width = 0;
|
int text_width = 0, total_width = 0;
|
||||||
for (GSList *iter = layouts; iter; iter = iter->next) {
|
for (GSList *iter = layouts; iter; iter = iter->next) {
|
||||||
colored_layout *cl = iter->data;
|
colored_layout *cl = iter->data;
|
||||||
int w=0,h=0;
|
int w=0,h=0;
|
||||||
pango_layout_get_pixel_size(cl->l, &w, &h);
|
pango_layout_get_pixel_size(cl->l, &w, &h);
|
||||||
|
if (cl->icon) {
|
||||||
|
h = MAX(cairo_image_surface_get_height(cl->icon), h);
|
||||||
|
w += cairo_image_surface_get_width(cl->icon) + settings.h_padding;
|
||||||
|
}
|
||||||
dim.h += h;
|
dim.h += h;
|
||||||
text_width = MAX(w, text_width);
|
text_width = MAX(w, text_width);
|
||||||
|
|
||||||
@ -227,13 +238,18 @@ static dimension_t calculate_dimensions(GSList *layouts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* re-setup the layout */
|
/* re-setup the layout */
|
||||||
int width = dim.w;
|
w = dim.w;
|
||||||
width -= 2 * settings.h_padding;
|
w -= 2 * settings.h_padding;
|
||||||
width -= 2 * settings.frame_width;
|
w -= 2 * settings.frame_width;
|
||||||
r_setup_pango_layout(cl->l, width);
|
if (cl->icon) w -= cairo_image_surface_get_width(cl->icon) + settings.h_padding;
|
||||||
|
r_setup_pango_layout(cl->l, w);
|
||||||
|
|
||||||
/* re-read information */
|
/* re-read information */
|
||||||
pango_layout_get_pixel_size(cl->l, &w, &h);
|
pango_layout_get_pixel_size(cl->l, &w, &h);
|
||||||
|
if (cl->icon) {
|
||||||
|
h = MAX(cairo_image_surface_get_height(cl->icon), h);
|
||||||
|
w += cairo_image_surface_get_width(cl->icon) + settings.h_padding;
|
||||||
|
}
|
||||||
dim.h += h;
|
dim.h += h;
|
||||||
text_width = MAX(w, text_width);
|
text_width = MAX(w, text_width);
|
||||||
}
|
}
|
||||||
@ -256,6 +272,9 @@ 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 = NULL;
|
||||||
|
if (strlen(n->icon) > 0 && settings.show_icons)
|
||||||
|
cl->icon = cairo_image_surface_create_from_png(n->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]);
|
||||||
@ -268,6 +287,7 @@ static colored_layout *r_init_shared(cairo_t *c, notification *n)
|
|||||||
} else {
|
} else {
|
||||||
width -= 2 * settings.h_padding;
|
width -= 2 * settings.h_padding;
|
||||||
width -= 2 * settings.frame_width;
|
width -= 2 * settings.frame_width;
|
||||||
|
if (cl->icon) width -= cairo_image_surface_get_width(cl->icon) + settings.h_padding;
|
||||||
r_setup_pango_layout(cl->l, width);
|
r_setup_pango_layout(cl->l, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,6 +329,7 @@ static colored_layout *r_create_layout_from_notification(cairo_t *c, notificatio
|
|||||||
|
|
||||||
|
|
||||||
pango_layout_get_pixel_size(cl->l, NULL, &(n->displayed_height));
|
pango_layout_get_pixel_size(cl->l, NULL, &(n->displayed_height));
|
||||||
|
if (cl->icon) n->displayed_height = MAX(cairo_image_surface_get_height(cl->icon), n->displayed_height);
|
||||||
n->displayed_height += 2 * settings.padding;
|
n->displayed_height += 2 * settings.padding;
|
||||||
|
|
||||||
n->first_render = false;
|
n->first_render = false;
|
||||||
@ -358,6 +379,7 @@ static dimension_t x_render_layout(cairo_t *c, colored_layout *cl, dimension_t d
|
|||||||
{
|
{
|
||||||
int h;
|
int h;
|
||||||
pango_layout_get_pixel_size(cl->l, NULL, &h);
|
pango_layout_get_pixel_size(cl->l, NULL, &h);
|
||||||
|
if (cl->icon) h = MAX(cairo_image_surface_get_height(cl->icon), h);
|
||||||
|
|
||||||
int bg_x = 0;
|
int bg_x = 0;
|
||||||
int bg_y = dim.y;
|
int bg_y = dim.y;
|
||||||
@ -397,6 +419,16 @@ static dimension_t x_render_layout(cairo_t *c, colored_layout *cl, dimension_t d
|
|||||||
}
|
}
|
||||||
cairo_move_to(c, settings.h_padding, dim.y);
|
cairo_move_to(c, settings.h_padding, dim.y);
|
||||||
|
|
||||||
|
if (cl->icon) {
|
||||||
|
unsigned int image_width = cairo_image_surface_get_width(cl->icon),
|
||||||
|
image_height = cairo_image_surface_get_height(cl->icon),
|
||||||
|
image_x = bg_width - settings.h_padding - image_width,
|
||||||
|
image_y = bg_y + settings.padding;
|
||||||
|
cairo_set_source_surface (c, cl->icon, image_x, image_y);
|
||||||
|
cairo_rectangle (c, image_x, image_y, image_width, image_height);
|
||||||
|
cairo_fill (c);
|
||||||
|
}
|
||||||
|
|
||||||
return dim;
|
return dim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user