diff --git a/dunst.h b/dunst.h index 054c99e..a27a9fa 100644 --- a/dunst.h +++ b/dunst.h @@ -13,7 +13,8 @@ #define PERR(msg, errnum) printf("(%d) %s : %s\n", __LINE__, (msg), (strerror(errnum))) #define LENGTH(X) (sizeof X / sizeof X[0]) -#define ColLast 2 +#define ColLast 3 +#define ColFrame 2 #define ColFG 1 #define ColBG 0 @@ -28,7 +29,7 @@ extern GQueue *displayed; extern GQueue *history; extern GSList *rules; extern bool pause_display; -extern const char *color_strings[2][3]; +extern const char *color_strings[3][3]; /* return id of notification */ gboolean run(void *data); diff --git a/dunstrc b/dunstrc index 61fa321..37407c7 100644 --- a/dunstrc +++ b/dunstrc @@ -194,6 +194,7 @@ [urgency_critical] background = "#900000" foreground = "#ffffff" + frame_color = "#ff0000" timeout = 0 diff --git a/notification.c b/notification.c index da3c80a..b0b12a4 100644 --- a/notification.c +++ b/notification.c @@ -37,6 +37,7 @@ void notification_print(notification * n) printf("\tformatted: '%s'\n", n->msg); printf("\tfg: %s\n", n->color_strings[ColFG]); printf("\tbg: %s\n", n->color_strings[ColBG]); + printf("\tframe: %s\n", n->color_strings[ColFrame]); printf("\tid: %d\n", n->id); if (n->urls) { printf("\turls\n"); @@ -453,6 +454,10 @@ int notification_init(notification * n, int id) n->color_strings[ColBG] = xctx.color_strings[ColBG][n->urgency]; } + if (!n->color_strings[ColFrame]) { + n->color_strings[ColFrame] = xctx.color_strings[ColFrame][n->urgency]; + } + n->timeout = n->timeout == -1 ? settings.timeouts[n->urgency] : n->timeout; n->start = 0; diff --git a/notification.h b/notification.h index c6b0b6a..f7c3858 100644 --- a/notification.h +++ b/notification.h @@ -44,7 +44,7 @@ typedef struct _notification { int id; int dup_count; int displayed_height; - const char *color_strings[2]; + const char *color_strings[3]; bool first_render; int progress; /* percentage + 1, 0 to hide */ diff --git a/settings.c b/settings.c index ae0c14c..88229b9 100644 --- a/settings.c +++ b/settings.c @@ -277,6 +277,9 @@ void load_settings(char *cmdline_config_path) settings.lowfgcolor = option_get_string("urgency_low", "foreground", "-lf", lowfgcolor, "Foreground color for notifications with low urgency"); + settings.lowframecolor = + option_get_string("urgency_low", "frame_color", "-lfr", NULL, + "Frame color for notifications with low urgency"); settings.timeouts[LOW] = option_get_int("urgency_low", "timeout", "-lto", timeouts[LOW], "Timeout for notifications with low urgency"); @@ -291,6 +294,9 @@ void load_settings(char *cmdline_config_path) option_get_string("urgency_normal", "foreground", "-nf", normfgcolor, "Foreground color for notifications with normal urgency"); + settings.normframecolor = + option_get_string("urgency_normal", "frame_color", "-nfr", NULL, + "Frame color for notifications with normal urgency"); settings.timeouts[NORM] = option_get_int("urgency_normal", "timeout", "-nto", timeouts[NORM], "Timeout for notifications with normal urgency"); @@ -305,6 +311,9 @@ void load_settings(char *cmdline_config_path) option_get_string("urgency_critical", "foreground", "-cf", critfgcolor, "Foreground color for notifications with ciritical urgency"); + settings.critframecolor = + option_get_string("urgency_critical", "frame_color", "-cfr", NULL, + "Frame color for notifications with critical urgency"); settings.timeouts[CRIT] = option_get_int("urgency_critical", "timeout", "-cto", timeouts[CRIT], "Timeout for notifications with critical urgency"); diff --git a/settings.h b/settings.h index fec97a3..517922b 100644 --- a/settings.h +++ b/settings.h @@ -10,10 +10,13 @@ typedef struct _settings { char *font; char *normbgcolor; char *normfgcolor; + char *normframecolor; char *critbgcolor; char *critfgcolor; + char *critframecolor; char *lowbgcolor; char *lowfgcolor; + char *lowframecolor; char *format; int timeouts[3]; char *icons[3]; diff --git a/x.c b/x.c index 309839a..49e7099 100644 --- a/x.c +++ b/x.c @@ -40,15 +40,15 @@ typedef struct _colored_layout { PangoLayout *l; color_t fg; color_t bg; + color_t frame; char *text; PangoAttrList *attr; cairo_surface_t *icon; + notification *n; } colored_layout; cairo_ctx_t cairo_ctx; -static color_t frame_color; - /* FIXME refactor setup teardown handlers into one setup and one teardown */ static void x_follow_setup_error_handler(void); static int x_follow_tear_down_error_handler(void); @@ -60,8 +60,6 @@ static void x_handle_click(XEvent ev); static void x_screen_info(screen_info * scr); static void x_win_setup(void); - - static color_t x_color_hex_to_double(int hexValue) { color_t color; @@ -112,20 +110,23 @@ static color_t calculate_foreground_color(color_t bg) } -static color_t x_get_separator_color(color_t fg, color_t bg) +static color_t x_get_separator_color(colored_layout *cl, colored_layout *cl_next) { switch (settings.sep_color) { case FRAME: - return x_string_to_color_t(settings.frame_color); + if (cl_next->n->urgency > cl->n->urgency) + return cl_next->frame; + else + return cl->frame; case CUSTOM: return x_string_to_color_t(settings.sep_custom_color_str); case FOREGROUND: - return fg; + return cl->fg; case AUTO: - return calculate_foreground_color(bg); + return calculate_foreground_color(cl->bg); default: printf("Unknown separator color type. Please file a Bugreport.\n"); - return fg; + return cl->fg; } } @@ -138,8 +139,6 @@ static void x_cairo_setup(void) cairo_ctx.context = cairo_create(cairo_ctx.surface); cairo_ctx.desc = pango_font_description_from_string(settings.font); - - frame_color = x_string_to_color_t(settings.frame_color); } static void r_setup_pango_layout(PangoLayout *layout, int width) @@ -229,6 +228,7 @@ static dimension_t calculate_dimensions(GSList *layouts) dim.w = scr.dim.w; } + dim.h += 2 * settings.frame_width; dim.h += (g_slist_length(layouts) - 1) * settings.separator_height; int text_width = 0, total_width = 0; @@ -434,6 +434,9 @@ static colored_layout *r_init_shared(cairo_t *c, notification *n) cl->fg = x_string_to_color_t(n->color_strings[ColFG]); cl->bg = x_string_to_color_t(n->color_strings[ColBG]); + cl->frame = x_string_to_color_t(n->color_strings[ColFrame]); + + cl->n = n; dimension_t dim = calculate_dimensions(NULL); int width = dim.w; @@ -531,7 +534,7 @@ static void r_free_layouts(GSList *layouts) g_slist_free_full(layouts, free_colored_layout); } -static dimension_t x_render_layout(cairo_t *c, colored_layout *cl, dimension_t dim, bool first, bool last) +static dimension_t x_render_layout(cairo_t *c, colored_layout *cl, colored_layout *cl_next, dimension_t dim, bool first, bool last) { int h; pango_layout_get_pixel_size(cl->l, NULL, &h); @@ -544,11 +547,21 @@ static dimension_t x_render_layout(cairo_t *c, colored_layout *cl, dimension_t d double bg_half_height = settings.notification_height/2.0; int pango_offset = (int) floor(h/2.0); + if (first) bg_height += settings.frame_width; + if (last) bg_height += settings.frame_width; + else bg_height += settings.separator_height; + + cairo_set_source_rgb(c, cl->frame.r, cl->frame.g, cl->frame.b); + cairo_rectangle(c, bg_x, bg_y, bg_width, bg_height); + cairo_fill(c); + /* adding frame */ bg_x += settings.frame_width; if (first) { + dim.y += settings.frame_width; bg_y += settings.frame_width; bg_height -= settings.frame_width; + if (!last) bg_height -= settings.separator_height; } bg_width -= 2 * settings.frame_width; if (last) @@ -574,13 +587,18 @@ static dimension_t x_render_layout(cairo_t *c, colored_layout *cl, dimension_t d else dim.y += (int) (floor(bg_half_height) + pango_offset); - color_t sep_color = x_get_separator_color(cl->fg, cl->bg); if (settings.separator_height > 0 && !last) { + color_t sep_color = x_get_separator_color(cl, cl_next); cairo_set_source_rgb(c, sep_color.r, sep_color.g, sep_color.b); - cairo_rectangle(c, settings.frame_width, dim.y, - dim.w - 2 * settings.frame_width - , settings.separator_height); + if (settings.sep_color == FRAME) + // Draw over the borders on both sides to avoid + // the wrong color in the corners. + cairo_rectangle(c, 0, dim.y, dim.w, settings.separator_height); + else + cairo_rectangle(c, settings.frame_width, dim.y, + dim.w - 2 * settings.frame_width, + settings.separator_height); cairo_fill(c); dim.y += settings.separator_height; @@ -624,16 +642,15 @@ void x_win_draw(void) x_win_move(width, height); cairo_xlib_surface_set_size(cairo_ctx.surface, width, height); - cairo_set_source_rgb(c, frame_color.r, frame_color.g, frame_color.b); - cairo_rectangle(c, 0.0, 0.0, width, height); - cairo_fill(c); - cairo_move_to(c, 0, 0); bool first = true; for (GSList *iter = layouts; iter; iter = iter->next) { - colored_layout *cl = iter->data; - dim = x_render_layout(c, cl, dim, first, iter->next == NULL); + if (iter->next) + dim = x_render_layout(c, iter->data, iter->next->data, dim, first, iter->next == NULL); + else + dim = x_render_layout(c, iter->data, NULL, dim, first, iter->next == NULL); + first = false; } @@ -1055,6 +1072,19 @@ void x_setup(void) xctx.color_strings[ColBG][NORM] = settings.normbgcolor; xctx.color_strings[ColBG][CRIT] = settings.critbgcolor; + if (settings.lowframecolor) + xctx.color_strings[ColFrame][LOW] = settings.lowframecolor; + else + xctx.color_strings[ColFrame][LOW] = settings.frame_color; + if (settings.normframecolor) + xctx.color_strings[ColFrame][NORM] = settings.normframecolor; + else + xctx.color_strings[ColFrame][NORM] = settings.frame_color; + if (settings.critframecolor) + xctx.color_strings[ColFrame][CRIT] = settings.critframecolor; + else + xctx.color_strings[ColFrame][CRIT] = settings.frame_color; + /* parse and set xctx.geometry and monitor position */ if (settings.geom[0] == '-') { xctx.geometry.negative_width = true; diff --git a/x.h b/x.h index 48b076f..cc366b9 100644 --- a/x.h +++ b/x.h @@ -46,10 +46,9 @@ typedef struct _xctx { Window win; bool visible; dimension_t geometry; - const char *color_strings[2][3]; + const char *color_strings[3][3]; XScreenSaverInfo *screensaver_info; dimension_t window_dim; - unsigned long framec; unsigned long sep_custom_col; } xctx_t;