From 53ad430b489153e00bd96a9333d5db47f264f341 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Wed, 23 Jan 2019 16:11:22 +0100 Subject: [PATCH 1/5] Compose rule matching function more readable --- src/rules.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/rules.c b/src/rules.c index 9fd9ce6..b27419a 100644 --- a/src/rules.c +++ b/src/rules.c @@ -91,18 +91,23 @@ void rule_init(struct rule *r) r->set_stack_tag = NULL; } +static inline bool rule_field_matches_string(const char *value, const char *pattern) +{ + return !pattern || (value && !fnmatch(pattern, value, 0)); +} + /* * Check whether rule should be applied to n. */ bool rule_matches_notification(struct rule *r, struct notification *n) { - return ( (!r->appname || (n->appname && !fnmatch(r->appname, n->appname, 0))) - && (!r->summary || (n->summary && !fnmatch(r->summary, n->summary, 0))) - && (!r->body || (n->body && !fnmatch(r->body, n->body, 0))) - && (!r->icon || (n->iconname && !fnmatch(r->icon, n->iconname,0))) - && (!r->category || (n->category && !fnmatch(r->category, n->category, 0))) - && (!r->stack_tag || (n->stack_tag && !fnmatch(r->stack_tag, n->stack_tag, 0))) + return (r->msg_urgency == URG_NONE || r->msg_urgency == n->urgency) && (r->match_transient == -1 || (r->match_transient == n->transient)) - && (r->msg_urgency == URG_NONE || r->msg_urgency == n->urgency)); + && rule_field_matches_string(n->appname, r->appname) + && rule_field_matches_string(n->summary, r->summary) + && rule_field_matches_string(n->body, r->body) + && rule_field_matches_string(n->iconname, r->icon) + && rule_field_matches_string(n->category, r->category) + && rule_field_matches_string(n->stack_tag, r->stack_tag); } /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ From 3828cca699c708c7cc386d6434d196e42057dcb8 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Wed, 23 Jan 2019 16:17:32 +0100 Subject: [PATCH 2/5] Introduce rule_new --- src/rules.c | 22 +++++----------------- src/rules.h | 8 +++++++- src/settings.c | 3 +-- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/rules.c b/src/rules.c index b27419a..fe9675d 100644 --- a/src/rules.c +++ b/src/rules.c @@ -63,32 +63,20 @@ void rule_apply_all(struct notification *n) } } -/* - * Initialize rule with default values. - */ -void rule_init(struct rule *r) +struct rule *rule_new(void) { - r->name = NULL; - r->appname = NULL; - r->summary = NULL; - r->body = NULL; - r->icon = NULL; - r->category = NULL; - r->stack_tag = NULL; + struct rule *r = g_malloc0(sizeof(struct rule)); + r->msg_urgency = URG_NONE; r->timeout = -1; r->urgency = URG_NONE; r->fullscreen = FS_NULL; r->markup = MARKUP_NULL; - r->new_icon = NULL; r->history_ignore = false; r->match_transient = -1; r->set_transient = -1; - r->fg = NULL; - r->bg = NULL; - r->fc = NULL; - r->format = NULL; - r->set_stack_tag = NULL; + + return r; } static inline bool rule_field_matches_string(const char *value, const char *pattern) diff --git a/src/rules.h b/src/rules.h index df45f5d..83f7b61 100644 --- a/src/rules.h +++ b/src/rules.h @@ -38,7 +38,13 @@ struct rule { extern GSList *rules; -void rule_init(struct rule *r); +/** + * Allocate a new rule. The rule is fully initialised. + * + * @returns A new initialised rule. + */ +struct rule *rule_new(void); + void rule_apply(struct rule *r, struct notification *n); void rule_apply_all(struct notification *n); bool rule_matches_notification(struct rule *r, struct notification *n); diff --git a/src/settings.c b/src/settings.c index 2f6a7b5..fb70a36 100644 --- a/src/settings.c +++ b/src/settings.c @@ -688,8 +688,7 @@ void load_settings(char *cmdline_config_path) } if (!r) { - r = g_malloc(sizeof(struct rule)); - rule_init(r); + r = rule_new(); rules = g_slist_insert(rules, r, -1); } From 1e82c761c9b8c340be4cba74c5ed59bf0413aa54 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Wed, 23 Jan 2019 16:41:07 +0100 Subject: [PATCH 3/5] Add support for desktop-entry hints --- CHANGELOG.md | 1 + src/dbus.c | 5 +++++ src/notification.c | 2 ++ src/notification.h | 1 + src/rules.c | 1 + src/rules.h | 1 + src/settings.c | 1 + test/dbus.c | 34 ++++++++++++++++++++++++++++++++++ 8 files changed, 46 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15e555e..ba5abba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added +- Introduce new desktop-entry filter (#470) - Remove libxdg-basedir dependency (GLib's function is used instead) - `fullscreen` rule to hide notifications when a fullscreen window is active - When new notifications arrive, but display is full, important notifications don't diff --git a/src/dbus.c b/src/dbus.c index 0b5ea57..e4f098e 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -227,6 +227,11 @@ static struct notification *dbus_message_to_notification(const gchar *sender, GV g_variant_unref(dict_value); } + if ((dict_value = g_variant_lookup_value(hints, "desktop-entry", G_VARIANT_TYPE_STRING))) { + n->desktop_entry = g_variant_dup_string(dict_value, NULL); + g_variant_unref(dict_value); + } + if ((dict_value = g_variant_lookup_value(hints, "image-path", G_VARIANT_TYPE_STRING))) { g_free(n->iconname); n->iconname = g_variant_dup_string(dict_value, NULL); diff --git a/src/notification.c b/src/notification.c index f6e94f9..f1cc14d 100644 --- a/src/notification.c +++ b/src/notification.c @@ -56,6 +56,7 @@ void notification_print(const struct notification *n) printf("\ticon: '%s'\n", n->iconname); printf("\traw_icon set: %s\n", (n->icon_id && !STR_EQ(n->iconname, n->icon_id)) ? "true" : "false"); printf("\ticon_id: '%s'\n", n->icon_id); + printf("\tdesktop_entry: '%s'\n", n->desktop_entry ? n->desktop_entry : ""); printf("\tcategory: %s\n", n->category); printf("\ttimeout: %ld\n", n->timeout/1000); printf("\turgency: %s\n", notification_urgency_to_string(n->urgency)); @@ -225,6 +226,7 @@ void notification_unref(struct notification *n) g_free(n->colors.bg); g_free(n->colors.frame); g_free(n->stack_tag); + g_free(n->desktop_entry); g_hash_table_unref(n->actions); diff --git a/src/notification.h b/src/notification.h index f02f3b0..ad63d0b 100644 --- a/src/notification.h +++ b/src/notification.h @@ -45,6 +45,7 @@ struct notification { char *summary; char *body; char *category; + char *desktop_entry; /**< The desktop entry hint sent via every GApplication */ enum urgency urgency; GdkPixbuf *icon; /**< The raw cached icon data used to draw */ diff --git a/src/rules.c b/src/rules.c index fe9675d..10b0995 100644 --- a/src/rules.c +++ b/src/rules.c @@ -92,6 +92,7 @@ bool rule_matches_notification(struct rule *r, struct notification *n) return (r->msg_urgency == URG_NONE || r->msg_urgency == n->urgency) && (r->match_transient == -1 || (r->match_transient == n->transient)) && rule_field_matches_string(n->appname, r->appname) + && rule_field_matches_string(n->desktop_entry, r->desktop_entry) && rule_field_matches_string(n->summary, r->summary) && rule_field_matches_string(n->body, r->body) && rule_field_matches_string(n->iconname, r->icon) diff --git a/src/rules.h b/src/rules.h index 83f7b61..69e63a1 100644 --- a/src/rules.h +++ b/src/rules.h @@ -17,6 +17,7 @@ struct rule { char *icon; char *category; char *stack_tag; + char *desktop_entry; int msg_urgency; /* actions */ diff --git a/src/settings.c b/src/settings.c index fb70a36..9245b5f 100644 --- a/src/settings.c +++ b/src/settings.c @@ -724,6 +724,7 @@ void load_settings(char *cmdline_config_path) r->history_ignore = ini_get_bool(cur_section, "history_ignore", r->history_ignore); r->match_transient = ini_get_bool(cur_section, "match_transient", r->match_transient); r->set_transient = ini_get_bool(cur_section, "set_transient", r->set_transient); + r->desktop_entry = ini_get_string(cur_section, "desktop_entry", r->desktop_entry); { char *c = ini_get_string( cur_section, diff --git a/test/dbus.c b/test/dbus.c index 066a0d6..4987891 100644 --- a/test/dbus.c +++ b/test/dbus.c @@ -551,6 +551,39 @@ TEST test_hint_category(void) PASS(); } +TEST test_hint_desktop_entry(void) +{ + struct notification *n; + struct dbus_notification *n_dbus; + const char *desktop_entry = "org.dunst-project.dunst"; + + gsize len = queues_length_waiting(); + + n_dbus = dbus_notification_new(); + n_dbus->app_name = "dunstteststack"; + n_dbus->app_icon = "NONE"; + n_dbus->summary = "test_hint_desktopentry"; + n_dbus->body = "Summary of my desktop_entry"; + + g_hash_table_insert(n_dbus->hints, + g_strdup("desktop-entry"), + g_variant_ref_sink(g_variant_new_string(desktop_entry))); + + guint id; + ASSERT(dbus_notification_fire(n_dbus, &id)); + ASSERT(id != 0); + + ASSERT_EQ(queues_length_waiting(), len+1); + + n = queues_debug_find_notification_by_id(id); + + ASSERT_STR_EQ(desktop_entry, n->desktop_entry); + + dbus_notification_free(n_dbus); + + PASS(); +} + TEST test_hint_urgency(void) { static char msg[50]; @@ -779,6 +812,7 @@ gpointer run_threaded_tests(gpointer data) RUN_TEST(test_hint_progress); RUN_TEST(test_hint_icons); RUN_TEST(test_hint_category); + RUN_TEST(test_hint_desktop_entry); RUN_TEST(test_hint_urgency); RUN_TEST(test_hint_raw_image); RUN_TEST(test_dbus_notify_colors); From 3bb6df2f1ed7b5de06b78b61215855590c440907 Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Wed, 23 Jan 2019 17:16:55 +0100 Subject: [PATCH 4/5] Format rule fields as a list --- docs/dunst.pod | 55 ++++++++++++++++++++++++++++++++++++++++++-------- dunstrc | 25 +++++++++++++++++++---- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/docs/dunst.pod b/docs/dunst.pod index 1e9a660..a11bbe5 100644 --- a/docs/dunst.pod +++ b/docs/dunst.pod @@ -610,11 +610,28 @@ matched. =item B -Notifications can be matched for any of the following attributes: appname, -summary, body, icon, category, match_transient, msg_urgency, and stack_tag where -each is the respective notification attribute to be matched and 'msg_urgency' is -the urgency of the notification, it is named so to not conflict with trying to -modify the urgency. +Notifications can be matched for any of the following attributes: + +=over 4 + +=item C + +=item C + +=item C + +=item C + +=item C + +=item C + +=item C + +=back + +C is the urgency of the notification, it is named so to not conflict +with trying to modify the urgency. To define a matching rule simply assign the specified value to the value that should be matched, for example: @@ -629,9 +646,31 @@ Shell-like globing is supported. =item B -The following attributes can be overridden: timeout, urgency, foreground, -background, frame_color, new_icon, set_transient, format, fullscreen, -set_stack_tag where, as with the filtering attributes, each one corresponds to +The following attributes can be overridden: + +=over 4 + +=item C + +=item C + +=item C + +=item C + +=item C + +=item C + +=item C + +=item C + +=item C + +=back + +As with the filtering attributes, each one corresponds to the respective notification attribute to be modified. As with filtering, to make a rule modify an attribute simply assign it in the diff --git a/dunstrc b/dunstrc index bf9fc99..2a2a772 100644 --- a/dunstrc +++ b/dunstrc @@ -297,10 +297,27 @@ # Every section that isn't one of the above is interpreted as a rules to # override settings for certain messages. -# Messages can be matched by "appname", "summary", "body", "icon", "category", -# "msg_urgency" and you can override the "timeout", "urgency", "foreground", -# "background", "frame_color", "new_icon" and "format", "fullscreen", -# "stack_tag". +# +# Messages can be matched by +# appname +# body +# category +# icon +# msg_urgency +# stack_tag +# summary +# +# and you can override the +# background +# foreground +# format +# frame_color +# fullscreen +# new_icon +# set_stack_tag +# timeout +# urgency +# # Shell-like globbing will get expanded. # # SCRIPTING From 7fff1d13c1055afedefa6695d8a6cb4f5a024c3e Mon Sep 17 00:00:00 2001 From: Benedikt Heine Date: Wed, 23 Jan 2019 17:22:41 +0100 Subject: [PATCH 5/5] Add docs for desktop-entry filter --- docs/dunst.pod | 8 +++++++- dunstrc | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/dunst.pod b/docs/dunst.pod index a11bbe5..135ac55 100644 --- a/docs/dunst.pod +++ b/docs/dunst.pod @@ -614,12 +614,14 @@ Notifications can be matched for any of the following attributes: =over 4 -=item C +=item C (discouraged, see desktop_entry) =item C =item C +=item C + =item C =item C @@ -633,6 +635,10 @@ Notifications can be matched for any of the following attributes: C is the urgency of the notification, it is named so to not conflict with trying to modify the urgency. +Instead of the appname filter, it's recommended to use the desktop_entry filter. +GLib based applications export their desktop-entry name. In comparison to the appname, +the desktop-entry won't get localized. + To define a matching rule simply assign the specified value to the value that should be matched, for example: diff --git a/dunstrc b/dunstrc index 2a2a772..8da67c3 100644 --- a/dunstrc +++ b/dunstrc @@ -299,9 +299,10 @@ # override settings for certain messages. # # Messages can be matched by -# appname +# appname (discouraged, see desktop_entry) # body # category +# desktop_entry # icon # msg_urgency # stack_tag @@ -320,6 +321,10 @@ # # Shell-like globbing will get expanded. # +# Instead of the appname filter, it's recommended to use the desktop_entry filter. +# GLib based applications export their desktop-entry name. In comparison to the appname, +# the desktop-entry won't get localized. +# # SCRIPTING # You can specify a script that gets run when the rule matches by # setting the "script" option.