Merge pull request #552 from Gravemind/x-canonical-private-synchronous
Implement x-canonical-private-synchronous hint
This commit is contained in:
		
						commit
						27c6a1682d
					
				| @ -611,9 +611,9 @@ matched. | ||||
| =item B<filtering> | ||||
| 
 | ||||
| Notifications can be matched for any of the following attributes: appname, | ||||
| 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 | ||||
| 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. | ||||
| 
 | ||||
| To define a matching rule simply assign the specified value to the value that | ||||
| @ -630,9 +630,9 @@ Shell-like globing is supported. | ||||
| =item B<modifying> | ||||
| 
 | ||||
| The following attributes can be overridden: timeout, urgency, foreground, | ||||
| background, frame_color, new_icon, set_transient, format, fullscreen where, | ||||
| as with the filtering attributes, each one corresponds to the respective | ||||
| notification attribute to be modified. | ||||
| background, frame_color, new_icon, set_transient, format, fullscreen, | ||||
| set_stack_tag 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. | ||||
| @ -640,6 +640,11 @@ rule definition. | ||||
| If the format is set to an empty string, the notification will not be | ||||
| suppressed. | ||||
| 
 | ||||
| Notifications with the same non-empty stack_tag value will be stacked | ||||
| together. The default stack_stag value is set from the string hints | ||||
| "synchronous", "private-synchronous", "x-canonical-private-synchronous", and | ||||
| "x-dunst-stack-tag". | ||||
| 
 | ||||
| =back | ||||
| 
 | ||||
| =head2 SCRIPTING | ||||
|  | ||||
							
								
								
									
										11
									
								
								dunstrc
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								dunstrc
									
									
									
									
									
								
							| @ -147,10 +147,10 @@ | ||||
|     # Ignore newlines '\n' in notifications. | ||||
|     ignore_newline = no | ||||
| 
 | ||||
|     # Merge multiple notifications with the same content | ||||
|     # Stack together notifications with the same content | ||||
|     stack_duplicates = true | ||||
| 
 | ||||
|     # Hide the count of merged notifications with the same content | ||||
|     # Hide the count of stacked notifications with the same content | ||||
|     hide_duplicate_count = false | ||||
| 
 | ||||
|     # Display indicators for URLs (U) and actions (A). | ||||
| @ -299,7 +299,8 @@ | ||||
| # 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". | ||||
| # "background", "frame_color", "new_icon" and "format", "fullscreen", | ||||
| # "stack_tag". | ||||
| # Shell-like globbing will get expanded. | ||||
| # | ||||
| # SCRIPTING | ||||
| @ -365,4 +366,8 @@ | ||||
| #    summary = *twitter.com* | ||||
| #    urgency = normal | ||||
| # | ||||
| #[stack-volumes] | ||||
| #    appname = "some_volume_notifiers" | ||||
| #    set_stack_tag = "volume" | ||||
| # | ||||
| # vim: ft=cfg | ||||
|  | ||||
							
								
								
									
										24
									
								
								src/dbus.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/dbus.c
									
									
									
									
									
								
							| @ -65,6 +65,13 @@ static const char *introspection_xml = | ||||
|     "   </interface>" | ||||
|     "</node>"; | ||||
| 
 | ||||
| static const char *stack_tag_hints[] = { | ||||
|         "synchronous", | ||||
|         "private-synchronous", | ||||
|         "x-canonical-private-synchronous", | ||||
|         "x-dunst-stack-tag" | ||||
| }; | ||||
| 
 | ||||
| static void on_get_capabilities(GDBusConnection *connection, | ||||
|                                 const gchar *sender, | ||||
|                                 const GVariant *parameters, | ||||
| @ -120,6 +127,9 @@ static void on_get_capabilities(GDBusConnection *connection, | ||||
|         g_variant_builder_add(builder, "s", "body"); | ||||
|         g_variant_builder_add(builder, "s", "body-hyperlinks"); | ||||
| 
 | ||||
|         for (int i = 0; i < sizeof(stack_tag_hints)/sizeof(*stack_tag_hints); ++i) | ||||
|                 g_variant_builder_add(builder, "s", stack_tag_hints[i]); | ||||
| 
 | ||||
|         if (settings.markup != MARKUP_NO) | ||||
|                 g_variant_builder_add(builder, "s", "body-markup"); | ||||
| 
 | ||||
| @ -245,6 +255,20 @@ static struct notification *dbus_message_to_notification(const gchar *sender, GV | ||||
|                                                 n->progress = g_variant_get_uint32(dict_value); | ||||
|                                                 g_variant_unref(dict_value); | ||||
|                                         } | ||||
| 
 | ||||
|                                         /* Check for hints that define the stack_tag
 | ||||
|                                          * | ||||
|                                          * Only accept to first one we find. | ||||
|                                          */ | ||||
|                                         for (int i = 0; i < sizeof(stack_tag_hints)/sizeof(*stack_tag_hints); ++i) { | ||||
|                                                 dict_value = g_variant_lookup_value(content, stack_tag_hints[i], G_VARIANT_TYPE_STRING); | ||||
|                                                 if (dict_value) { | ||||
|                                                         n->stack_tag = g_variant_dup_string(dict_value, NULL); | ||||
|                                                         g_variant_unref(dict_value); | ||||
|                                                         break; | ||||
|                                                 } | ||||
|                                         } | ||||
| 
 | ||||
|                                 } | ||||
|                                 break; | ||||
|                         case 7: | ||||
|  | ||||
| @ -66,6 +66,7 @@ void notification_print(const struct notification *n) | ||||
|         printf("\tframe: %s\n", n->colors[ColFrame]); | ||||
|         printf("\tfullscreen: %s\n", enum_to_string_fullscreen(n->fullscreen)); | ||||
|         printf("\tprogress: %d\n", n->progress); | ||||
|         printf("\tstack_tag: %s\n", (n->stack_tag ? n->stack_tag : "")); | ||||
|         printf("\tid: %d\n", n->id); | ||||
|         if (n->urls) { | ||||
|                 char *urls = string_replace_all("\n", "\t\t\n", g_strdup(n->urls)); | ||||
| @ -251,6 +252,7 @@ void notification_unref(struct notification *n) | ||||
|         g_free(n->colors[ColFG]); | ||||
|         g_free(n->colors[ColBG]); | ||||
|         g_free(n->colors[ColFrame]); | ||||
|         g_free(n->stack_tag); | ||||
| 
 | ||||
|         actions_free(n->actions); | ||||
|         rawimage_free(n->raw_icon); | ||||
|  | ||||
| @ -70,6 +70,8 @@ struct notification { | ||||
|         const char *script; | ||||
|         char *colors[3]; | ||||
| 
 | ||||
|         char *stack_tag;    /**< stack notifications by tag */ | ||||
| 
 | ||||
|         /* Hints */ | ||||
|         bool transient;     /**< timeout albeit user is idle */ | ||||
|         int progress;       /**< percentage (-1: undefined) */ | ||||
|  | ||||
							
								
								
									
										59
									
								
								src/queues.c
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								src/queues.c
									
									
									
									
									
								
							| @ -34,6 +34,7 @@ int next_notification_id = 1; | ||||
| bool pause_displayed = false; | ||||
| 
 | ||||
| static bool queues_stack_duplicate(struct notification *n); | ||||
| static bool queues_stack_by_tag(struct notification *n); | ||||
| 
 | ||||
| /* see queues.h */ | ||||
| void queues_init(void) | ||||
| @ -123,6 +124,7 @@ static bool queues_notification_is_ready(const struct notification *n, bool full | ||||
| /* see queues.h */ | ||||
| int queues_notification_insert(struct notification *n) | ||||
| { | ||||
|         bool inserted = false; | ||||
| 
 | ||||
|         /* do not display the message, if the message is empty */ | ||||
|         if (STR_EMPTY(n->msg)) { | ||||
| @ -146,14 +148,17 @@ int queues_notification_insert(struct notification *n) | ||||
|                 return 0; | ||||
|         } | ||||
| 
 | ||||
|         if (n->id == 0) { | ||||
|         if (!inserted && n->id != 0 && queues_notification_replace_id(n)) | ||||
|                 inserted = true; | ||||
|         else | ||||
|                 n->id = ++next_notification_id; | ||||
|                 if (!settings.stack_duplicates || !queues_stack_duplicate(n)) | ||||
| 
 | ||||
|         if (!inserted && STR_FULL(n->stack_tag) && queues_stack_by_tag(n)) | ||||
|                 inserted = true; | ||||
|         if (!inserted && settings.stack_duplicates && queues_stack_duplicate(n)) | ||||
|                 inserted = true; | ||||
|         if (!inserted) | ||||
|                 g_queue_insert_sorted(waiting, n, notification_cmp_data, NULL); | ||||
|         } else { | ||||
|                 if (!queues_notification_replace_id(n)) | ||||
|                         g_queue_insert_sorted(waiting, n, notification_cmp_data, NULL); | ||||
|         } | ||||
| 
 | ||||
|         if (settings.print_notifications) | ||||
|                 notification_print(n); | ||||
| @ -170,7 +175,7 @@ int queues_notification_insert(struct notification *n) | ||||
| static bool queues_stack_duplicate(struct notification *n) | ||||
| { | ||||
|         GQueue *allqueues[] = { displayed, waiting }; | ||||
|         for (int i = 0; i < sizeof(allqueues)/sizeof(GList*); i++) { | ||||
|         for (int i = 0; i < sizeof(allqueues)/sizeof(GQueue*); i++) { | ||||
|                 for (GList *iter = g_queue_peek_head_link(allqueues[i]); iter; | ||||
|                      iter = iter->next) { | ||||
|                         struct notification *orig = iter->data; | ||||
| @ -188,7 +193,7 @@ static bool queues_stack_duplicate(struct notification *n) | ||||
|                                 n->dup_count = orig->dup_count; | ||||
|                                 signal_notification_closed(orig, 1); | ||||
| 
 | ||||
|                                 if ( allqueues[i] == displayed ) | ||||
|                                 if (allqueues[i] == displayed) | ||||
|                                         n->start = time_monotonic_now(); | ||||
| 
 | ||||
|                                 notification_unref(orig); | ||||
| @ -200,11 +205,43 @@ static bool queues_stack_duplicate(struct notification *n) | ||||
|         return false; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Replaces the first notification of the same stack_tag | ||||
|  * | ||||
|  * @return true, if notification got stacked | ||||
|  * @return false, if notification did not get stacked | ||||
|  */ | ||||
| static bool queues_stack_by_tag(struct notification *new) | ||||
| { | ||||
|         GQueue *allqueues[] = { displayed, waiting }; | ||||
|         for (int i = 0; i < sizeof(allqueues)/sizeof(GQueue*); i++) { | ||||
|                 for (GList *iter = g_queue_peek_head_link(allqueues[i]); iter; | ||||
|                             iter = iter->next) { | ||||
|                         struct notification *old = iter->data; | ||||
|                         if (STR_FULL(old->stack_tag) && STR_EQ(old->stack_tag, new->stack_tag)) { | ||||
|                                 iter->data = new; | ||||
|                                 new->dup_count = old->dup_count; | ||||
| 
 | ||||
|                                 signal_notification_closed(old, 1); | ||||
| 
 | ||||
|                                 if (allqueues[i] == displayed) { | ||||
|                                         new->start = time_monotonic_now(); | ||||
|                                         notification_run_script(new); | ||||
|                                 } | ||||
| 
 | ||||
|                                 notification_unref(old); | ||||
|                                 return true; | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
|         return false; | ||||
| } | ||||
| 
 | ||||
| /* see queues.h */ | ||||
| bool queues_notification_replace_id(struct notification *new) | ||||
| { | ||||
|         GQueue *allqueues[] = { displayed, waiting }; | ||||
|         for (int i = 0; i < sizeof(allqueues)/sizeof(GList*); i++) { | ||||
|         for (int i = 0; i < sizeof(allqueues)/sizeof(GQueue*); i++) { | ||||
|                 for (GList *iter = g_queue_peek_head_link(allqueues[i]); | ||||
|                             iter; | ||||
|                             iter = iter->next) { | ||||
| @ -213,7 +250,7 @@ bool queues_notification_replace_id(struct notification *new) | ||||
|                                 iter->data = new; | ||||
|                                 new->dup_count = old->dup_count; | ||||
| 
 | ||||
|                                 if ( allqueues[i] == displayed ) { | ||||
|                                 if (allqueues[i] == displayed) { | ||||
|                                         new->start = time_monotonic_now(); | ||||
|                                         notification_run_script(new); | ||||
|                                 } | ||||
| @ -232,7 +269,7 @@ void queues_notification_close_id(int id, enum reason reason) | ||||
|         struct notification *target = NULL; | ||||
| 
 | ||||
|         GQueue *allqueues[] = { displayed, waiting }; | ||||
|         for (int i = 0; i < sizeof(allqueues)/sizeof(GList*); i++) { | ||||
|         for (int i = 0; i < sizeof(allqueues)/sizeof(GQueue*); i++) { | ||||
|                 for (GList *iter = g_queue_peek_head_link(allqueues[i]); iter; | ||||
|                      iter = iter->next) { | ||||
|                         struct notification *n = iter->data; | ||||
|  | ||||
| @ -47,6 +47,10 @@ void rule_apply(struct rule *r, struct notification *n) | ||||
|                 n->format = r->format; | ||||
|         if (r->script) | ||||
|                 n->script = r->script; | ||||
|         if (r->set_stack_tag) { | ||||
|                 g_free(n->stack_tag); | ||||
|                 n->stack_tag = g_strdup(r->set_stack_tag); | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -73,6 +77,7 @@ void rule_init(struct rule *r) | ||||
|         r->body = NULL; | ||||
|         r->icon = NULL; | ||||
|         r->category = NULL; | ||||
|         r->stack_tag = NULL; | ||||
|         r->msg_urgency = URG_NONE; | ||||
|         r->timeout = -1; | ||||
|         r->urgency = URG_NONE; | ||||
| @ -86,6 +91,7 @@ void rule_init(struct rule *r) | ||||
|         r->bg = NULL; | ||||
|         r->fc = NULL; | ||||
|         r->format = NULL; | ||||
|         r->set_stack_tag = NULL; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -98,6 +104,7 @@ bool rule_matches_notification(struct rule *r, struct notification *n) | ||||
|                 && (!r->body      || (n->body      && !fnmatch(r->body,      n->body, 0))) | ||||
|                 && (!r->icon      || (n->icon      && !fnmatch(r->icon,      n->icon, 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))) | ||||
|                 && (r->match_transient == -1 || (r->match_transient == n->transient)) | ||||
|                 && (r->msg_urgency == URG_NONE || r->msg_urgency == n->urgency)); | ||||
| } | ||||
|  | ||||
| @ -16,6 +16,7 @@ struct rule { | ||||
|         char *body; | ||||
|         char *icon; | ||||
|         char *category; | ||||
|         char *stack_tag; | ||||
|         int msg_urgency; | ||||
| 
 | ||||
|         /* actions */ | ||||
| @ -32,6 +33,7 @@ struct rule { | ||||
|         const char *format; | ||||
|         const char *script; | ||||
|         enum behavior_fullscreen fullscreen; | ||||
|         char *set_stack_tag; | ||||
| }; | ||||
| 
 | ||||
| extern GSList *rules; | ||||
|  | ||||
| @ -368,7 +368,7 @@ void load_settings(char *cmdline_config_path) | ||||
|         settings.hide_duplicate_count = option_get_bool( | ||||
|                 "global", | ||||
|                 "hide_duplicate_count", "-hide_duplicate_count", false, | ||||
|                 "Hide the count of merged notifications with the same content" | ||||
|                 "Hide the count of stacked notifications with the same content" | ||||
|         ); | ||||
| 
 | ||||
|         settings.sticky_history = option_get_bool( | ||||
| @ -444,7 +444,7 @@ void load_settings(char *cmdline_config_path) | ||||
|         settings.stack_duplicates = option_get_bool( | ||||
|                 "global", | ||||
|                 "stack_duplicates", "-stack_duplicates", true, | ||||
|                 "Merge multiple notifications with the same content" | ||||
|                 "Stack together notifications with the same content" | ||||
|         ); | ||||
| 
 | ||||
|         settings.startup_notification = option_get_bool( | ||||
| @ -785,6 +785,7 @@ void load_settings(char *cmdline_config_path) | ||||
|                 r->body = ini_get_string(cur_section, "body", r->body); | ||||
|                 r->icon = ini_get_string(cur_section, "icon", r->icon); | ||||
|                 r->category = ini_get_string(cur_section, "category", r->category); | ||||
|                 r->stack_tag = ini_get_string(cur_section, "stack_tag", r->stack_tag); | ||||
|                 r->timeout = ini_get_time(cur_section, "timeout", r->timeout); | ||||
| 
 | ||||
|                 { | ||||
| @ -819,6 +820,7 @@ void load_settings(char *cmdline_config_path) | ||||
|                         g_free(c); | ||||
|                 } | ||||
|                 r->script = ini_get_path(cur_section, "script", NULL); | ||||
|                 r->set_stack_tag = ini_get_string(cur_section, "set_stack_tag", r->set_stack_tag); | ||||
|         } | ||||
| 
 | ||||
| #ifndef STATIC_CONFIG | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Nikos Tsipinakis
						Nikos Tsipinakis