diff --git a/CHANGELOG.md b/CHANGELOG.md index fb97a72..2264f8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ ### Fixed - `new_icon` rule being ignored on notifications that had a raw icon +## Changed +- transient hints are now handled + An additional rule option (`match_transient` and `set_transient`) is added + to optionally reset the transient setting + ## 1.2.0 - 2017-07-12 ### Added diff --git a/config.def.h b/config.def.h index 605e58b..76763b9 100644 --- a/config.def.h +++ b/config.def.h @@ -91,13 +91,16 @@ keyboard_shortcut context_ks = {.str = "none", rule_t default_rules[] = { /* name can be any unique string. It is used to identify the rule in dunstrc to override it there */ - /* name, appname, summary, body, icon, category, msg_urgency, timeout, urgency, markup, history_ignore, new_icon, fg, bg, format, script */ - { "empty", NULL, NULL, NULL, NULL, NULL, -1, -1, -1, MARKUP_NULL, false, NULL, NULL, NULL, NULL, NULL}, - /* { "rule1", "notify-send", NULL, NULL, NULL, NULL, -1, -1, -1, MARKUP_NULL, false, NULL, NULL, NULL, "%s %b", NULL}, */ - /* { "rule2", "Pidgin", "*says*, NULL, NULL, NULL, -1, -1, CRITICAL, MARKUP_NULL, false, NULL, NULL, NULL, NULL, NULL}, */ - /* { "rule3", "Pidgin", "*signed on*", NULL, NULL, NULL, -1, -1, LOW, MARKUP_NULL, false, NULL, NULL, NULL, NULL, NULL}, */ - /* { "rule4", "Pidgin", "*signed off*", NULL, NULL, NULL, -1, -1, LOW, MARKUP_NULL, false, NULL, NULL, NULL, NULL, NULL}, */ - /* { "rule5", NULL, "*foobar*", NULL, NULL, NULL, -1, -1, -1, MARKUP_NULL, false, NULL, NULL, "#00FF00", NULL, NULL}, */ + /* name, appname, summary, body, icon, category, msg_urgency, timeout, urgency, markup, history_ignore, match_transient, set_transient, new_icon, fg, bg, format, script */ + { "empty", NULL, NULL, NULL, NULL, NULL, -1, -1, -1, MARKUP_NULL, -1, -1, -1, NULL, NULL, NULL, NULL, NULL}, + /* ignore transient hints in history by default */ + { "ignore_transient_in_history", + NULL, NULL, NULL, NULL, NULL, -1, -1, -1, MARKUP_NULL, 1, 1, -1, NULL, NULL, NULL, NULL, NULL}, + /* { "rule1", "notify-send", NULL, NULL, NULL, NULL, -1, -1, -1, MARKUP_NULL, -1, -1, -1, NULL, NULL, NULL, "%s %b", NULL}, */ + /* { "rule2", "Pidgin", "*says*, NULL, NULL, NULL, -1, -1, CRITICAL, MARKUP_NULL, -1, -1, -1, NULL, NULL, NULL, NULL, NULL}, */ + /* { "rule3", "Pidgin", "*signed on*", NULL, NULL, NULL, -1, -1, LOW, MARKUP_NULL, -1, -1, -1, NULL, NULL, NULL, NULL, NULL}, */ + /* { "rule4", "Pidgin", "*signed off*", NULL, NULL, NULL, -1, -1, LOW, MARKUP_NULL, -1, -1, -1, NULL, NULL, NULL, NULL, NULL}, */ + /* { "rule5", NULL, "*foobar*", NULL, NULL, NULL, -1, -1, -1, MARKUP_NULL, -1, -1, -1, NULL, NULL, "#00FF00", NULL, NULL}, */ }; /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/docs/dunst.pod b/docs/dunst.pod index ee53aeb..d334ea0 100644 --- a/docs/dunst.pod +++ b/docs/dunst.pod @@ -234,6 +234,9 @@ Don't timeout notifications if user is idle longer than this value (in seconds). Set to 0 to disable. +Transient notifications will ignore this setting and timeout anyway. +Use a rule overwriting with 'set_transient = no' to disable this behavior. + =item B (default: "Monospace 8") Defines the font or font set used. Optionally set the size as a decimal number @@ -556,9 +559,10 @@ matched. =item B Notifications can be matched for any of the following attributes: appname, -summary, body, icon, category and msg_urgency 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. +summary, body, icon, category, match_transient and msg_urgency 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. To define a matching rule simply assign the specified value to the value that should be matched, for example: @@ -574,8 +578,8 @@ Shell-like globing is supported. =item B The following attributes can be overridden: timeout, urgency, foreground, -background, new_icon, format where, as with the filtering attributes, each one -corresponds to the respective notification attribute to be modified. +background, new_icon, set_transient, format where, 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 rule definition. diff --git a/dunstrc b/dunstrc index 6faedc4..3b2857f 100644 --- a/dunstrc +++ b/dunstrc @@ -80,6 +80,7 @@ # Don't remove messages, if the user is idle (no mouse or keyboard input) # for longer than idle_threshold seconds. # Set to 0 to disable. + # Transient notifications ignore this setting. idle_threshold = 120 ### Text ### diff --git a/src/dbus.c b/src/dbus.c index d681029..064c233 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -138,6 +138,7 @@ static void on_notify(GDBusConnection *connection, /* hints */ gint urgency = 1; gint progress = -1; + gboolean transient = 0; gchar *fgcolor = NULL; gchar *bgcolor = NULL; gchar *category = NULL; @@ -202,14 +203,23 @@ static void on_notify(GDBusConnection *connection, if (dict_value) raw_icon = get_raw_image_from_data_hint(dict_value); - dict_value = g_variant_lookup_value(content, "value", G_VARIANT_TYPE_INT32); - if (dict_value) { + /* Check for transient hints + * + * According to the spec, the transient hint should be boolean. + * But notify-send does not support hints of type 'boolean'. + * So let's check for int and boolean until notify-send is fixed. + */ + if((dict_value = g_variant_lookup_value(content, "transient", G_VARIANT_TYPE_BOOLEAN))) + transient = g_variant_get_boolean(dict_value); + else if((dict_value = g_variant_lookup_value(content, "transient", G_VARIANT_TYPE_UINT32))) + transient = g_variant_get_uint32(dict_value) > 0; + else if((dict_value = g_variant_lookup_value(content, "transient", G_VARIANT_TYPE_INT32))) + transient = g_variant_get_int32(dict_value) > 0; + + if((dict_value = g_variant_lookup_value(content, "value", G_VARIANT_TYPE_INT32))) progress = g_variant_get_int32(dict_value); - } else { - dict_value = g_variant_lookup_value(content, "value", G_VARIANT_TYPE_UINT32); - if (dict_value) - progress = g_variant_get_uint32(dict_value); - } + else if((dict_value = g_variant_lookup_value(content, "value", G_VARIANT_TYPE_UINT32))) + progress = g_variant_get_uint32(dict_value); } break; case 7: @@ -246,6 +256,7 @@ static void on_notify(GDBusConnection *connection, n->urgency = urgency; n->category = category; n->dbus_client = g_strdup(sender); + n->transient = transient; if (actions->count > 0) { n->actions = actions; } else { diff --git a/src/dunst.c b/src/dunst.c index b036500..a55a44e 100644 --- a/src/dunst.c +++ b/src/dunst.c @@ -69,7 +69,7 @@ void check_timeouts(void) iter = iter->next; /* don't timeout when user is idle */ - if (x_is_idle()) { + if (x_is_idle() && !n->transient) { n->start = time(NULL); continue; } diff --git a/src/notification.c b/src/notification.c index 3cb6b85..621f7d7 100644 --- a/src/notification.c +++ b/src/notification.c @@ -41,6 +41,7 @@ void notification_print(notification *n) printf("\tcategory: %s\n", n->category); printf("\ttimeout: %d\n", n->timeout); printf("\turgency: %d\n", n->urgency); + printf("\ttransient: %d\n", n->transient); printf("\tformatted: '%s'\n", n->msg); printf("\tfg: %s\n", n->color_strings[ColFG]); printf("\tbg: %s\n", n->color_strings[ColBG]); diff --git a/src/notification.h b/src/notification.h index 8297e07..b653575 100644 --- a/src/notification.h +++ b/src/notification.h @@ -53,6 +53,7 @@ typedef struct _notification { int displayed_height; const char *color_strings[3]; bool first_render; + bool transient; int progress; /* percentage + 1, 0 to hide */ int line_count; diff --git a/src/rules.c b/src/rules.c index d1166f9..ebaae8d 100644 --- a/src/rules.c +++ b/src/rules.c @@ -18,6 +18,8 @@ void rule_apply(rule_t *r, notification *n) n->urgency = r->urgency; if (r->history_ignore != -1) n->history_ignore = r->history_ignore; + if (r->set_transient != -1) + n->transient = r->set_transient; if (r->markup != MARKUP_NULL) n->markup = r->markup; if (r->new_icon) { @@ -66,6 +68,8 @@ void rule_init(rule_t *r) 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->format = NULL; @@ -81,6 +85,7 @@ bool rule_matches_notification(rule_t *r, notification *n) && (!r->body || !fnmatch(r->body, n->body, 0)) && (!r->icon || !fnmatch(r->icon, n->icon, 0)) && (!r->category || !fnmatch(r->category, n->category, 0)) + && (r->match_transient == -1 || (r->match_transient == n->transient)) && (r->msg_urgency == -1 || r->msg_urgency == n->urgency)); } /* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/src/rules.h b/src/rules.h index 47dd54b..b692b98 100644 --- a/src/rules.h +++ b/src/rules.h @@ -23,6 +23,8 @@ typedef struct _rule_t { int urgency; enum markup_mode markup; int history_ignore; + int match_transient; + int set_transient; char *new_icon; char *fg; char *bg; diff --git a/src/settings.c b/src/settings.c index 00b7e8a..1e7ae5e 100644 --- a/src/settings.c +++ b/src/settings.c @@ -636,6 +636,8 @@ void load_settings(char *cmdline_config_path) r->format = ini_get_string(cur_section, "format", r->format); r->new_icon = ini_get_string(cur_section, "new_icon", r->new_icon); 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->script = ini_get_path(cur_section, "script", NULL); }