10#include <pango/pango-attributes.h>
11#include <pango/pangocairo.h>
12#include <pango/pango-font.h>
13#include <pango/pango-layout.h>
14#include <pango/pango-types.h>
35 cairo_surface_t *icon;
43PangoFontDescription *pango_fdesc;
46#define COLOR(cl, field) (cl)->n->colors.field
48void load_icon_themes(
void)
50 bool loaded_theme =
false;
52 for (
int i = 0;
settings.icon_theme[i] != NULL; i++) {
53 char *theme =
settings.icon_theme[i];
55 if (theme_index >= 0) {
56 LOG_I(
"Adding icon theme %s", theme);
70 if (!COLOR_VALID(c))
return NULL;
72 g_snprintf(buf, 10,
"#%02x%02x%02x%02x",
95 return grad != NULL ? g_rc_box_acquire(grad) : NULL;
98static void gradient_free(
struct gradient *grad)
101 cairo_pattern_destroy(grad->pattern);
104void gradient_release(
struct gradient *grad)
107 g_rc_box_release_full(grad, (GDestroyNotify)gradient_free);
110void gradient_pattern(
struct gradient *grad)
112 if (grad->length == 1) {
113 grad->pattern = cairo_pattern_create_rgba(grad->colors[0].r,
118 grad->pattern = cairo_pattern_create_linear(0, 0, 1, 0);
119 for (
size_t i = 0; i < grad->length; i++) {
120 double offset = i / (double)(grad->length - 1);
121 cairo_pattern_add_color_stop_rgba(grad->pattern,
131char *gradient_to_string(
const struct gradient *grad)
133 if (!GRADIENT_VALID(grad))
return NULL;
135 int max = grad->length * 11 + 1;
136 char *buf = g_malloc(max);
138 for (
size_t i = 0, j = 0; i < grad->length; i++) {
139 j += g_snprintf(buf + j, max - j,
"#%02x%02x%02x%02x",
140 (
int)(grad->colors[i].r * 255),
141 (
int)(grad->colors[i].g * 255),
142 (
int)(grad->colors[i].b * 255),
143 (
int)(grad->colors[i].a * 255));
145 if (i != grad->length - 1) {
146 j += g_snprintf(buf + j, max - j,
", ");
158 win = out->win_create();
160 LOG_D(
"Trying to load font: '%s'",
settings.font);
161 pango_fdesc = pango_font_description_from_string(
settings.font);
162 LOG_D(
"Loaded closest matching font: '%s'", pango_font_description_get_family(pango_fdesc));
164 if (
settings.enable_recursive_icon_lookup)
168static inline double color_apply_delta(
double base,
double delta)
179static struct color calculate_foreground_color(struct
color bg)
181 double c_delta = 0.1;
182 struct color fg = bg;
185 bool darken = (bg.r + bg.g + bg.b) / 3 > 0.5;
187 int signedness = darken ? -1 : 1;
189 fg.r = color_apply_delta(fg.r, c_delta * signedness);
190 fg.g = color_apply_delta(fg.g, c_delta * signedness);
191 fg.b = color_apply_delta(fg.b, c_delta * signedness);
201 return COLOR(cl_next->n->urgency > cl->n->urgency ? cl_next : cl, frame);
205 return COLOR(cl, fg);
207 return calculate_foreground_color(COLOR(cl, bg));
209 LOG_E(
"Invalid %s enum value in %s:%d",
"sep_color", __FILE__, __LINE__);
214static int get_horizontal_text_icon_padding(
struct notification *n)
216 bool horizontal_icon = (
219 if (
settings.text_icon_padding && horizontal_icon) {
226static int get_vertical_text_icon_padding(
struct notification *n)
229 if (
settings.text_icon_padding && vertical_icon) {
242static void get_text_size(PangoLayout *l,
int *w,
int *h,
double scale) {
243 pango_layout_get_pixel_size(l, w, h);
247 *w = ceil(*w / scale);
249 *h = ceil(*h / scale);
255static void layout_setup_pango(PangoLayout *layout,
int width,
int height,
256 bool word_wrap, PangoEllipsizeMode ellipsize_mode,
257 PangoAlignment alignment)
259 double scale =
output->get_scale();
260 pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
261 pango_layout_set_width(layout, round(width * scale * PANGO_SCALE));
265 pango_layout_set_height(layout, round(height * scale * PANGO_SCALE));
267 pango_layout_set_font_description(layout, pango_fdesc);
268 pango_layout_set_spacing(layout, round(
settings.line_height * scale * PANGO_SCALE));
270 pango_layout_set_ellipsize(layout, ellipsize_mode);
272 pango_layout_set_alignment(layout, alignment);
278static void layout_setup(
struct colored_layout *cl,
int width,
int height,
double scale)
280 int horizontal_padding = get_horizontal_text_icon_padding(cl->n);
281 int icon_width = cl->icon ?
get_icon_width(cl->icon, scale) + horizontal_padding : 0;
282 int text_width = width - 2 *
settings.h_padding - (cl->n->
icon_position == ICON_TOP ? 0 : icon_width);
283 int progress_bar_height = have_progress_bar(cl) ?
settings.progress_bar_height +
settings.padding : 0;
284 int max_text_height = MAX(0,
settings.height.max - progress_bar_height - 2 *
settings.padding);
285 layout_setup_pango(cl->l, text_width, max_text_height, cl->n->word_wrap, cl->n->ellipsize, cl->n->alignment);
288static void free_colored_layout(
void *data)
291 g_object_unref(cl->l);
292 pango_attr_list_unref(cl->attr);
303 int horizontal_padding = get_horizontal_text_icon_padding(cl->n);
304 int icon_width = cl->icon?
get_icon_width(cl->icon, scale) + horizontal_padding : 0;
306 int progress_bar_height = have_progress_bar(cl) ?
settings.progress_bar_height +
settings.padding : 0;
308 int vertical_padding;
309 if (cl->n->hide_text) {
310 vertical_padding = 0;
314 get_text_size(cl->l, &dim.text_width, &dim.text_height, scale);
315 vertical_padding = get_vertical_text_icon_padding(cl->n);
318 if (cl->n->icon_position == ICON_TOP && cl->n->icon) {
319 dim.h = icon_height + dim.text_height + vertical_padding;
321 dim.h = MAX(icon_height, dim.text_height);
324 dim.h += progress_bar_height +
settings.padding * 2;
325 dim.w = dim.text_width + icon_width + 2 *
settings.h_padding;
327 if (have_progress_bar(cl))
328 dim.w = MAX(
settings.progress_bar_min_width, dim.w);
330 dim.h = MAX(
settings.height.min, dim.h);
331 dim.h = MIN(
settings.height.max, dim.h);
333 dim.w = MAX(
settings.width.min, dim.w);
334 dim.w = MIN(
settings.width.max, dim.w);
336 cl->n->displayed_height = dim.h;
340static struct dimensions calculate_dimensions(GSList *layouts)
342 int layout_count = g_slist_length(layouts);
344 double scale =
output->get_scale();
346 dim.corner_radius =
settings.corner_radius;
348 for (GSList *iter = layouts; iter; iter = iter->next) {
350 struct dimensions n_dim = calculate_notification_dimensions(cl, scale);
352 LOG_D(
"Notification dimensions %ix%i", n_dim.w, n_dim.h);
353 dim.w = MAX(dim.w, n_dim.w +
settings.frame_width);
357 dim.corner_radius = MIN(dim.corner_radius, dim.h/2);
362 if (dim.w > max_width) {
367 int extra_frame_height = layout_count * (2 *
settings.frame_width);
368 int extra_gap_height = (layout_count *
settings.gap_size) -
settings.gap_size;
369 int total_extra_height = extra_frame_height + extra_gap_height;
370 dim.h += total_extra_height;
373 dim.h += (layout_count - 1) *
settings.separator_height;
379static PangoLayout *layout_create(cairo_t *c)
383 PangoContext *context = pango_cairo_create_context(c);
384 pango_cairo_context_set_resolution(context, screen->dpi);
386 PangoLayout *layout = pango_layout_new(context);
388 g_object_unref(context);
396 cl->l = layout_create(c);
397 cl->is_xmore =
false;
401 assert(
settings.frame_width == 0 || COLOR_VALID(COLOR(cl, frame)));
402 assert(!have_progress_bar(cl) || COLOR(cl, highlight) != NULL);
403 assert(COLOR_VALID(COLOR(cl, fg)));
404 assert(COLOR_VALID(COLOR(cl, bg)));
411 cl->text = g_strdup_printf(
"(%d more)", qlen);
415 pango_layout_set_text(cl->l, cl->text, -1);
432 pango_parse_markup(n->
text_to_render, -1, 0, &(cl->attr), &(cl->text), NULL, &err);
435 pango_layout_set_text(cl->l, cl->text, -1);
436 pango_attr_list_insert(cl->attr, pango_attr_fallback_new(
true));
437 pango_layout_set_attributes(cl->l, cl->attr);
442 cl->attr = pango_attr_list_new();
443 pango_attr_list_insert(cl->attr, pango_attr_fallback_new(
true));
446 LOG_W(
"Unable to parse markup: %s", err->message);
455static GSList *create_layouts(cairo_t *c)
457 GSList *layouts = NULL;
460 bool xmore_is_needed = qlen > 0 &&
settings.indicate_hidden;
463 iter; iter = iter->next)
467 notification_update_text_to_render(n);
469 if (!iter->next && xmore_is_needed &&
settings.notification_limit == 1) {
470 char *new_ttr = g_strdup_printf(
"%s (%d more)", n->
text_to_render, qlen);
474 layouts = g_slist_append(layouts,
475 layout_from_notification(c, n));
478 if (xmore_is_needed &&
settings.notification_limit != 1) {
480 layouts = g_slist_append(layouts,
488static int layout_get_height(
struct colored_layout *cl,
double scale)
492 int h_progress_bar = 0;
494 int vertical_padding;
495 if (cl->n->hide_text) {
496 vertical_padding = 0;
498 get_text_size(cl->l, NULL, &h_text, scale);
499 vertical_padding = get_vertical_text_icon_padding(cl->n);
505 if (have_progress_bar(cl)) {
510 ? h_icon + h_text + h_progress_bar + vertical_padding
511 : MAX(h_text, h_icon) + h_progress_bar;
520static int frame_internal_radius (
int r,
int w,
int h)
522 if (r == 0 || h + (w - r) * 2 == 0)
526 const int s = 2 << (8 *
sizeof(int) / 4);
532 r1 = r - w + w * w / (r * 2);
533 r2 = r * h / (h + (w - r) * 2);
535 ret = (r > w) ? r1 : (r / 2 < r2) ? r / 2 : r2;
543static inline void draw_rect(cairo_t *c,
double x,
double y,
double width,
double height,
double scale)
545 cairo_rectangle(c, round(x * scale), round(y * scale), round(width * scale), round(height * scale));
559 if (corners == C_NONE || corner_radius <= 0) {
560 draw_rect(c, x, y, width, height, scale);
564 width = round(width * scale);
565 height = round(height * scale);
568 corner_radius = round(corner_radius * scale);
571 if (width <= 0 || height <= 0 || scale <= 0)
574 const double degrees = M_PI / 180.0;
581 float top_y_off = 0, bot_y_off = 0, top_x_off, bot_x_off;
582 top_x_off = bot_x_off = MAX(width - corner_radius, corner_radius);
584 double bot_left_angle1 = degrees * 90;
585 double bot_left_angle2 = degrees * 180;
587 double top_left_angle1 = degrees * 180;
588 double top_left_angle2 = degrees * 270;
590 double top_right_angle1 = degrees * 270;
591 double top_right_angle2 = degrees * 360;
593 double bot_right_angle1 = degrees * 0;
594 double bot_right_angle2 = degrees * 90;
598 if (width <= corner_radius) {
599 double angle1 = 0, angle2 = 0;
602 if ((corners & C_TOP) == C_TOP)
603 angle1 = acos(1.0 - ((
double)width / 2.0) / (
double)corner_radius);
605 angle1 = acos(1.0 - (
double)width / (
double)corner_radius);
607 if ((corners & C_BOT) == C_BOT)
608 angle2 = acos(1.0 - ((
double)width / 2.0) / (
double)corner_radius);
610 angle2 = acos(1.0 - (
double)width / (
double)corner_radius);
612 if ((corners & (C_TOP_RIGHT | C_BOT_LEFT)) == (C_TOP_RIGHT | C_BOT_LEFT) && !(corners & C_TOP_LEFT)) {
613 top_y_off -= corner_radius * (1.0 - sin(angle1));
616 if ((corners & (C_TOP_LEFT | C_BOT_RIGHT)) == (C_TOP_LEFT | C_BOT_RIGHT) && !(corners & C_BOT_LEFT)) {
617 bot_y_off = corner_radius * (1.0 - sin(angle2));
620 top_left_angle2 = degrees * 180 + angle1;
621 top_right_angle1 = degrees * 360 - angle1;
622 bot_left_angle1 = degrees * 180 - angle2;
623 bot_right_angle2 = angle2;
625 top_x_off = -(corner_radius - width);
626 bot_x_off = -(corner_radius - width);
628 if (corners != C_TOP && corners != C_BOT)
631 }
else if (width <= corner_radius * 2 && (corners & C_LEFT && corners & C_RIGHT)) {
632 double angle1 = 0, angle2 = 0;
633 if (!(corners & C_TOP_LEFT) && corners & C_TOP_RIGHT)
634 top_x_off = width - corner_radius;
636 angle1 = acos((
double)width / (
double)corner_radius - 1.0);
638 if (!(corners & C_BOT_LEFT) && corners & C_BOT_RIGHT)
639 bot_x_off = width - corner_radius;
641 angle2 = acos((
double)width / (
double)corner_radius - 1.0);
643 top_right_angle2 = degrees * 360 - angle1;
644 bot_right_angle1 = angle2;
647 cairo_new_sub_path(c);
650 if (!(skip & C_BOT_LEFT)) {
651 if (corners & C_BOT_LEFT) {
654 y + height - corner_radius,
659 cairo_line_to(c, x, y + height);
664 if (!(skip & C_TOP_LEFT)) {
665 if (corners & C_TOP_LEFT) {
673 cairo_line_to(c, x, y);
678 if (!(skip & C_TOP_RIGHT)) {
679 if (corners & C_TOP_RIGHT) {
682 y + corner_radius + top_y_off,
687 cairo_line_to(c, x + width, y);
692 if (!(skip & C_BOT_RIGHT)) {
693 if (corners & C_BOT_RIGHT) {
696 y + height - corner_radius + bot_y_off,
701 cairo_line_to(c, x + width, y + height);
708static cairo_surface_t *render_background(cairo_surface_t *srf,
720 int radius_int = corner_radius;
722 cairo_t *c = cairo_create(srf);
725 cairo_set_fill_rule(c, CAIRO_FILL_RULE_EVEN_ODD);
728 cairo_set_operator(c, CAIRO_OPERATOR_ADD);
730 if (corners & (C_TOP | _C_FIRST))
732 if (corners & (C_BOT | _C_LAST))
735 height +=
settings.separator_height;
741 if (corners & (C_TOP | _C_FIRST)) {
748 if (corners & (C_BOT | _C_LAST))
751 height -=
settings.separator_height;
753 radius_int = frame_internal_radius(corner_radius,
settings.frame_width, height);
756 cairo_set_source_rgba(c, COLOR(cl, frame.r), COLOR(cl, frame.g), COLOR(cl, frame.b), COLOR(cl, frame.a));
760 cairo_set_source_rgba(c, COLOR(cl, bg.r), COLOR(cl, bg.g), COLOR(cl, bg.b), COLOR(cl, bg.a));
763 cairo_set_operator(c, CAIRO_OPERATOR_SOURCE);
765 if (
settings.sep_color.type != SEP_FRAME
767 && (corners & (C_BOT | _C_LAST)) == 0) {
768 struct color sep_color = layout_get_sepcolor(cl, cl_next);
769 cairo_set_source_rgba(c, sep_color.r, sep_color.g, sep_color.b, sep_color.a);
781 return cairo_surface_create_for_rectangle(srf,
782 round(x * scale), round(y * scale),
783 round(width * scale), round(height * scale));
786static void render_content(cairo_t *c,
struct colored_layout *cl,
int width,
int height,
double scale)
790 layout_setup(cl, width, height, scale);
793 int h_without_progress_bar = height;
794 if (have_progress_bar(cl)) {
799 if (!cl->n->hide_text) {
800 get_text_size(cl->l, NULL, &text_h, scale);
807 if (
settings.vertical_alignment == VERTICAL_CENTER) {
808 text_y = h_without_progress_bar / 2 - text_h / 2;
809 }
else if (
settings.vertical_alignment == VERTICAL_BOTTOM) {
810 text_y = h_without_progress_bar -
settings.padding - text_h;
811 if (text_y < 0) text_y =
settings.padding;
818 image_x = width -
settings.h_padding - image_width,
820 v_padding = get_vertical_text_icon_padding(cl->n);
823 switch (
settings.vertical_alignment) {
827 text_y += image_height + v_padding;
830 case VERTICAL_CENTER:
833 image_y -= (image_height + v_padding) / 2;
834 text_y += (image_height + v_padding) / 2;
836 image_y += text_h / 2 - image_height / 2;
839 case VERTICAL_BOTTOM:
841 image_y -= image_height + v_padding;
843 image_y -= image_height - text_h;
850 image_x = (width - image_width) / 2;
853 text_x += image_width + get_horizontal_text_icon_padding(cl->n);
856 cairo_set_source_surface(c, cl->icon, round(image_x * scale), round(image_y * scale));
862 if (!cl->n->hide_text) {
863 cairo_move_to(c, round(text_x * scale), round(text_y * scale));
864 cairo_set_source_rgba(c, COLOR(cl, fg.r), COLOR(cl, fg.g), COLOR(cl, fg.b), COLOR(cl, fg.a));
865 pango_cairo_update_layout(c, cl->l);
866 pango_cairo_show_layout(c, cl->l);
870 if (have_progress_bar(cl)) {
871 int progress = MIN(cl->n->
progress, 100);
872 unsigned int frame_x = 0;
873 unsigned int frame_width =
settings.progress_bar_frame_width,
874 progress_width = MIN(width - 2 *
settings.h_padding,
settings.progress_bar_max_width),
875 progress_height =
settings.progress_bar_height - frame_width,
876 frame_y = h_without_progress_bar,
877 progress_width_without_frame = progress_width - 2 * frame_width,
878 progress_width_1 = progress_width_without_frame * progress / 100,
879 progress_width_2 = progress_width_without_frame - 1,
880 progress_width_scaled = (progress_width + 1) * scale;
883 case PANGO_ALIGN_LEFT:
886 case PANGO_ALIGN_CENTER:
887 frame_x = width/2 - progress_width/2;
889 case PANGO_ALIGN_RIGHT:
890 frame_x = width - progress_width -
settings.h_padding;
893 unsigned int x_bar_1 = frame_x + frame_width,
894 x_bar_2 = x_bar_1 + 0.5;
896 double half_frame_width = (double)frame_width / 2.0;
905 cairo_set_source_rgba(c, COLOR(cl, bg.r), COLOR(cl, bg.g), COLOR(cl, bg.b), COLOR(cl, bg.a));
911 cairo_matrix_t matrix;
912 cairo_matrix_init_scale(&matrix, 1.0 / progress_width_scaled, 1.0);
913 cairo_pattern_set_matrix(COLOR(cl, highlight->pattern), &matrix);
914 cairo_set_source(c, COLOR(cl, highlight->pattern));
921 cairo_set_source_rgba(c, COLOR(cl, frame.r), COLOR(cl, frame.g), COLOR(cl, frame.b), COLOR(cl, frame.a));
922 cairo_set_line_width(c, frame_width * scale);
924 frame_x + half_frame_width + 1,
926 progress_width - frame_width - 2,
928 settings.progress_bar_corner_radius,
929 scale,
settings.progress_bar_corners);
934static struct dimensions layout_render(cairo_surface_t *srf,
940 double scale = output->get_scale();
941 const int cl_h = layout_get_height(cl, scale);
944 int bg_height = MAX(settings.height.min, 2 * settings.padding + cl_h);
945 bg_height = MIN(settings.height.max, bg_height);
947 cairo_surface_t *content = render_background(srf, cl, cl_next, dim.y, dim.w, bg_height, dim.corner_radius, corners, &bg_width, scale);
948 cairo_t *c = cairo_create(content);
950 render_content(c, cl, bg_width, bg_height, scale);
953 if (corners & (C_TOP | _C_FIRST))
954 dim.y += settings.frame_width;
956 if (corners & (C_BOT | _C_LAST))
957 dim.y += settings.frame_width;
961 if (settings.gap_size)
962 dim.y += settings.gap_size;
964 dim.y += settings.separator_height;
967 cairo_surface_destroy(content);
982 case ORIGIN_TOP_LEFT:
983 case ORIGIN_LEFT_CENTER:
984 case ORIGIN_BOTTOM_LEFT:
987 case ORIGIN_TOP_RIGHT:
988 case ORIGIN_RIGHT_CENTER:
989 case ORIGIN_BOTTOM_RIGHT:
990 *ret_x = scr->x + (scr->w - width) - round(
settings.
offset.x * draw_get_scale());
992 case ORIGIN_TOP_CENTER:
994 case ORIGIN_BOTTOM_CENTER:
996 *ret_x = scr->x + (scr->w - width) / 2;
1002 case ORIGIN_TOP_LEFT:
1003 case ORIGIN_TOP_CENTER:
1004 case ORIGIN_TOP_RIGHT:
1007 case ORIGIN_BOTTOM_LEFT:
1008 case ORIGIN_BOTTOM_CENTER:
1009 case ORIGIN_BOTTOM_RIGHT:
1010 *ret_y = scr->y + (scr->h - height) - round(
settings.
offset.y * draw_get_scale());
1012 case ORIGIN_LEFT_CENTER:
1014 case ORIGIN_RIGHT_CENTER:
1016 *ret_y = scr->y + (scr->h - height) / 2;
1025 cairo_t *c =
output->win_get_context(win);
1031 GSList *layouts = create_layouts(c);
1033 struct dimensions dim = calculate_dimensions(layouts);
1034 LOG_D(
"Window dimensions %ix%i", dim.w, dim.h);
1035 double scale =
output->get_scale();
1037 cairo_surface_t *image_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1038 round(dim.w * scale),
1039 round(dim.h * scale));
1042 for (GSList *iter = layouts; iter; iter = iter->next) {
1045 struct colored_layout *cl_next = iter->next ? iter->next->data : NULL;
1050 corners |= (
settings.corners & C_BOT) | _C_LAST;
1052 dim = layout_render(image_surface, cl_this, cl_next, dim, corners);
1053 corners &= ~(C_TOP | _C_FIRST);
1056 output->display_surface(image_surface, win, &dim);
1058 cairo_surface_destroy(image_surface);
1059 g_slist_free_full(layouts, free_colored_layout);
1062void draw_deinit(
void)
1064 pango_font_description_free(pango_fdesc);
1065 output->win_destroy(win);
1067 if (
settings.enable_recursive_icon_lookup)
1071double draw_get_scale(
void)
1074 return output->get_scale();
1076 LOG_W(
"Called draw_get_scale before output init");
char * color_to_string(struct color c, char buf[10])
Stringify a color struct to a RRGGBBAA string.
void calc_window_pos(const struct screen_info *scr, int width, int height, int *ret_x, int *ret_y)
Calculates the position the window should be placed at given its width and height and stores them in ...
void draw_rounded_rect(cairo_t *c, float x, float y, int width, int height, int corner_radius, double scale, enum corner_pos corners)
Create a path on the given cairo context to draw the background of a notification.
static void draw_rect(cairo_t *c, double x, double y, double width, double height, double scale)
A small wrapper around cairo_rectange for drawing a scaled rectangle.
Layout and render notifications.
corner_pos
Specify which corner to draw in draw_rouned_rect.
int load_icon_theme(char *name)
Load a theme with given name from a standard icon directory.
void free_all_themes(void)
Free all icon themes.
void add_default_theme(int theme_index)
Add theme to the list of default themes.
Recursive icon lookup in theme directories.
int get_icon_width(cairo_surface_t *icon, double scale)
Get the unscaled icon width.
int get_icon_height(cairo_surface_t *icon, double scale)
Get the unscaled icon height, see get_icon_width.
Notification images loading.
Logging subsystem and helpers.
#define LOG_E
Prefix message with "[<source path>:<function name>:<line number>] ".
char * markup_strip(char *str)
Strip any markup from text; turn it in to plain text.
Markup handling for notifications body.
Notification type definitions.
const struct output * output_create(bool force_xwayland)
return an initialized output, selecting the correct output type from either wayland or X11 according ...
Generic graphics backend wrapper.
unsigned int queues_length_waiting(void)
Returns the current amount of notifications, which are waiting to get displayed.
GList * queues_get_displayed(void)
Receive the current list of displayed notifications.
unsigned int queues_length_displayed(void)
Returns the current amount of notifications, which are shown in the UI.
struct notification * queues_get_head_waiting(void)
Get the highest notification in line.
Queues for history, waiting and displayed notifications.
Type definitions for settings.
PangoAlignment progress_bar_alignment
Horizontal alignment of the progress bar.
enum icon_position icon_position
Icon position (enum left,right,top,off).
int progress
percentage (-1: undefined)
cairo_surface_t * icon
The raw cached icon data used to draw.
char * text_to_render
formatted message (with age and action indicators)
bool first_render
markup has been rendered before?
String, time and other various helpers.