From ab3b5c28051640f83420d24a79cf4bdffea7738d Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Fri, 29 Sep 2017 11:58:10 +0300 Subject: [PATCH 01/10] Implement #392 --- config.h | 1 + src/icon.c | 28 ++++++++++++++++------------ src/settings.c | 6 ++++++ src/settings.h | 1 + 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/config.h b/config.h index 7026d38..81f82ec 100644 --- a/config.h +++ b/config.h @@ -65,6 +65,7 @@ struct settings defaults = { .browser = "/usr/bin/firefox", +.min_icon_size = 0, .max_icon_size = 0, /* paths to default icons */ diff --git a/src/icon.c b/src/icon.c index 71a4731..f24ef4b 100644 --- a/src/icon.c +++ b/src/icon.c @@ -116,19 +116,23 @@ GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) int w = gdk_pixbuf_get_width(pixbuf); int h = gdk_pixbuf_get_height(pixbuf); - int larger = w > h ? w : h; + int landscape = w > h; + int orig_larger = landscape ? w : h; + double larger = orig_larger; + double smaller = landscape ? h : w; + if (settings.min_icon_size && smaller < settings.min_icon_size) { + larger = larger / smaller * settings.min_icon_size; + smaller = settings.min_icon_size; + } if (settings.max_icon_size && larger > settings.max_icon_size) { - int scaled_w = settings.max_icon_size; - int scaled_h = settings.max_icon_size; - if (w >= h) - scaled_h = (settings.max_icon_size * h) / w; - else - scaled_w = (settings.max_icon_size * w) / h; - - GdkPixbuf *scaled = gdk_pixbuf_scale_simple( - pixbuf, - scaled_w, - scaled_h, + smaller = smaller / larger * settings.max_icon_size; + larger = settings.max_icon_size; + } + if ((int) larger != orig_larger) { + GdkPixbuf *scaled; + scaled = gdk_pixbuf_scale_simple(pixbuf, + (int) (landscape ? larger : smaller), + (int) (landscape ? smaller : larger), GDK_INTERP_BILINEAR); g_object_unref(pixbuf); pixbuf = scaled; diff --git a/src/settings.c b/src/settings.c index fde3715..90077fb 100644 --- a/src/settings.c +++ b/src/settings.c @@ -423,6 +423,12 @@ void load_settings(char *cmdline_config_path) g_free(c); } + settings.min_icon_size = option_get_int( + "global", + "min_icon_size", "-min_icon_size", defaults.min_icon_size, + "Scale smaller icons up to this size, set to 0 to disable. If max_icon_size also specified, that has the final say." + ); + settings.max_icon_size = option_get_int( "global", "max_icon_size", "-max_icon_size", defaults.max_icon_size, diff --git a/src/settings.h b/src/settings.h index 6bcf6b8..6e541c2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -75,6 +75,7 @@ struct settings { char *browser; char **browser_cmd; enum icon_position icon_position; + int min_icon_size; int max_icon_size; char *icon_path; enum follow_mode f_mode; From 364bce1ed0366dc3b24ed8eac12881e033858d2a Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Fri, 29 Nov 2019 21:28:22 +0200 Subject: [PATCH 02/10] Scale icons during loading to get best quality for e.g. vector images --- src/icon.c | 65 ++++++++++++++++++++++++++++++++++++---------- src/icon.h | 19 +++----------- src/notification.c | 2 -- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/icon.c b/src/icon.c index f24ef4b..2701a27 100644 --- a/src/icon.c +++ b/src/icon.c @@ -110,16 +110,18 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf) return icon_surface; } -GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) -{ - ASSERT_OR_RET(pixbuf, NULL); - - int w = gdk_pixbuf_get_width(pixbuf); - int h = gdk_pixbuf_get_height(pixbuf); - int landscape = w > h; - int orig_larger = landscape ? w : h; +/** + * Scales the given image dimensions if necessary according to the settings. + * + * @param w a pointer to the image width, to be modified in-place + * @param h a pointer to the image height, to be modified in-place + */ +static bool icon_size_clamp(int *w, int *h) { + int _w = *w, _h = *h; + int landscape = _w > _h; + int orig_larger = landscape ? _w : _h; double larger = orig_larger; - double smaller = landscape ? h : w; + double smaller = landscape ? _h : _w; if (settings.min_icon_size && smaller < settings.min_icon_size) { larger = larger / smaller * settings.min_icon_size; smaller = settings.min_icon_size; @@ -129,11 +131,35 @@ GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) larger = settings.max_icon_size; } if ((int) larger != orig_larger) { + *w = (int) (landscape ? larger : smaller); + *h = (int) (landscape ? smaller : larger); + return TRUE; + } + return FALSE; +} + +/** + * Scales the given GdkPixbuf if necessary according to the settings. + * + * @param pixbuf (nullable) The pixbuf, which may be too big. + * Takes ownership of the reference. + * @return the scaled version of the pixbuf. If scaling wasn't + * necessary, it returns the same pixbuf. Transfers full + * ownership of the reference. + */ +static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) +{ + ASSERT_OR_RET(pixbuf, NULL); + + int w = gdk_pixbuf_get_width(pixbuf); + int h = gdk_pixbuf_get_height(pixbuf); + + if (icon_size_clamp(&w, &h)) { GdkPixbuf *scaled; scaled = gdk_pixbuf_scale_simple(pixbuf, - (int) (landscape ? larger : smaller), - (int) (landscape ? smaller : larger), - GDK_INTERP_BILINEAR); + w, + h, + GDK_INTERP_BILINEAR); g_object_unref(pixbuf); pixbuf = scaled; } @@ -145,8 +171,19 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename) { char *path = string_to_path(g_strdup(filename)); GError *error = NULL; + gint w, h; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &error); + if (!gdk_pixbuf_get_file_info (path, &w, &h)) { + LOG_W("Failed to load image info for %s", filename); + g_error_free(error); + return NULL; + } + icon_size_clamp(&w, &h); + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_scale(path, + w, + h, + TRUE, + &error); if (error) { LOG_W("%s", error->message); @@ -324,6 +361,8 @@ GdkPixbuf *icon_get_for_data(GVariant *data, char **id) g_free(data_chk); g_variant_unref(data_variant); + pixbuf = icon_pixbuf_scale(pixbuf); + return pixbuf; } diff --git a/src/icon.h b/src/icon.h index 37cbea0..2de0740 100644 --- a/src/icon.h +++ b/src/icon.h @@ -8,18 +8,7 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf); -/** - * Scales the given GdkPixbuf if necessary according to the settings. - * - * @param pixbuf (nullable) The pixbuf, which may be too big. - * Takes ownership of the reference. - * @return the scaled version of the pixbuf. If scaling wasn't - * necessary, it returns the same pixbuf. Transfers full - * ownership of the reference. - */ -GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf); - -/** Retrieve an icon by its full filepath. +/** Retrieve an icon by its full filepath, scaled according to settings. * * @param filename A string representing a readable file path * @@ -28,7 +17,7 @@ GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf); */ GdkPixbuf *get_pixbuf_from_file(const char *filename); -/** Retrieve an icon by its name sent via the notification bus +/** Retrieve an icon by its name sent via the notification bus, scaled according to settings * * @param iconname A string describing a `file://` URL, an arbitary filename * or an icon name, which then gets searched for in the @@ -39,7 +28,7 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename); */ GdkPixbuf *get_pixbuf_from_icon(const char *iconname); -/** Read an icon from disk and convert it to a GdkPixbuf. +/** Read an icon from disk and convert it to a GdkPixbuf, scaled according to settings * * The returned id will be a unique identifier. To check if two given * GdkPixbufs are equal, it's sufficient to just compare the id strings. @@ -54,7 +43,7 @@ GdkPixbuf *get_pixbuf_from_icon(const char *iconname); */ GdkPixbuf *icon_get_for_name(const char *name, char **id); -/** Convert a GVariant like described in GdkPixbuf +/** Convert a GVariant like described in GdkPixbuf, scaled according to settings * * The returned id will be a unique identifier. To check if two given * GdkPixbufs are equal, it's sufficient to just compare the id strings. diff --git a/src/notification.c b/src/notification.c index f1cc14d..6518b49 100644 --- a/src/notification.c +++ b/src/notification.c @@ -252,7 +252,6 @@ void notification_icon_replace_path(struct notification *n, const char *new_icon g_clear_pointer(&n->icon_id, g_free); n->icon = icon_get_for_name(new_icon, &n->icon_id); - n->icon = icon_pixbuf_scale(n->icon); } void notification_icon_replace_data(struct notification *n, GVariant *new_icon) @@ -264,7 +263,6 @@ void notification_icon_replace_data(struct notification *n, GVariant *new_icon) g_clear_pointer(&n->icon_id, g_free); n->icon = icon_get_for_data(new_icon, &n->icon_id); - n->icon = icon_pixbuf_scale(n->icon); } /* see notification.h */ From 39c97e28f6f3be8aedd492ca8e538a672f547529 Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Tue, 3 Dec 2019 20:27:31 +0200 Subject: [PATCH 03/10] [ReviewFix] get_pixbuf_from_file: Free memory on error return --- src/icon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/icon.c b/src/icon.c index 2701a27..d07e8ea 100644 --- a/src/icon.c +++ b/src/icon.c @@ -175,6 +175,7 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename) if (!gdk_pixbuf_get_file_info (path, &w, &h)) { LOG_W("Failed to load image info for %s", filename); + g_free(path); g_error_free(error); return NULL; } From e077b949a6282f25dceab14c29062ba72d10ccd0 Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Tue, 3 Dec 2019 20:28:08 +0200 Subject: [PATCH 04/10] [ReviewFix] gdk_pixbuf_from_file: Update valgrind suppressions to match new code paths --- .valgrind.suppressions | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.valgrind.suppressions b/.valgrind.suppressions index 7201368..49b3d07 100644 --- a/.valgrind.suppressions +++ b/.valgrind.suppressions @@ -20,10 +20,10 @@ fun:g_error_new_valist fun:g_set_error obj:*/librsvg-2.so* - obj:*/librsvg-2.so* + fun:rsvg_handle_close obj:*/loaders/libpixbufloader-svg.so - obj:*/libgdk_pixbuf-2.0.so* - fun:gdk_pixbuf_new_from_file + fun:gdk_pixbuf_loader_close + fun:gdk_pixbuf_get_file_info fun:get_pixbuf_from_file ... } @@ -45,7 +45,8 @@ fun:rsvg_handle_write obj:*/loaders/libpixbufloader-svg.so obj:*/libgdk_pixbuf-2.0.so* - fun:gdk_pixbuf_new_from_file + fun:gdk_pixbuf_loader_close + fun:gdk_pixbuf_get_file_info fun:get_pixbuf_from_file ... } From 445d305bf86e7dc65c7005392261982bee746f59 Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Tue, 3 Dec 2019 20:45:27 +0200 Subject: [PATCH 05/10] [ReviewFix] dunstrc: Add min_icon_size --- dunstrc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dunstrc b/dunstrc index d8665fe..c9b149e 100644 --- a/dunstrc +++ b/dunstrc @@ -162,6 +162,11 @@ # Align icons left/right/off icon_position = off + # Scale small icons up to this size, set to 0 to disable. Helpful + # for e.g. small files or high-dpi screens. In case of conflict, + # max_icon_size takes precedence over this. + min_icon_size = 0 + # Scale larger icons down to this size, set to 0 to disable max_icon_size = 32 From 9264b0f994615ff6b8bd05f19049a3eaee944f42 Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Tue, 3 Dec 2019 21:29:22 +0200 Subject: [PATCH 06/10] [ReviewFix] dunst.pod: Update icon scaling documentation --- docs/dunst.pod | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/dunst.pod b/docs/dunst.pod index f9d0ee5..4c25b2c 100644 --- a/docs/dunst.pod +++ b/docs/dunst.pod @@ -384,14 +384,28 @@ ACTIONS below for further details. Defines the position of the icon in the notification window. Setting it to off disables icons. +=item B (default: 0) + +Defines the minimum size in pixels for the icons. +If the icon is larger than or equal to the specified value it won't be affected. +If it's smaller then it will be scaled up so that the smaller axis is equivalent +to the specified size. + +Set to 0 to disable icon upscaling. (default) + +If B is set to off, this setting is ignored. + =item B (default: 0) Defines the maximum size in pixels for the icons. -If the icon is smaller than the specified value it won't be affected. +If the icon is smaller than or equal to the specified value it won't be affected. If it's larger then it will be scaled down so that the larger axis is equivalent to the specified size. -Set to 0 to disable icon scaling. (default) +Set to 0 to disable icon downscaling. (default) + +If both B and B are enabled, the latter +gets the last say. If B is set to off, this setting is ignored. From 87491192cb9d4af974f0db6cd0676881dbd29e9d Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Tue, 3 Dec 2019 22:34:17 +0200 Subject: [PATCH 07/10] [RegressionFix] Slightly different valgrind leak trace in CI env --- .valgrind.suppressions | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.valgrind.suppressions b/.valgrind.suppressions index 49b3d07..db7a88a 100644 --- a/.valgrind.suppressions +++ b/.valgrind.suppressions @@ -28,6 +28,26 @@ ... } +# same as above, but as occurs in CI environment +{ + rsvg_error_handle_close2 + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_error_new_valist + fun:g_set_error + obj:*/librsvg-2.so* + obj:*/librsvg-2.so* + obj:*/loaders/libpixbufloader-svg.so + obj:*/libgdk_pixbuf-2.0.so* + fun:gdk_pixbuf_loader_close + fun:gdk_pixbuf_get_file_info + fun:get_pixbuf_from_file + ... +} + # rsvg_error_writehandler got fixed in # - GNOME/librsvg@7b4cc9b # (2018-11-12, first tags: v2.45.0, v2.44.9) From 667503ef7dc41b9cdfc4a6bd0d47c306f0dbb8e0 Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Wed, 4 Dec 2019 20:59:19 +0200 Subject: [PATCH 08/10] Cleanup, documentation --- src/icon.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/icon.c b/src/icon.c index d07e8ea..6359933 100644 --- a/src/icon.c +++ b/src/icon.c @@ -115,6 +115,7 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf) * * @param w a pointer to the image width, to be modified in-place * @param h a pointer to the image height, to be modified in-place + * @return TRUE if the dimensions were updated, FALSE if they were left unchanged */ static bool icon_size_clamp(int *w, int *h) { int _w = *w, _h = *h; @@ -155,11 +156,11 @@ static GdkPixbuf *icon_pixbuf_scale(GdkPixbuf *pixbuf) int h = gdk_pixbuf_get_height(pixbuf); if (icon_size_clamp(&w, &h)) { - GdkPixbuf *scaled; - scaled = gdk_pixbuf_scale_simple(pixbuf, - w, - h, - GDK_INTERP_BILINEAR); + GdkPixbuf *scaled = gdk_pixbuf_scale_simple( + pixbuf, + w, + h, + GDK_INTERP_BILINEAR); g_object_unref(pixbuf); pixbuf = scaled; } From 03253e82f7fce95c3e330fcc6e8bda03c6d7a316 Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Thu, 5 Dec 2019 20:12:07 +0200 Subject: [PATCH 09/10] [ReviewFix] Remove bogous g_error_free() cal --- src/icon.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/icon.c b/src/icon.c index 6359933..7529944 100644 --- a/src/icon.c +++ b/src/icon.c @@ -177,7 +177,6 @@ GdkPixbuf *get_pixbuf_from_file(const char *filename) if (!gdk_pixbuf_get_file_info (path, &w, &h)) { LOG_W("Failed to load image info for %s", filename); g_free(path); - g_error_free(error); return NULL; } icon_size_clamp(&w, &h); From ad5d20bd6a0437544abdf913ae03ff2401a156b4 Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Tue, 17 Dec 2019 22:16:29 +0200 Subject: [PATCH 10/10] Add tests for icon scaling math & loading --- test/dbus.c | 25 ++------------ test/helpers.c | 35 ++++++++++++++++++++ test/helpers.h | 9 +++++ test/icon.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ test/notification.c | 75 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 202 insertions(+), 22 deletions(-) create mode 100644 test/helpers.c create mode 100644 test/helpers.h diff --git a/test/dbus.c b/test/dbus.c index f212468..659731a 100644 --- a/test/dbus.c +++ b/test/dbus.c @@ -6,6 +6,7 @@ #include #include +#include "helpers.h" #include "queues.h" extern const char *base; @@ -252,33 +253,13 @@ bool dbus_notification_fire(struct dbus_notification *n, uint *id) void dbus_notification_set_raw_image(struct dbus_notification *n_dbus, const char *path) { - GdkPixbuf *pb = gdk_pixbuf_new_from_file(path, NULL); - - if (!pb) + GVariant *hint = notification_setup_raw_image(path); + if (!hint) return; - GVariant *hint_data = g_variant_new_from_data( - G_VARIANT_TYPE("ay"), - gdk_pixbuf_read_pixels(pb), - gdk_pixbuf_get_byte_length(pb), - TRUE, - (GDestroyNotify) g_object_unref, - g_object_ref(pb)); - - GVariant *hint = g_variant_new( - "(iiibii@ay)", - gdk_pixbuf_get_width(pb), - gdk_pixbuf_get_height(pb), - gdk_pixbuf_get_rowstride(pb), - gdk_pixbuf_get_has_alpha(pb), - gdk_pixbuf_get_bits_per_sample(pb), - gdk_pixbuf_get_n_channels(pb), - hint_data); - g_hash_table_insert(n_dbus->hints, g_strdup("image-data"), g_variant_ref_sink(hint)); - g_object_unref(pb); } /////// TESTS diff --git a/test/helpers.c b/test/helpers.c new file mode 100644 index 0000000..da3cde2 --- /dev/null +++ b/test/helpers.c @@ -0,0 +1,35 @@ +#include + +#include "helpers.h" + +GVariant *notification_setup_raw_image(const char *path) +{ + GdkPixbuf *pb = gdk_pixbuf_new_from_file(path, NULL); + + if (!pb) + return NULL; + + GVariant *hint_data = g_variant_new_from_data( + G_VARIANT_TYPE("ay"), + gdk_pixbuf_read_pixels(pb), + gdk_pixbuf_get_byte_length(pb), + TRUE, + (GDestroyNotify) g_object_unref, + g_object_ref(pb)); + + GVariant *hint = g_variant_new( + "(iiibii@ay)", + gdk_pixbuf_get_width(pb), + gdk_pixbuf_get_height(pb), + gdk_pixbuf_get_rowstride(pb), + gdk_pixbuf_get_has_alpha(pb), + gdk_pixbuf_get_bits_per_sample(pb), + gdk_pixbuf_get_n_channels(pb), + hint_data); + + g_object_unref(pb); + + return hint; +} + +/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/test/helpers.h b/test/helpers.h new file mode 100644 index 0000000..0b9867a --- /dev/null +++ b/test/helpers.h @@ -0,0 +1,9 @@ +#ifndef DUNST_TEST_HELPERS_H +#define DUNST_TEST_HELPERS_H + +#include + +GVariant *notification_setup_raw_image(const char *path); + +#endif +/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/test/icon.c b/test/icon.c index 5bd96aa..94a29ce 100644 --- a/test/icon.c +++ b/test/icon.c @@ -113,6 +113,61 @@ TEST test_get_pixbuf_from_icon_fileuri(void) PASS(); } +TEST test_icon_size_clamp_too_small(void) +{ + int w = 12, h = 24; + bool resized = icon_size_clamp(&w, &h); + ASSERT(resized); + ASSERT_EQ(w, 16); + ASSERT_EQ(h, 32); + + PASS(); +} + +TEST test_icon_size_clamp_not_necessary(void) +{ + int w = 20, h = 30; + bool resized = icon_size_clamp(&w, &h); + ASSERT(!resized); + ASSERT_EQ(w, 20); + ASSERT_EQ(h, 30); + + PASS(); +} + +TEST test_icon_size_clamp_too_big(void) +{ + int w = 75, h = 150; + bool resized = icon_size_clamp(&w, &h); + ASSERT(resized); + ASSERT_EQ(w, 50); + ASSERT_EQ(h, 100); + + PASS(); +} + +TEST test_icon_size_clamp_too_small_then_too_big(void) +{ + int w = 8, h = 80; + bool resized = icon_size_clamp(&w, &h); + ASSERT(resized); + ASSERT_EQ(w, 10); + ASSERT_EQ(h, 100); + + PASS(); +} + +TEST test_get_pixbuf_from_icon_both_is_scaled(void) +{ + GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng"); + ASSERT(pixbuf); + ASSERT_EQ(gdk_pixbuf_get_width(pixbuf), 16); + ASSERT_EQ(gdk_pixbuf_get_height(pixbuf), 16); + g_clear_pointer(&pixbuf, g_object_unref); + + PASS(); +} + SUITE(suite_icon) { settings.icon_path = g_strconcat( @@ -129,6 +184,31 @@ SUITE(suite_icon) RUN_TEST(test_get_pixbuf_from_icon_onlypng); RUN_TEST(test_get_pixbuf_from_icon_filename); RUN_TEST(test_get_pixbuf_from_icon_fileuri); + RUN_TEST(test_icon_size_clamp_not_necessary); + + settings.min_icon_size = 16; + settings.max_icon_size = 100; + + RUN_TEST(test_get_pixbuf_from_icon_both_is_scaled); + RUN_TEST(test_icon_size_clamp_too_small); + RUN_TEST(test_icon_size_clamp_not_necessary); + RUN_TEST(test_icon_size_clamp_too_big); + RUN_TEST(test_icon_size_clamp_too_small_then_too_big); + + settings.min_icon_size = 16; + settings.max_icon_size = 0; + + RUN_TEST(test_icon_size_clamp_too_small); + RUN_TEST(test_icon_size_clamp_not_necessary); + + settings.min_icon_size = 0; + settings.max_icon_size = 100; + + RUN_TEST(test_icon_size_clamp_not_necessary); + RUN_TEST(test_icon_size_clamp_too_big); + + settings.min_icon_size = 0; + settings.max_icon_size = 0; g_clear_pointer(&settings.icon_path, g_free); } diff --git a/test/notification.c b/test/notification.c index 69040f6..ad73f34 100644 --- a/test/notification.c +++ b/test/notification.c @@ -1,5 +1,6 @@ #include "../src/notification.c" #include "greatest.h" +#include "helpers.h" #include "../src/option_parser.h" #include "../src/settings.h" @@ -124,6 +125,76 @@ TEST test_notification_referencing(void) PASS(); } + +static struct notification *notification_load_icon_with_scaling(int min_icon_size, int max_icon_size) +{ + struct notification *n = notification_create(); + + char *path = g_strconcat(base, "/data/icons/valid.svg", NULL); // 16x16 + + GVariant *rawIcon = notification_setup_raw_image(path); + + settings.min_icon_size = min_icon_size; + settings.max_icon_size = max_icon_size; + notification_icon_replace_data(n, rawIcon); + settings.min_icon_size = 0; + settings.max_icon_size = 0; + + g_variant_unref(rawIcon); + g_free(path); + + return n; +} + +TEST test_notification_icon_scaling_toosmall(void) +{ + struct notification *n = notification_load_icon_with_scaling(20, 100); + + ASSERT_EQ(gdk_pixbuf_get_width(n->icon), 20); + ASSERT_EQ(gdk_pixbuf_get_height(n->icon), 20); + + notification_unref(n); + + PASS(); +} + + +TEST test_notification_icon_scaling_toolarge(void) +{ + struct notification *n = notification_load_icon_with_scaling(5, 10); + + ASSERT_EQ(gdk_pixbuf_get_width(n->icon), 10); + ASSERT_EQ(gdk_pixbuf_get_height(n->icon), 10); + + notification_unref(n); + + PASS(); +} + +TEST test_notification_icon_scaling_notconfigured(void) +{ + struct notification *n = notification_load_icon_with_scaling(0, 0); + + ASSERT_EQ(gdk_pixbuf_get_width(n->icon), 16); + ASSERT_EQ(gdk_pixbuf_get_height(n->icon), 16); + + notification_unref(n); + + PASS(); +} + +TEST test_notification_icon_scaling_notneeded(void) +{ + struct notification *n = notification_load_icon_with_scaling(10, 20); + + ASSERT_EQ(gdk_pixbuf_get_width(n->icon), 16); + ASSERT_EQ(gdk_pixbuf_get_height(n->icon), 16); + + notification_unref(n); + + PASS(); +} + TEST test_notification_format_message(struct notification *n, const char *format, const char *exp) { n->format = format; @@ -167,6 +238,10 @@ SUITE(suite_notification) RUN_TEST(test_notification_is_duplicate); RUN_TEST(test_notification_replace_single_field); RUN_TEST(test_notification_referencing); + RUN_TEST(test_notification_icon_scaling_toosmall); + RUN_TEST(test_notification_icon_scaling_toolarge); + RUN_TEST(test_notification_icon_scaling_notconfigured); + RUN_TEST(test_notification_icon_scaling_notneeded); // TEST notification_format_message struct notification *a = notification_create();