From b72d021fa55a6f4775a24fea926fbe018249c5d5 Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Sat, 20 Apr 2024 16:22:10 +0200 Subject: [PATCH 01/10] Implement dynamic height and change vertical padding --- src/draw.c | 125 +++++++++++++++++++++----------------------- src/settings.c | 4 +- src/settings_data.h | 2 +- 3 files changed, 64 insertions(+), 67 deletions(-) diff --git a/src/draw.c b/src/draw.c index 58fc4119f..8fa514a0c 100644 --- a/src/draw.c +++ b/src/draw.c @@ -202,7 +202,7 @@ static void layout_setup(struct colored_layout *cl, int width, int height, doubl int icon_width = cl->icon ? get_icon_width(cl->icon, scale) + horizontal_padding : 0; int text_width = width - 2 * settings.h_padding - (cl->n->icon_position == ICON_TOP ? 0 : icon_width); int progress_bar_height = have_progress_bar(cl) ? settings.progress_bar_height + settings.padding : 0; - int max_text_height = MAX(0, settings.height.max - progress_bar_height - 2 * settings.padding); + int max_text_height = MAX(0, height - progress_bar_height - 2 * settings.padding); layout_setup_pango(cl->l, text_width, max_text_height, cl->n->word_wrap, cl->n->ellipsize, cl->n->alignment); } @@ -246,12 +246,14 @@ static struct dimensions calculate_notification_dimensions(struct colored_layout dim.w = dim.text_width + icon_width + 2 * settings.h_padding; dim.h = MIN(settings.height.max, dim.h + settings.padding * 2); + dim.h = MAX(settings.height.min, dim.h); + dim.w = MAX(settings.width.min, dim.w); + dim.w = MIN(settings.width.max, dim.w); + if (have_progress_bar(cl)) dim.w = MAX(settings.progress_bar_min_width, dim.w); - dim.w = MIN(settings.width.max, dim.w); - cl->n->displayed_height = dim.h; return dim; } @@ -426,11 +428,9 @@ static int layout_get_height(struct colored_layout *cl, double scale) } - if (cl->n->icon_position == ICON_TOP && cl->n->icon) { - return h_icon + h_text + h_progress_bar + vertical_padding; - } else { - return MAX(h_text, h_icon) + h_progress_bar; - } + return (cl->n->icon_position == ICON_TOP && cl->n->icon) + ? h_icon + h_text + h_progress_bar + vertical_padding + : MAX(h_text, h_icon) + h_progress_bar; } /* Attempt to make internal radius more organic. @@ -705,73 +705,64 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, round(width * scale), round(height * scale)); } -static void render_content(cairo_t *c, struct colored_layout *cl, int width, double scale) +static void render_content(cairo_t *c, struct colored_layout *cl, int width, int height, double scale) { // Redo layout setup, while knowing the width. This is to make // alignment work correctly - layout_setup(cl, width, settings.height.max, scale); + layout_setup(cl, width, height, scale); - const int h = layout_get_height(cl, scale); - LOG_D("Layout height %i", h); - int h_without_progress_bar = h; + // NOTE: Includes the last padding + int h_without_progress_bar = height; if (have_progress_bar(cl)) { - h_without_progress_bar -= settings.progress_bar_height + settings.padding; + h_without_progress_bar -= settings.progress_bar_height + settings.padding; } - if (!cl->n->hide_text) { - int h_text = 0; - get_text_size(cl->l, NULL, &h_text, scale); + int text_h = 0; + if (!cl->n->hide_text) + get_text_size(cl->l, NULL, &text_h, scale); - int text_x = settings.h_padding, - text_y = settings.padding + h_without_progress_bar / 2 - h_text / 2; - - // text positioning - if (cl->icon) { - // vertical alignment - if (settings.vertical_alignment == VERTICAL_TOP) { - text_y = settings.padding; - } else if (settings.vertical_alignment == VERTICAL_BOTTOM) { - text_y = h_without_progress_bar + settings.padding - h_text; - if (text_y < 0) - text_y = settings.padding; - } // else VERTICAL_CENTER - - // icon position - if (cl->n->icon_position == ICON_LEFT) { - text_x = get_icon_width(cl->icon, scale) + settings.h_padding + get_horizontal_text_icon_padding(cl->n); - } else if (cl->n->icon_position == ICON_TOP) { - text_y = get_icon_height(cl->icon, scale) + settings.padding + get_vertical_text_icon_padding(cl->n); - } // else ICON_RIGHT - } - cairo_move_to(c, round(text_x * scale), round(text_y * scale)); + // text vertical alignment + int text_x = settings.h_padding, + text_y = settings.padding; - cairo_set_source_rgba(c, COLOR(cl, fg.r), COLOR(cl, fg.g), COLOR(cl, fg.b), COLOR(cl, fg.a)); - pango_cairo_update_layout(c, cl->l); - pango_cairo_show_layout(c, cl->l); - } + if (settings.vertical_alignment == VERTICAL_CENTER) { + text_y = h_without_progress_bar / 2 - text_h / 2; + } else if (settings.vertical_alignment == VERTICAL_BOTTOM) { + text_y = h_without_progress_bar - settings.padding - text_h; + } // else VERTICAL_TOP // icon positioning if (cl->icon) { - unsigned int image_width = get_icon_width(cl->icon, scale), - image_height = get_icon_height(cl->icon, scale), - image_x = width - settings.h_padding - image_width, - image_y = settings.padding + h_without_progress_bar/2 - image_height/2; + int image_width = get_icon_width(cl->icon, scale), + image_height = get_icon_height(cl->icon, scale), + image_x = width - settings.h_padding - image_width, + image_y = text_y, + v_padding = get_vertical_text_icon_padding(cl->n); // vertical alignment - if (settings.vertical_alignment == VERTICAL_TOP) { - image_y = settings.padding; - } else if (settings.vertical_alignment == VERTICAL_BOTTOM) { - image_y = h_without_progress_bar + settings.padding - image_height; - if (image_y < settings.padding || image_y > h_without_progress_bar) - image_y = settings.padding; - } // else VERTICAL_CENTER + if (cl->n->hide_text || cl->n->icon_position == ICON_TOP) { + switch (settings.vertical_alignment) { + case VERTICAL_TOP: + text_y += image_height + v_padding; + break; + case VERTICAL_CENTER: + image_y -= (image_height + v_padding) / 2; + text_y += (image_height + v_padding) / 2; + break; + case VERTICAL_BOTTOM: + image_y -= image_height + v_padding; + if (image_y < settings.padding || image_y > h_without_progress_bar) + image_y = settings.padding; + break; + } + } // icon position - if (cl->n->icon_position == ICON_LEFT) { + if (cl->n->icon_position == ICON_TOP) { + image_x = (width - image_width) / 2; + } else if (cl->n->icon_position == ICON_LEFT) { image_x = settings.h_padding; - } else if (cl->n->icon_position == ICON_TOP) { - image_y = settings.padding; - image_x = width/2 - image_width/2; + text_x += image_width + get_horizontal_text_icon_padding(cl->n); } // else ICON_RIGHT cairo_set_source_surface(c, cl->icon, round(image_x * scale), round(image_y * scale)); @@ -779,6 +770,14 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, dou cairo_fill(c); } + // text positioning + if (!cl->n->hide_text) { + cairo_move_to(c, round(text_x * scale), round(text_y * scale)); + cairo_set_source_rgba(c, COLOR(cl, fg.r), COLOR(cl, fg.g), COLOR(cl, fg.b), COLOR(cl, fg.a)); + pango_cairo_update_layout(c, cl->l); + pango_cairo_show_layout(c, cl->l); + } + // progress bar positioning if (have_progress_bar(cl)) { int progress = MIN(cl->n->progress, 100); @@ -786,7 +785,7 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, dou unsigned int frame_width = settings.progress_bar_frame_width, progress_width = MIN(width - 2 * settings.h_padding, settings.progress_bar_max_width), progress_height = settings.progress_bar_height - frame_width, - frame_y = settings.padding + h - settings.progress_bar_height, + frame_y = h_without_progress_bar, progress_width_without_frame = progress_width - 2 * frame_width, progress_width_1 = progress_width_without_frame * progress / 100, progress_width_2 = progress_width_without_frame - 1; @@ -853,11 +852,12 @@ static struct dimensions layout_render(cairo_surface_t *srf, int bg_width = 0; int bg_height = MIN(settings.height.max, (2 * settings.padding) + cl_h); + bg_height = MAX(settings.height.min, bg_height); cairo_surface_t *content = render_background(srf, cl, cl_next, dim.y, dim.w, bg_height, dim.corner_radius, corners, &bg_width, scale); cairo_t *c = cairo_create(content); - render_content(c, cl, bg_width, scale); + render_content(c, cl, bg_width, bg_height, scale); /* adding frame */ if (corners & (C_TOP | _C_FIRST)) @@ -866,10 +866,7 @@ static struct dimensions layout_render(cairo_surface_t *srf, if (corners & (C_BOT | _C_LAST)) dim.y += settings.frame_width; - if ((2 * settings.padding + cl_h) < settings.height.max) - dim.y += cl_h + 2 * settings.padding; - else - dim.y += settings.height.max; + dim.y += bg_height; if (settings.gap_size) dim.y += settings.gap_size; diff --git a/src/settings.c b/src/settings.c index 94367316c..7e2eccdb2 100644 --- a/src/settings.c +++ b/src/settings.c @@ -226,8 +226,8 @@ void check_and_correct_settings(struct settings *s) { if (s->height.min < 0 || s->height.max < 0) { DIE("setting height does not support negative values"); } - if (s->height.min != s->height.max) { - LOG_W("Dynamic height is not yet supported"); + if (s->height.min > s->height.max) { + DIE("setting height min (%i) is always greather than max (%i)", s->height.min, s->height.max); } if (s->offset.x == INT_MIN || s->offset.y == INT_MAX) { diff --git a/src/settings_data.h b/src/settings_data.h index 06c4fe1f3..0e19586f5 100644 --- a/src/settings_data.h +++ b/src/settings_data.h @@ -1528,7 +1528,7 @@ static const struct setting allowed_settings[] = { { .name = "height", .section = "global", - .description = "The maximum height of a single notification, excluding the frame.", + .description = "The height of a single notification, excluding the frame.", .type = TYPE_LENGTH, .default_value = "300", .value = &settings.height, From 7b42087e417d025204db7e1a9a8d0cd1fd5b3695 Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Sat, 20 Apr 2024 16:30:52 +0200 Subject: [PATCH 02/10] Add documentation for height --- docs/dunst.5.pod | 12 ++++++++++-- dunstrc | 4 ++-- src/settings_data.h | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/dunst.5.pod b/docs/dunst.5.pod index 13ee9ab93..751b2dbf9 100644 --- a/docs/dunst.5.pod +++ b/docs/dunst.5.pod @@ -106,7 +106,15 @@ screens exceed (e.g. 10000). =item B -The maximum height of a single notification. +The height of each notification in pixels. This can be a single number to +specify a constant height or two numbers for the minimum and maximum width. The +notification will expand from the minimum height as neccesary. + +Examples: + height = 300 # constant height of 300 + height = (0, 300) # height between 0 and 300 + +Note that unlike width, different notifications can have diffrent height values. =item B (default: 20) @@ -416,7 +424,7 @@ removed from the format. =item B (values: [top/center/bottom], default: center) Defines how the text and icon should be aligned vertically within the -notification. If icons are disabled, this option has no effect. +notification. =item B (default: 60) diff --git a/dunstrc b/dunstrc index 2c756993e..fe39dd95b 100644 --- a/dunstrc +++ b/dunstrc @@ -26,8 +26,8 @@ # constant width of 300 width = 300 - # The maximum height of a single notification, excluding the frame. - height = 300 + # The height of a single notification, excluding the frame. + height = (0, 300) # Position the notification in the top right corner origin = top-right diff --git a/src/settings_data.h b/src/settings_data.h index 0e19586f5..93fd092e9 100644 --- a/src/settings_data.h +++ b/src/settings_data.h @@ -1528,9 +1528,9 @@ static const struct setting allowed_settings[] = { { .name = "height", .section = "global", - .description = "The height of a single notification, excluding the frame.", + .description = "The height of a notification, excluding the frame.", .type = TYPE_LENGTH, - .default_value = "300", + .default_value = "(0, 300)", .value = &settings.height, .parser = NULL, .parser_data = NULL, From c87a7b6d2bd133bd81c8babe60df96bc8233e6be Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Sat, 20 Apr 2024 19:19:29 +0200 Subject: [PATCH 03/10] Add dynamic_height and vertical_align functional tests --- src/settings.c | 3 + test/functional-tests/test.sh | 220 ++++++++++++++++++++++++---------- 2 files changed, 159 insertions(+), 64 deletions(-) diff --git a/src/settings.c b/src/settings.c index 7e2eccdb2..0c00565fa 100644 --- a/src/settings.c +++ b/src/settings.c @@ -223,6 +223,9 @@ void check_and_correct_settings(struct settings *s) { DIE("setting width min (%i) is always greather than max (%i)", s->width.min, s->width.max); } + if (s->height.min == INT_MIN) { + s->height.min = 0; + } if (s->height.min < 0 || s->height.max < 0) { DIE("setting height does not support negative values"); } diff --git a/test/functional-tests/test.sh b/test/functional-tests/test.sh index 89246aead..8ecd20fc7 100755 --- a/test/functional-tests/test.sh +++ b/test/functional-tests/test.sh @@ -1,5 +1,8 @@ #!/bin/bash +DUNST="${DUNST:-../../dunst}" +DUNSTIFY="${DUNSTIFY:-../../dunstify}" + function keypress { echo "press enter to continue..." read key @@ -11,19 +14,19 @@ function tmp_dunstrc { } function start_dunst { - killall dunst - ../../dunst -config $1 & - sleep 0.1 + killall dunst 2>/dev/null + $DUNST -config $1 & + sleep 0.05 } function basic_notifications { - ../../dunstify -a "dunst tester" "normal" "italic body" - ../../dunstify -a "dunst tester" -u c "critical" "bold body" - ../../dunstify -a "dunst tester" "long body" "This is a notification with a very long body" - ../../dunstify -a "dunst tester" "duplucate" - ../../dunstify -a "dunst tester" "duplucate" - ../../dunstify -a "dunst tester" "duplucate" - ../../dunstify -a "dunst tester" "url" "www.google.de" + $DUNSTIFY -a "dunst tester" "normal" "italic body" + $DUNSTIFY -a "dunst tester" -u c "critical" "bold body" + $DUNSTIFY -a "dunst tester" "long body" "This is a notification with a very long body" + $DUNSTIFY -a "dunst tester" "duplucate" + $DUNSTIFY -a "dunst tester" "duplucate" + $DUNSTIFY -a "dunst tester" "duplucate" + $DUNSTIFY -a "dunst tester" "url" "www.google.de" } @@ -32,8 +35,8 @@ function show_age { echo "show age" echo "###################################" killall dunst - ../../dunst -config dunstrc.show_age & - ../../dunstify -a "dunst tester" -u c "Show Age" "These should print their age after 2 seconds" + $DUNST -config dunstrc.show_age & + $DUNSTIFY -a "dunst tester" -u c "Show Age" "These should print their age after 2 seconds" basic_notifications keypress } @@ -43,11 +46,11 @@ function run_script { echo "run script" echo "###################################" killall dunst - PATH=".:$PATH" ../../dunst -config dunstrc.run_script & - ../../dunstify -a "dunst tester" -u c \ + PATH=".:$PATH" $DUNST -config dunstrc.run_script & + $DUNSTIFY -a "dunst tester" -u c \ "Run Script" "After Keypress, 2 other notification should pop up." keypress - ../../dunstify -a "dunst tester" -u c "trigger" "this should trigger a notification" + $DUNSTIFY -a "dunst tester" -u c "trigger" "this should trigger a notification" keypress } @@ -56,10 +59,10 @@ function replace { echo "replace" echo "###################################" killall dunst - ../../dunst -config dunstrc.default & - id=$(../../dunstify -a "dunst tester" -p "Replace" "this should get replaces after keypress") + $DUNST -config dunstrc.default & + id=$($DUNSTIFY -a "dunst tester" -p "Replace" "this should get replaces after keypress") keypress - ../../dunstify -a "dunst tester" -r $id "Success?" "I hope this is not a new notification" + $DUNSTIFY -a "dunst tester" -r $id "Success?" "I hope this is not a new notification" keypress } @@ -70,14 +73,14 @@ function limit { echo "###################################" tmp_dunstrc dunstrc.default "notification_limit=4" start_dunst dunstrc.tmp - ../../dunstify -a "dunst tester" -u c "notification limit = 4" + $DUNSTIFY -a "dunst tester" -u c "notification limit = 4" basic_notifications rm dunstrc.tmp keypress tmp_dunstrc dunstrc.default "notification_limit=0" start_dunst dunstrc.tmp - ../../dunstify -a "dunst tester" -u c "notification limit = 0 (unlimited notifications)" + $DUNSTIFY -a "dunst tester" -u c "notification limit = 0 (unlimited notifications)" basic_notifications rm dunstrc.tmp keypress @@ -88,18 +91,18 @@ function markup { echo "markup" echo "###################################" killall dunst - ../../dunst -config dunstrc.default & - ../../dunstify -a "dunst tester" "Markup Tests" -u "c" - ../../dunstify -a "dunst tester" "Title" "bold italic" - ../../dunstify -a "dunst tester" "Title" ' Github link ' - ../../dunstify -a "dunst tester" "Title" "broken markup" + $DUNST -config dunstrc.default & + $DUNSTIFY -a "dunst tester" "Markup Tests" -u "c" + $DUNSTIFY -a "dunst tester" "Title" "bold italic" + $DUNSTIFY -a "dunst tester" "Title" ' Github link ' + $DUNSTIFY -a "dunst tester" "Title" "broken markup" keypress killall dunst - ../../dunst -config dunstrc.nomarkup & - ../../dunstify -a "dunst tester" -u c "No markup Tests" "Titles shoud still be in bold and body in italics" - ../../dunstify -a "dunst tester" "Title" "bolditalic" - ../../dunstify -a "dunst tester" "Title" "broken markup" + $DUNST -config dunstrc.nomarkup & + $DUNSTIFY -a "dunst tester" -u c "No markup Tests" "Titles shoud still be in bold and body in italics" + $DUNSTIFY -a "dunst tester" "Title" "bolditalic" + $DUNSTIFY -a "dunst tester" "Title" "broken markup" keypress } @@ -107,7 +110,7 @@ function markup { function test_origin { tmp_dunstrc dunstrc.default "origin = $1\n offset = 10x10" start_dunst dunstrc.tmp - ../../dunstify -a "dunst tester" -u c "$1" + $DUNSTIFY -a "dunst tester" -u c "$1" basic_notifications rm dunstrc.tmp keypress @@ -131,7 +134,7 @@ function origin { function test_width { tmp_dunstrc dunstrc.default "width = $1" start_dunst dunstrc.tmp - ../../dunstify -a "dunst tester" -u c "width = $1" + $DUNSTIFY -a "dunst tester" -u c "width = $1" basic_notifications rm dunstrc.tmp keypress @@ -150,8 +153,8 @@ function width { function test_height { tmp_dunstrc dunstrc.default "height = $1" start_dunst dunstrc.tmp - ../../dunstify -a "dunst tester" -u c "height = $1" - ../../dunstify -a "dunst tester" -u c "Temporibus accusantium libero sequi at nostrum dolor sequi sed. Cum minus reprehenderit voluptatibus laboriosam et et ut. Laudantium blanditiis omnis ipsa rerum quas velit ut. Quae voluptate soluta enim consequatur libero eum similique ad. Veritatis neque consequatur et aperiam quisquam id nostrum. Consequatur voluptas aut ut omnis atque cum perferendis. Possimus laudantium tempore iste qui nemo voluptate quod. Labore totam debitis consectetur amet. Maxime quibusdam ipsum voluptates quod ex nam sunt. Officiis repellat quod maxime cumque tenetur. Veritatis labore aperiam repellendus. Provident dignissimos ducimus voluptates." + $DUNSTIFY -a "dunst tester" -u c "height = $1" + $DUNSTIFY -a "dunst tester" -u c "Temporibus accusantium libero sequi at nostrum dolor sequi sed. Cum minus reprehenderit voluptatibus laboriosam et et ut. Laudantium blanditiis omnis ipsa rerum quas velit ut. Quae voluptate soluta enim consequatur libero eum similique ad. Veritatis neque consequatur et aperiam quisquam id nostrum. Consequatur voluptas aut ut omnis atque cum perferendis. Possimus laudantium tempore iste qui nemo voluptate quod. Labore totam debitis consectetur amet. Maxime quibusdam ipsum voluptates quod ex nam sunt. Officiis repellat quod maxime cumque tenetur. Veritatis labore aperiam repellendus. Provident dignissimos ducimus voluptates." basic_notifications rm dunstrc.tmp keypress @@ -160,9 +163,9 @@ function test_height { function test_progress_bar_alignment { tmp_dunstrc dunstrc.default "progress_bar_horizontal_alignment = $1\n progress_bar_max_width = 200" start_dunst dunstrc.tmp - ../../dunstify -a "dunst tester" -u c "alignment = $1" - ../../dunstify -h int:value:33 -a "dunst tester" -u n "The progress bar should not be the entire width" - ../../dunstify -h int:value:33 -a "dunst tester" -u c "Short" + $DUNSTIFY -a "dunst tester" -u c "alignment = $1" + $DUNSTIFY -h int:value:33 -a "dunst tester" -u n "The progress bar should not be the entire width" + $DUNSTIFY -h int:value:33 -a "dunst tester" -u c "Short" rm dunstrc.tmp keypress } @@ -177,24 +180,27 @@ function height { } function progress_bar { + echo "###################################" + echo "progress_bar" + echo "###################################" killall dunst - ../../dunst -config dunstrc.default & - ../../dunstify -h int:value:0 -a "dunst tester" -u c "Progress bar 0%: " - ../../dunstify -h int:value:33 -a "dunst tester" -u c "Progress bar 33%: " - ../../dunstify -h int:value:66 -a "dunst tester" -u c "Progress bar 66%: " - ../../dunstify -h int:value:100 -a "dunst tester" -u c "Progress bar 100%: " + $DUNST -config dunstrc.default & + $DUNSTIFY -h int:value:0 -a "dunst tester" -u c "Progress bar 0%: " + $DUNSTIFY -h int:value:33 -a "dunst tester" -u c "Progress bar 33%: " + $DUNSTIFY -h int:value:66 -a "dunst tester" -u c "Progress bar 66%: " + $DUNSTIFY -h int:value:100 -a "dunst tester" -u c "Progress bar 100%: " keypress killall dunst - ../../dunst -config dunstrc.default & - ../../dunstify -h int:value:33 -a "dunst tester" -u l "Low priority: " - ../../dunstify -h int:value:33 -a "dunst tester" -u n "Normal priority: " - ../../dunstify -h int:value:33 -a "dunst tester" -u c "Critical priority: " + $DUNST -config dunstrc.default & + $DUNSTIFY -h int:value:33 -a "dunst tester" -u l "Low priority: " + $DUNSTIFY -h int:value:33 -a "dunst tester" -u n "Normal priority: " + $DUNSTIFY -h int:value:33 -a "dunst tester" -u c "Critical priority: " keypress killall dunst - ../../dunst -config dunstrc.progress_bar & - ../../dunstify -h int:value:33 -a "dunst tester" -u n "The progress bar should not be the entire width" - ../../dunstify -h int:value:33 -a "dunst tester" -u n "You might also notice height and frame size are changed" - ../../dunstify -h int:value:33 -a "dunst tester" -u c "Short" + $DUNST -config dunstrc.progress_bar & + $DUNSTIFY -h int:value:33 -a "dunst tester" -u n "The progress bar should not be the entire width" + $DUNSTIFY -h int:value:33 -a "dunst tester" -u n "You might also notice height and frame size are changed" + $DUNSTIFY -h int:value:33 -a "dunst tester" -u c "Short" keypress test_progress_bar_alignment "left" test_progress_bar_alignment "center" @@ -202,6 +208,9 @@ function progress_bar { } function icon_position { + echo "###################################" + echo "icon_position" + echo "###################################" padding_cases=( '0 0 0 no padding' '15 1 1 vertical' @@ -224,7 +233,7 @@ function icon_position { for position in left top right off; do for alignment in left center right; do category="icon-$position-alignment-$alignment" - ../../dunstify -a "dunst tester" --hints string:category:$category -u n "$category"$'\n'"padding emphasis: $label" + $DUNSTIFY -a "dunst tester" --hints string:category:$category -u n "$category"$'\n'"padding emphasis: $label" done done rm dunstrc.tmp @@ -233,13 +242,16 @@ function icon_position { } function hide_text { + echo "###################################" + echo "hide_text" + echo "###################################" start_dunst dunstrc.hide_text - ../../dunstify -a "dunst tester" -u c "text not hidden" "You should be able to read me!\nThe next notifications should not have any text." + $DUNSTIFY -a "dunst tester" -u c "text not hidden" "You should be able to read me!\nThe next notifications should not have any text." local hidden_body="If you can read me then hide_text is not working." - ../../dunstify -a "dunst tester" -u l "text hidden" "$hidden_body" - ../../dunstify -a "dunst tester" -h int:value:$((RANDOM%100)) -u l "text hidden + progress bar" "$hidden_body" - ../../dunstify -a "dunst tester" -u n "text hidden + icon" "$hidden_body" - ../../dunstify -a "dunst tester" -h int:value:$((RANDOM%100)) -u n "text hidden + icon + progress bar" "$hidden_body" + $DUNSTIFY -a "dunst tester" -u l "text hidden" "$hidden_body" + $DUNSTIFY -a "dunst tester" -h int:value:$((RANDOM%100)) -u l "text hidden + progress bar" "$hidden_body" + $DUNSTIFY -a "dunst tester" -u n "text hidden + icon" "$hidden_body" + $DUNSTIFY -a "dunst tester" -h int:value:$((RANDOM%100)) -u n "text hidden + icon + progress bar" "$hidden_body" keypress } @@ -248,17 +260,17 @@ function gaps { echo "gaps" echo "###################################" start_dunst dunstrc.gaps - CHOICE=$(../../dunstify -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #1" -u l) \ + CHOICE=$($DUNSTIFY -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #1" -u l) \ && echo Clicked $CHOICE for \#1 & - CHOICE=$(../../dunstify -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #2" -u n) \ + CHOICE=$($DUNSTIFY -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #2" -u n) \ && echo Clicked $CHOICE for \#2 & - CHOICE=$(../../dunstify -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #3" -u c) \ + CHOICE=$($DUNSTIFY -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #3" -u c) \ && echo Clicked $CHOICE for \#3 & - CHOICE=$(../../dunstify -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #4" -u l) \ + CHOICE=$($DUNSTIFY -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #4" -u l) \ && echo Clicked $CHOICE for \#4 & - CHOICE=$(../../dunstify -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #5" -u n) \ + CHOICE=$($DUNSTIFY -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #5" -u n) \ && echo Clicked $CHOICE for \#5 & - CHOICE=$(../../dunstify -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #6" -u c) \ + CHOICE=$($DUNSTIFY -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #6" -u c) \ && echo Clicked $CHOICE for \#6 & keypress } @@ -268,15 +280,93 @@ function separator_click { echo "separator_click" echo "###################################" start_dunst dunstrc.separator_click - CHOICE=$(../../dunstify -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #1" -u l) \ + CHOICE=$($DUNSTIFY -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #1" -u l) \ && echo Clicked $CHOICE for \#1 & - CHOICE=$(../../dunstify -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #2" -u c) \ + CHOICE=$($DUNSTIFY -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #2" -u c) \ && echo Clicked $CHOICE for \#2 & - CHOICE=$(../../dunstify -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #3" -u n) \ + CHOICE=$($DUNSTIFY -a "dunst tester" -A "default,Default" -A "optional,Optional" "Click #3" -u n) \ && echo Clicked $CHOICE for \#3 & keypress } +function dynamic_height { + echo "###################################" + echo "dynamic_height" + echo "###################################" + + for max in 50 100 200 ""; do + for min in 50 100 200 ""; do + [[ $min -gt $max ]] && continue + + tmp_dunstrc dunstrc.dynamic_height "height = ($min, $max)" + start_dunst dunstrc.tmp + + $DUNSTIFY -a "dunst tester" -u l "text" "height min = $min"$'\n'"height max = $max" + $DUNSTIFY -a "dunst tester" -h int:value:$((RANDOM%100)) -u l "text+ progress bar" "height min = $min"$'\n'"height max = $max" + $DUNSTIFY -a "dunst tester" -u n "text + icon" "height min = $min"$'\n'"height max = $max" + $DUNSTIFY -a "dunst tester" -h int:value:$((RANDOM%100)) -u n "text + icon + progress bar" "height min = $min"$'\n'"height max = $max" + + $DUNSTIFY -a "dunst tester" -h string:category:hide_text -u l "text hidden" "SHOULD BE NOT VISIBLE" + $DUNSTIFY -a "dunst tester" -h string:category:hide_text -h int:value:$((RANDOM%100)) -u l "text hidden + progress bar" "SHOULD BE NOT VISIBLE" + $DUNSTIFY -a "dunst tester" -h string:category:hide_text -u n "text hidden + icon" "SHOULD BE NOT VISIBLE" + $DUNSTIFY -a "dunst tester" -h string:category:hide_text -h int:value:$((RANDOM%100)) -u n "text hidden + icon + progress bar" "SHOULD BE NOT VISIBLE" + + rm dunstrc.tmp + keypress + done + done +} + +function vertical_align { + echo "###################################" + echo "vertical_align" + echo "###################################" + + padding_cases=( + '0 0 0 0 none' + '15 1 1 50 less' + '1 50 1 100 slight' + '1 1 25 200 more' + ) + + for valign in top center bottom; do + for padding_case in "${padding_cases[@]}"; do + read vertical horizontal icon height label <<<"$padding_case" + + padding_settings=" + padding = $vertical + horizontal_padding = $horizontal + text_icon_padding = $icon + vertical_alignment = $valign + height = ($height, ) + " + + tmp_dunstrc dunstrc.vertical_align "$padding_settings" + start_dunst dunstrc.tmp + + for position in left top right off; do + for alignment in left center right; do + category="icon-$position-alignment-$alignment" + $DUNSTIFY -a "dunst tester" --hints string:category:$category -u n "$category"$'\n'"emphasis: $label"$'\n'"vertical alignment: $valign" + done + done + + keypress + start_dunst dunstrc.tmp + + for position in left top right; do + for alignment in left center right; do + category="icon-$position-alignment-$alignment-hide" + $DUNSTIFY -a "dunst tester" --hints string:category:$category -u n "$category"$'\n'"emphasis: $label"$'\n'"vertical alignment: $valign" + done + done + + rm dunstrc.tmp + keypress + done + done +} + if [ -n "$1" ]; then while [ -n "$1" ]; do $1 @@ -297,6 +387,8 @@ else hide_text gaps separator_click + dynamic_height + vertical_align fi killall dunst From 4bcf603800a41222821fb5d4c2a84301a2f1fb8a Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:19:49 +0200 Subject: [PATCH 04/10] Fix vertical alignment --- src/draw.c | 36 +++++++++++++++++++++-------------- test/functional-tests/test.sh | 6 +++--- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/draw.c b/src/draw.c index 8fa514a0c..d74b637c4 100644 --- a/src/draw.c +++ b/src/draw.c @@ -718,21 +718,22 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int } int text_h = 0; - if (!cl->n->hide_text) + if (!cl->n->hide_text) { get_text_size(cl->l, NULL, &text_h, scale); + } // text vertical alignment int text_x = settings.h_padding, text_y = settings.padding; if (settings.vertical_alignment == VERTICAL_CENTER) { - text_y = h_without_progress_bar / 2 - text_h / 2; + text_y += h_without_progress_bar / 2 - text_h / 2; } else if (settings.vertical_alignment == VERTICAL_BOTTOM) { text_y = h_without_progress_bar - settings.padding - text_h; } // else VERTICAL_TOP // icon positioning - if (cl->icon) { + if (cl->icon && cl->n->icon_position != ICON_OFF) { int image_width = get_icon_width(cl->icon, scale), image_height = get_icon_height(cl->icon, scale), image_x = width - settings.h_padding - image_width, @@ -740,21 +741,28 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int v_padding = get_vertical_text_icon_padding(cl->n); // vertical alignment - if (cl->n->hide_text || cl->n->icon_position == ICON_TOP) { - switch (settings.vertical_alignment) { - case VERTICAL_TOP: + switch (settings.vertical_alignment) { + case VERTICAL_TOP: + if (cl->n->hide_text || cl->n->icon_position == ICON_TOP) { text_y += image_height + v_padding; - break; - case VERTICAL_CENTER: + } + break; + case VERTICAL_CENTER: + if (cl->n->hide_text || cl->n->icon_position == ICON_TOP) { + // Shift text downward image_y -= (image_height + v_padding) / 2; text_y += (image_height + v_padding) / 2; - break; - case VERTICAL_BOTTOM: + } else { + image_y += text_h / 2 - image_height / 2; + } + break; + case VERTICAL_BOTTOM: + if (cl->n->hide_text || cl->n->icon_position == ICON_TOP) { image_y -= image_height + v_padding; - if (image_y < settings.padding || image_y > h_without_progress_bar) - image_y = settings.padding; - break; - } + } else { + image_y -= image_height - text_h; + } + break; } // icon position diff --git a/test/functional-tests/test.sh b/test/functional-tests/test.sh index 8ecd20fc7..8a4470ef5 100755 --- a/test/functional-tests/test.sh +++ b/test/functional-tests/test.sh @@ -324,9 +324,9 @@ function vertical_align { padding_cases=( '0 0 0 0 none' - '15 1 1 50 less' - '1 50 1 100 slight' - '1 1 25 200 more' + '1 1 1 50 less' + '1 1 1 100 slight' + '1 1 1 200 more' ) for valign in top center bottom; do From 44af81c07dbd60142affe256b6e0ed2800f83030 Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:33:42 +0200 Subject: [PATCH 05/10] Add more tests --- test/draw.c | 67 ++++++++++++++++++--- test/functional-tests/dunstrc.default | 3 +- test/functional-tests/dunstrc.hide_text | 2 +- test/functional-tests/dunstrc.icon_position | 2 +- test/functional-tests/dunstrc.nowrap | 2 - test/functional-tests/dunstrc.show_age | 2 - test/functional-tests/test.sh | 6 +- 7 files changed, 65 insertions(+), 19 deletions(-) diff --git a/test/draw.c b/test/draw.c index 1a6527abd..df31ccc9a 100644 --- a/test/draw.c +++ b/test/draw.c @@ -81,12 +81,12 @@ struct length get_small_max_height(void) return height; } -int get_expected_dimension_height(int layout_count) +int get_expected_dimension_height(int layout_count, int height) { - // assumes settings.height == notification height, see get_small_max_height + // assumes height == notification height, see get_small_max_height int separator_height = (layout_count - 1) * settings.separator_height; int total_gap_size = (layout_count - 1) * settings.gap_size; - int height = settings.height.max * layout_count; + height *= layout_count; int frame_width_total_height; int expected_height; if(settings.gap_size) { @@ -170,7 +170,7 @@ TEST test_calculate_dimensions_height_no_gaps(void) notifications = get_dummy_notifications(layout_count); layouts = get_dummy_layouts(notifications); dim = calculate_dimensions(layouts); - expected_height = get_expected_dimension_height(layout_count); + expected_height = get_expected_dimension_height(layout_count, settings.height.max); ASSERT(dim.h == expected_height); g_slist_free_full(layouts, free_colored_layout); g_slist_free_full(notifications, free_dummy_notification); @@ -179,7 +179,7 @@ TEST test_calculate_dimensions_height_no_gaps(void) notifications = get_dummy_notifications(layout_count); layouts = get_dummy_layouts(notifications); dim = calculate_dimensions(layouts); - expected_height = get_expected_dimension_height(layout_count); + expected_height = get_expected_dimension_height(layout_count, settings.height.max); ASSERT(dim.h == expected_height); g_slist_free_full(layouts, free_colored_layout); g_slist_free_full(notifications, free_dummy_notification); @@ -188,7 +188,7 @@ TEST test_calculate_dimensions_height_no_gaps(void) notifications = get_dummy_notifications(layout_count); layouts = get_dummy_layouts(notifications); dim = calculate_dimensions(layouts); - expected_height = get_expected_dimension_height(layout_count); + expected_height = get_expected_dimension_height(layout_count, settings.height.max); ASSERT(dim.h == expected_height); g_slist_free_full(layouts, free_colored_layout); g_slist_free_full(notifications, free_dummy_notification); @@ -216,7 +216,7 @@ TEST test_calculate_dimensions_height_gaps(void) notifications = get_dummy_notifications(layout_count); layouts = get_dummy_layouts(notifications); dim = calculate_dimensions(layouts); - expected_height = get_expected_dimension_height(layout_count); + expected_height = get_expected_dimension_height(layout_count, settings.height.max); ASSERT(dim.h == expected_height); g_slist_free_full(layouts, free_colored_layout); g_slist_free_full(notifications, free_dummy_notification); @@ -225,7 +225,7 @@ TEST test_calculate_dimensions_height_gaps(void) notifications = get_dummy_notifications(layout_count); layouts = get_dummy_layouts(notifications); dim = calculate_dimensions(layouts); - expected_height = get_expected_dimension_height(layout_count); + expected_height = get_expected_dimension_height(layout_count, settings.height.max); ASSERT(dim.h == expected_height); g_slist_free_full(layouts, free_colored_layout); g_slist_free_full(notifications, free_dummy_notification); @@ -234,7 +234,7 @@ TEST test_calculate_dimensions_height_gaps(void) notifications = get_dummy_notifications(layout_count); layouts = get_dummy_layouts(notifications); dim = calculate_dimensions(layouts); - expected_height = get_expected_dimension_height(layout_count); + expected_height = get_expected_dimension_height(layout_count, settings.height.max); ASSERT(dim.h == expected_height); g_slist_free_full(layouts, free_colored_layout); @@ -289,6 +289,54 @@ TEST test_layout_render_no_gaps(void) PASS(); } +TEST test_calculate_dimensions_height_min(void) +{ + struct length original_height = settings.height; + bool orginal_gap_size = settings.gap_size; + // NOTE: Should be big enough to fit the notification nicely + settings.height.min = 100; + settings.height.max = 200; + settings.gap_size = 0; + + int layout_count; + GSList *notifications; + GSList *layouts; + struct dimensions dim; + int expected_height; + + layout_count = 1; + notifications = get_dummy_notifications(layout_count); + layouts = get_dummy_layouts(notifications); + dim = calculate_dimensions(layouts); + expected_height = get_expected_dimension_height(layout_count, settings.height.min); + ASSERT(dim.h == expected_height); + g_slist_free_full(layouts, free_colored_layout); + g_slist_free_full(notifications, free_dummy_notification); + + layout_count = 2; + notifications = get_dummy_notifications(layout_count); + layouts = get_dummy_layouts(notifications); + dim = calculate_dimensions(layouts); + expected_height = get_expected_dimension_height(layout_count, settings.height.min); + ASSERT(dim.h == expected_height); + g_slist_free_full(layouts, free_colored_layout); + g_slist_free_full(notifications, free_dummy_notification); + + layout_count = 3; + notifications = get_dummy_notifications(layout_count); + layouts = get_dummy_layouts(notifications); + dim = calculate_dimensions(layouts); + expected_height = get_expected_dimension_height(layout_count, settings.height.min); + ASSERT(dim.h == expected_height); + + g_slist_free_full(layouts, free_colored_layout); + g_slist_free_full(notifications, free_dummy_notification); + settings.gap_size = orginal_gap_size; + settings.height = original_height; + + PASS(); +} + TEST test_layout_render_gaps(void) { struct length original_height = settings.height; @@ -340,6 +388,7 @@ SUITE(suite_draw) RUN_TEST(test_layout_from_notification_no_icon); RUN_TEST(test_calculate_dimensions_height_no_gaps); RUN_TEST(test_calculate_dimensions_height_gaps); + RUN_TEST(test_calculate_dimensions_height_min); RUN_TEST(test_layout_render_no_gaps); RUN_TEST(test_layout_render_gaps); }); diff --git a/test/functional-tests/dunstrc.default b/test/functional-tests/dunstrc.default index d26f38e8c..fac2ad908 100644 --- a/test/functional-tests/dunstrc.default +++ b/test/functional-tests/dunstrc.default @@ -14,4 +14,5 @@ timeout = 0 [global] -# can be appended by script + icon_path = /usr/share/icons/Papirus/24x24/status/:/usr/share/icons/Papirus/24x24/devices/:/usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ + # can be appended by script diff --git a/test/functional-tests/dunstrc.hide_text b/test/functional-tests/dunstrc.hide_text index 1340983cf..aff5a58af 100644 --- a/test/functional-tests/dunstrc.hide_text +++ b/test/functional-tests/dunstrc.hide_text @@ -25,4 +25,4 @@ progress_bar_max_width = 200 progress_bar_frame_width = 5 progress_bar_height = 30 - icon_path = /usr/share/icons/Papirus/24x24/status/:/usr/share/icons/Papirus/24x24/devices/:/usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ \ No newline at end of file + icon_path = /usr/share/icons/Papirus/24x24/status/:/usr/share/icons/Papirus/24x24/devices/:/usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ diff --git a/test/functional-tests/dunstrc.icon_position b/test/functional-tests/dunstrc.icon_position index a54287847..f33fd6c23 100644 --- a/test/functional-tests/dunstrc.icon_position +++ b/test/functional-tests/dunstrc.icon_position @@ -82,4 +82,4 @@ progress_bar_frame_width = 5 progress_bar_height = 30 width = (500,750) - icon_path = /usr/share/icons/Papirus/24x24/status/:/usr/share/icons/Papirus/24x24/devices/:/usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ \ No newline at end of file + icon_path = /usr/share/icons/Papirus/24x24/status/:/usr/share/icons/Papirus/24x24/devices/:/usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ diff --git a/test/functional-tests/dunstrc.nowrap b/test/functional-tests/dunstrc.nowrap index 01478f201..d39843e76 100644 --- a/test/functional-tests/dunstrc.nowrap +++ b/test/functional-tests/dunstrc.nowrap @@ -19,8 +19,6 @@ horizontal_padding = 8 separator_color = frame startup_notification = false - dmenu = /usr/bin/dmenu -p dunst: - browser = /usr/bin/firefox -new-tab [frame] width = 3 diff --git a/test/functional-tests/dunstrc.show_age b/test/functional-tests/dunstrc.show_age index 171da2793..7aba58b5e 100644 --- a/test/functional-tests/dunstrc.show_age +++ b/test/functional-tests/dunstrc.show_age @@ -19,8 +19,6 @@ horizontal_padding = 8 separator_color = frame startup_notification = false - dmenu = /usr/bin/dmenu -p dunst - browser = /usr/bin/firefox -new-tab [frame] width = 3 diff --git a/test/functional-tests/test.sh b/test/functional-tests/test.sh index 8a4470ef5..367ddf93f 100755 --- a/test/functional-tests/test.sh +++ b/test/functional-tests/test.sh @@ -23,9 +23,9 @@ function basic_notifications { $DUNSTIFY -a "dunst tester" "normal" "italic body" $DUNSTIFY -a "dunst tester" -u c "critical" "bold body" $DUNSTIFY -a "dunst tester" "long body" "This is a notification with a very long body" - $DUNSTIFY -a "dunst tester" "duplucate" - $DUNSTIFY -a "dunst tester" "duplucate" - $DUNSTIFY -a "dunst tester" "duplucate" + $DUNSTIFY -a "dunst tester" "duplicate" + $DUNSTIFY -a "dunst tester" "duplicate" + $DUNSTIFY -a "dunst tester" "duplicate" $DUNSTIFY -a "dunst tester" "url" "www.google.de" } From 6a03faeb3b2754061ad881dea85b55bb40d97867 Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:55:07 +0200 Subject: [PATCH 06/10] Fix docs formatting --- docs/dunst.5.pod | 51 ++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/docs/dunst.5.pod b/docs/dunst.5.pod index 751b2dbf9..5794586e0 100644 --- a/docs/dunst.5.pod +++ b/docs/dunst.5.pod @@ -84,10 +84,11 @@ old geometry config as follows: In the new config you can then set the following variables (make sure to remove any negative signs) - width = - height = - offset = - origin = top-right # or top-left, or any other direction you prefer + + width = + height = + offset = + origin = top-right # or top-left, or any other direction you prefer =item B @@ -96,8 +97,9 @@ specify a constant width or two numbers for the minimum and maximum width. The notification will expand from the minimum width as neccesary. Examples: - width = 300 # constant width of 300 - width = (0, 300) # width between 0 and 300 + + width = 300 # constant width of 300 + width = (0, 300) # width between 0 and 300 When setting a width bigger than the screen, dunst will clamp the width to the screen width. So if you want the notifcation to stretch the entire screen @@ -111,8 +113,9 @@ specify a constant height or two numbers for the minimum and maximum width. The notification will expand from the minimum height as neccesary. Examples: - height = 300 # constant height of 300 - height = (0, 300) # height between 0 and 300 + + height = 300 # constant height of 300 + height = (0, 300) # height between 0 and 300 Note that unlike width, different notifications can have diffrent height values. @@ -131,15 +134,16 @@ more information. The origin of the notification window on the screen. It can then be moved with offset. Origin can be one of: - top-left - top-center - top-right - bottom-left - bottom-center - bottom-right - left-center - center - right-center + + top-left + top-center + top-right + bottom-left + bottom-center + bottom-right + left-center + center + right-center =item B format: (horizontal, vertical) @@ -148,8 +152,9 @@ of the screen specified by B. A negative offset will lead to the notification being off screen. Examples: - origin = top-right - offset = (10, 300) # a margin of 10 pixels from the right and 300 pixels from the top + + origin = top-right + offset = (10, 300) # a margin of 10 pixels from the right and 300 pixels from the top For backwards compatibility the syntax NxN is also accepted. @@ -571,13 +576,13 @@ actions to be executed in sequence. B -=over 12 +=over 8 -=item * C +=item * C -=item * C +=item * C -=item * C +=item * C =back From 21f276cf9ddb9974f863b88491f52c86da67df65 Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:12:27 +0200 Subject: [PATCH 07/10] Add functional-tests to the Makefile --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c130cf065..4149575e0 100644 --- a/Makefile +++ b/Makefile @@ -90,7 +90,7 @@ dunstify: dunstify.o ${CC} -o ${@} dunstify.o ${DUNSTIFY_CFLAGS} ${DUNSTIFY_LDFLAGS} endif -.PHONY: test test-valgrind test-coverage +.PHONY: test test-valgrind test-coverage functional-tests test: test/test clean-coverage-run # Make sure an error code is returned when the test fails /usr/bin/env bash -c 'set -euo pipefail;\ @@ -124,6 +124,9 @@ test/%.o: test/%.c src/%.c test/test: ${OBJ} ${TEST_OBJ} ${CC} -o ${@} ${TEST_OBJ} $(filter-out ${TEST_OBJ:test/%=src/%},${OBJ}) ${CFLAGS} ${LDFLAGS} +functional-tests: dunst dunstify + DUNST=./dunst DUNSTIFY=./dunstify ./test/functional-tests/test.sh + .PHONY: doc doc-doxygen doc: docs/dunst.1 docs/dunst.5 docs/dunstctl.1 @@ -213,7 +216,7 @@ clean-wayland-protocols: install-service install-service-dbus install-service-systemd \ uninstall uninstall-dunstctl uninstall-dunstrc \ uninstall-service uninstall-service-dbus uninstall-service-systemd \ - uninstall-keepconf uninstall-purge + uninstall-keepconf uninstall-purge install: install-dunst install-dunstctl install-dunstrc install-service install-dunst: dunst doc From 6fafffc7d3e06714c34c2427ebc9b1d28bcf2c22 Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Wed, 1 May 2024 21:48:41 +0200 Subject: [PATCH 08/10] Fix functional tests --- Makefile | 2 +- test/functional-tests/dunstrc.vertical_align | 40 ++++++++++++++++++++ test/functional-tests/test.sh | 33 +++++++--------- 3 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 test/functional-tests/dunstrc.vertical_align diff --git a/Makefile b/Makefile index 4149575e0..5d81556b6 100644 --- a/Makefile +++ b/Makefile @@ -125,7 +125,7 @@ test/test: ${OBJ} ${TEST_OBJ} ${CC} -o ${@} ${TEST_OBJ} $(filter-out ${TEST_OBJ:test/%=src/%},${OBJ}) ${CFLAGS} ${LDFLAGS} functional-tests: dunst dunstify - DUNST=./dunst DUNSTIFY=./dunstify ./test/functional-tests/test.sh + cd ./test/functional-tests ; ./test.sh .PHONY: doc doc-doxygen doc: docs/dunst.1 docs/dunst.5 docs/dunstctl.1 diff --git a/test/functional-tests/dunstrc.vertical_align b/test/functional-tests/dunstrc.vertical_align new file mode 100644 index 000000000..f16b3e062 --- /dev/null +++ b/test/functional-tests/dunstrc.vertical_align @@ -0,0 +1,40 @@ +[urgency_low] + background = "#222222" + foreground = "#888888" + timeout = 10 + +[urgency_normal] + background = "#285577" + foreground = "#ffffff" + timeout = 10 + +[urgency_critical] + background = "#900000" + foreground = "#ffffff" + timeout = 0 + +[hide] + category = .*hide.* + hide_text = yes + +[icon-left] + category = .*icon-left.* + icon_position = left + +[icon-off] + category = .*icon-off.* + icon_position = off + +[icon-right] + category = .*icon-right.* + icon_position = right + +[icon-top] + category = .*icon-top.* + icon_position = top + +[global] + icon_path = /usr/share/icons/Papirus/24x24/status/:/usr/share/icons/Papirus/24x24/devices/:/usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ + enable_posix_regex = yes + # can be appended by script + diff --git a/test/functional-tests/test.sh b/test/functional-tests/test.sh index 367ddf93f..27c02d553 100755 --- a/test/functional-tests/test.sh +++ b/test/functional-tests/test.sh @@ -34,8 +34,7 @@ function show_age { echo "###################################" echo "show age" echo "###################################" - killall dunst - $DUNST -config dunstrc.show_age & + start_dunst dunstrc.show_age & $DUNSTIFY -a "dunst tester" -u c "Show Age" "These should print their age after 2 seconds" basic_notifications keypress @@ -58,8 +57,7 @@ function replace { echo "###################################" echo "replace" echo "###################################" - killall dunst - $DUNST -config dunstrc.default & + start_dunst dunstrc.default id=$($DUNSTIFY -a "dunst tester" -p "Replace" "this should get replaces after keypress") keypress $DUNSTIFY -a "dunst tester" -r $id "Success?" "I hope this is not a new notification" @@ -90,16 +88,14 @@ function markup { echo "###################################" echo "markup" echo "###################################" - killall dunst - $DUNST -config dunstrc.default & + start_dunst dunstrc.default $DUNSTIFY -a "dunst tester" "Markup Tests" -u "c" $DUNSTIFY -a "dunst tester" "Title" "bold italic" $DUNSTIFY -a "dunst tester" "Title" ' Github link ' $DUNSTIFY -a "dunst tester" "Title" "broken markup" keypress - killall dunst - $DUNST -config dunstrc.nomarkup & + start_dunst dunstrc.nomarkup $DUNSTIFY -a "dunst tester" -u c "No markup Tests" "Titles shoud still be in bold and body in italics" $DUNSTIFY -a "dunst tester" "Title" "bolditalic" $DUNSTIFY -a "dunst tester" "Title" "broken markup" @@ -183,21 +179,20 @@ function progress_bar { echo "###################################" echo "progress_bar" echo "###################################" - killall dunst - $DUNST -config dunstrc.default & + start_dunst dunstrc.default $DUNSTIFY -h int:value:0 -a "dunst tester" -u c "Progress bar 0%: " $DUNSTIFY -h int:value:33 -a "dunst tester" -u c "Progress bar 33%: " $DUNSTIFY -h int:value:66 -a "dunst tester" -u c "Progress bar 66%: " $DUNSTIFY -h int:value:100 -a "dunst tester" -u c "Progress bar 100%: " keypress - killall dunst - $DUNST -config dunstrc.default & + + start_dunst dunstrc.default $DUNSTIFY -h int:value:33 -a "dunst tester" -u l "Low priority: " $DUNSTIFY -h int:value:33 -a "dunst tester" -u n "Normal priority: " $DUNSTIFY -h int:value:33 -a "dunst tester" -u c "Critical priority: " keypress - killall dunst - $DUNST -config dunstrc.progress_bar & + + start_dunst dunstrc.progress_bar $DUNSTIFY -h int:value:33 -a "dunst tester" -u n "The progress bar should not be the entire width" $DUNSTIFY -h int:value:33 -a "dunst tester" -u n "You might also notice height and frame size are changed" $DUNSTIFY -h int:value:33 -a "dunst tester" -u c "Short" @@ -298,7 +293,7 @@ function dynamic_height { for min in 50 100 200 ""; do [[ $min -gt $max ]] && continue - tmp_dunstrc dunstrc.dynamic_height "height = ($min, $max)" + tmp_dunstrc dunstrc.vertical_align "height = ($min, $max)" start_dunst dunstrc.tmp $DUNSTIFY -a "dunst tester" -u l "text" "height min = $min"$'\n'"height max = $max" @@ -306,10 +301,10 @@ function dynamic_height { $DUNSTIFY -a "dunst tester" -u n "text + icon" "height min = $min"$'\n'"height max = $max" $DUNSTIFY -a "dunst tester" -h int:value:$((RANDOM%100)) -u n "text + icon + progress bar" "height min = $min"$'\n'"height max = $max" - $DUNSTIFY -a "dunst tester" -h string:category:hide_text -u l "text hidden" "SHOULD BE NOT VISIBLE" - $DUNSTIFY -a "dunst tester" -h string:category:hide_text -h int:value:$((RANDOM%100)) -u l "text hidden + progress bar" "SHOULD BE NOT VISIBLE" - $DUNSTIFY -a "dunst tester" -h string:category:hide_text -u n "text hidden + icon" "SHOULD BE NOT VISIBLE" - $DUNSTIFY -a "dunst tester" -h string:category:hide_text -h int:value:$((RANDOM%100)) -u n "text hidden + icon + progress bar" "SHOULD BE NOT VISIBLE" + $DUNSTIFY -a "dunst tester" -h string:category:hide -u l "text hidden" "SHOULD BE NOT VISIBLE" + $DUNSTIFY -a "dunst tester" -h string:category:hide -h int:value:$((RANDOM%100)) -u l "text hidden + progress bar" "SHOULD BE NOT VISIBLE" + $DUNSTIFY -a "dunst tester" -h string:category:hide -u n "text hidden + icon" "SHOULD BE NOT VISIBLE" + $DUNSTIFY -a "dunst tester" -h string:category:hide -h int:value:$((RANDOM%100)) -u n "text hidden + icon + progress bar" "SHOULD BE NOT VISIBLE" rm dunstrc.tmp keypress From 4ac75962ae2fc77b8f43b880aa03bdd9edd234bc Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Thu, 2 May 2024 00:03:42 +0200 Subject: [PATCH 09/10] Fix vertical alignment --- src/draw.c | 19 ++++++++++--------- test/functional-tests/dunstrc.vertical_align | 12 ++++++++++++ test/functional-tests/test.sh | 8 ++++---- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/draw.c b/src/draw.c index d74b637c4..87437cc3e 100644 --- a/src/draw.c +++ b/src/draw.c @@ -245,15 +245,15 @@ static struct dimensions calculate_notification_dimensions(struct colored_layout dim.h += progress_bar_height; dim.w = dim.text_width + icon_width + 2 * settings.h_padding; + if (have_progress_bar(cl)) + dim.w = MAX(settings.progress_bar_min_width, dim.w); + dim.h = MIN(settings.height.max, dim.h + settings.padding * 2); dim.h = MAX(settings.height.min, dim.h); dim.w = MAX(settings.width.min, dim.w); dim.w = MIN(settings.width.max, dim.w); - if (have_progress_bar(cl)) - dim.w = MAX(settings.progress_bar_min_width, dim.w); - cl->n->displayed_height = dim.h; return dim; } @@ -711,7 +711,7 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int // alignment work correctly layout_setup(cl, width, height, scale); - // NOTE: Includes the last padding + // NOTE: Includes paddings! int h_without_progress_bar = height; if (have_progress_bar(cl)) { h_without_progress_bar -= settings.progress_bar_height + settings.padding; @@ -727,7 +727,7 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int text_y = settings.padding; if (settings.vertical_alignment == VERTICAL_CENTER) { - text_y += h_without_progress_bar / 2 - text_h / 2; + text_y = h_without_progress_bar / 2 - text_h / 2; } else if (settings.vertical_alignment == VERTICAL_BOTTOM) { text_y = h_without_progress_bar - settings.padding - text_h; } // else VERTICAL_TOP @@ -743,13 +743,14 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int // vertical alignment switch (settings.vertical_alignment) { case VERTICAL_TOP: - if (cl->n->hide_text || cl->n->icon_position == ICON_TOP) { + if (cl->n->icon_position == ICON_TOP) { + // Shift text downward text_y += image_height + v_padding; } break; case VERTICAL_CENTER: - if (cl->n->hide_text || cl->n->icon_position == ICON_TOP) { - // Shift text downward + if (cl->n->icon_position == ICON_TOP) { + // Adjust text and image by half image_y -= (image_height + v_padding) / 2; text_y += (image_height + v_padding) / 2; } else { @@ -757,7 +758,7 @@ static void render_content(cairo_t *c, struct colored_layout *cl, int width, int } break; case VERTICAL_BOTTOM: - if (cl->n->hide_text || cl->n->icon_position == ICON_TOP) { + if (cl->n->icon_position == ICON_TOP) { image_y -= image_height + v_padding; } else { image_y -= image_height - text_h; diff --git a/test/functional-tests/dunstrc.vertical_align b/test/functional-tests/dunstrc.vertical_align index f16b3e062..b451c01f8 100644 --- a/test/functional-tests/dunstrc.vertical_align +++ b/test/functional-tests/dunstrc.vertical_align @@ -33,6 +33,18 @@ category = .*icon-top.* icon_position = top +[alignment-left] + category = .*alignment-left.* + alignment = left + +[alignment-right] + category = .*alignment-right.* + alignment = right + +[alignment-center] + category = .*alignment-center.* + alignment = center + [global] icon_path = /usr/share/icons/Papirus/24x24/status/:/usr/share/icons/Papirus/24x24/devices/:/usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ enable_posix_regex = yes diff --git a/test/functional-tests/test.sh b/test/functional-tests/test.sh index 27c02d553..4a59ae918 100755 --- a/test/functional-tests/test.sh +++ b/test/functional-tests/test.sh @@ -296,10 +296,10 @@ function dynamic_height { tmp_dunstrc dunstrc.vertical_align "height = ($min, $max)" start_dunst dunstrc.tmp - $DUNSTIFY -a "dunst tester" -u l "text" "height min = $min"$'\n'"height max = $max" - $DUNSTIFY -a "dunst tester" -h int:value:$((RANDOM%100)) -u l "text+ progress bar" "height min = $min"$'\n'"height max = $max" - $DUNSTIFY -a "dunst tester" -u n "text + icon" "height min = $min"$'\n'"height max = $max" - $DUNSTIFY -a "dunst tester" -h int:value:$((RANDOM%100)) -u n "text + icon + progress bar" "height min = $min"$'\n'"height max = $max" + $DUNSTIFY -a "dunst tester" -u l "text" "height min = $min, max = $max" + $DUNSTIFY -a "dunst tester" -h int:value:$((RANDOM%100)) -u l "text + progress bar" "height min = $min, max = $max" + $DUNSTIFY -a "dunst tester" -u n "text + icon" "height min = $min, max = $max" + $DUNSTIFY -a "dunst tester" -h int:value:$((RANDOM%100)) -u n "text + icon + progress bar" "height min = $min, max = $max" $DUNSTIFY -a "dunst tester" -h string:category:hide -u l "text hidden" "SHOULD BE NOT VISIBLE" $DUNSTIFY -a "dunst tester" -h string:category:hide -h int:value:$((RANDOM%100)) -u l "text hidden + progress bar" "SHOULD BE NOT VISIBLE" From 2b407f260f752b105d45c63b33f84f9b450d313b Mon Sep 17 00:00:00 2001 From: bynect <68197565+bynect@users.noreply.github.com> Date: Fri, 3 May 2024 23:55:04 +0200 Subject: [PATCH 10/10] Improve functional tests --- Makefile | 2 +- test/functional-tests/dunstrc.nowrap | 6 ---- test/functional-tests/dunstrc.show_age | 6 ---- test/functional-tests/script_test.sh | 3 +- test/functional-tests/test.sh | 43 ++++++++++++++++---------- 5 files changed, 29 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index 5d81556b6..4070263d8 100644 --- a/Makefile +++ b/Makefile @@ -125,7 +125,7 @@ test/test: ${OBJ} ${TEST_OBJ} ${CC} -o ${@} ${TEST_OBJ} $(filter-out ${TEST_OBJ:test/%=src/%},${OBJ}) ${CFLAGS} ${LDFLAGS} functional-tests: dunst dunstify - cd ./test/functional-tests ; ./test.sh + PREFIX=. ./test/functional-tests/test.sh .PHONY: doc doc-doxygen doc: docs/dunst.1 docs/dunst.5 docs/dunstctl.1 diff --git a/test/functional-tests/dunstrc.nowrap b/test/functional-tests/dunstrc.nowrap index d39843e76..548108958 100644 --- a/test/functional-tests/dunstrc.nowrap +++ b/test/functional-tests/dunstrc.nowrap @@ -24,12 +24,6 @@ width = 3 color = "#aaaaaa" -[shortcuts] - close = ctrl+space - close_all = ctrl+shift+space - history = ctrl+grave - context = ctrl+shift+period - [urgency_low] background = "#222222" foreground = "#888888" diff --git a/test/functional-tests/dunstrc.show_age b/test/functional-tests/dunstrc.show_age index 7aba58b5e..47e8c75e0 100644 --- a/test/functional-tests/dunstrc.show_age +++ b/test/functional-tests/dunstrc.show_age @@ -24,12 +24,6 @@ width = 3 color = "#aaaaaa" -[shortcuts] - close = ctrl+space - close_all = ctrl+shift+space - history = ctrl+grave - context = ctrl+shift+period - [urgency_low] background = "#222222" foreground = "#888888" diff --git a/test/functional-tests/script_test.sh b/test/functional-tests/script_test.sh index 06ea56b09..8e21d4023 100755 --- a/test/functional-tests/script_test.sh +++ b/test/functional-tests/script_test.sh @@ -1,3 +1,4 @@ #!/bin/bash -../../dunstify "Success" "ooooh yeah" +echo "triggered script!" +$DUNSTIFY "Success" "ooooh yeah" diff --git a/test/functional-tests/test.sh b/test/functional-tests/test.sh index 4a59ae918..a66009a71 100755 --- a/test/functional-tests/test.sh +++ b/test/functional-tests/test.sh @@ -1,7 +1,13 @@ #!/bin/bash -DUNST="${DUNST:-../../dunst}" -DUNSTIFY="${DUNSTIFY:-../../dunstify}" +# prefix should be the root of the repository +PREFIX="${PREFIX:-../..}" +TESTDIR="$PREFIX/test/functional-tests" + +# for run_script +export PATH="$TESTDIR:$PATH" +export DUNST="${DUNST:-$PREFIX/dunst}" +export DUNSTIFY="${DUNSTIFY:-$PREFIX/dunstify}" function keypress { echo "press enter to continue..." @@ -9,13 +15,17 @@ function keypress { } function tmp_dunstrc { - cp "$1" dunstrc.tmp - echo -e "\n$2" >> dunstrc.tmp + cp "$TESTDIR/$1" "$TESTDIR/dunstrc.tmp" + echo -e "\n$2" >> "$TESTDIR/dunstrc.tmp" +} + +function tmp_clean { + rm "$TESTDIR/dunstrc.tmp" } function start_dunst { killall dunst 2>/dev/null - $DUNST -config $1 & + $DUNST -config "$TESTDIR/$1" & sleep 0.05 } @@ -34,7 +44,7 @@ function show_age { echo "###################################" echo "show age" echo "###################################" - start_dunst dunstrc.show_age & + start_dunst dunstrc.show_age $DUNSTIFY -a "dunst tester" -u c "Show Age" "These should print their age after 2 seconds" basic_notifications keypress @@ -44,8 +54,7 @@ function run_script { echo "###################################" echo "run script" echo "###################################" - killall dunst - PATH=".:$PATH" $DUNST -config dunstrc.run_script & + start_dunst dunstrc.run_script $DUNSTIFY -a "dunst tester" -u c \ "Run Script" "After Keypress, 2 other notification should pop up." keypress @@ -73,14 +82,14 @@ function limit { start_dunst dunstrc.tmp $DUNSTIFY -a "dunst tester" -u c "notification limit = 4" basic_notifications - rm dunstrc.tmp + tmp_clean keypress tmp_dunstrc dunstrc.default "notification_limit=0" start_dunst dunstrc.tmp $DUNSTIFY -a "dunst tester" -u c "notification limit = 0 (unlimited notifications)" basic_notifications - rm dunstrc.tmp + tmp_clean keypress } @@ -108,7 +117,7 @@ function test_origin { start_dunst dunstrc.tmp $DUNSTIFY -a "dunst tester" -u c "$1" basic_notifications - rm dunstrc.tmp + tmp_clean keypress } @@ -132,7 +141,7 @@ function test_width { start_dunst dunstrc.tmp $DUNSTIFY -a "dunst tester" -u c "width = $1" basic_notifications - rm dunstrc.tmp + tmp_clean keypress } @@ -152,7 +161,7 @@ function test_height { $DUNSTIFY -a "dunst tester" -u c "height = $1" $DUNSTIFY -a "dunst tester" -u c "Temporibus accusantium libero sequi at nostrum dolor sequi sed. Cum minus reprehenderit voluptatibus laboriosam et et ut. Laudantium blanditiis omnis ipsa rerum quas velit ut. Quae voluptate soluta enim consequatur libero eum similique ad. Veritatis neque consequatur et aperiam quisquam id nostrum. Consequatur voluptas aut ut omnis atque cum perferendis. Possimus laudantium tempore iste qui nemo voluptate quod. Labore totam debitis consectetur amet. Maxime quibusdam ipsum voluptates quod ex nam sunt. Officiis repellat quod maxime cumque tenetur. Veritatis labore aperiam repellendus. Provident dignissimos ducimus voluptates." basic_notifications - rm dunstrc.tmp + tmp_clean keypress } @@ -162,7 +171,7 @@ function test_progress_bar_alignment { $DUNSTIFY -a "dunst tester" -u c "alignment = $1" $DUNSTIFY -h int:value:33 -a "dunst tester" -u n "The progress bar should not be the entire width" $DUNSTIFY -h int:value:33 -a "dunst tester" -u c "Short" - rm dunstrc.tmp + tmp_clean keypress } @@ -231,7 +240,7 @@ function icon_position { $DUNSTIFY -a "dunst tester" --hints string:category:$category -u n "$category"$'\n'"padding emphasis: $label" done done - rm dunstrc.tmp + tmp_clean keypress done } @@ -306,7 +315,7 @@ function dynamic_height { $DUNSTIFY -a "dunst tester" -h string:category:hide -u n "text hidden + icon" "SHOULD BE NOT VISIBLE" $DUNSTIFY -a "dunst tester" -h string:category:hide -h int:value:$((RANDOM%100)) -u n "text hidden + icon + progress bar" "SHOULD BE NOT VISIBLE" - rm dunstrc.tmp + tmp_clean keypress done done @@ -356,7 +365,7 @@ function vertical_align { done done - rm dunstrc.tmp + tmp_clean keypress done done