diff --git a/plugins/notify/NormalNotification.vala b/plugins/notify/NormalNotification.vala index 475a0a49..8e360f08 100644 --- a/plugins/notify/NormalNotification.vala +++ b/plugins/notify/NormalNotification.vala @@ -167,9 +167,11 @@ namespace Gala.Plugins.Notify public string summary { get; construct set; } public string body { get; construct set; } public uint32 sender_pid { get; construct; } - public string[] notification_actions { get; construct; } + public string[] notification_actions { get; construct set; } public Screen screen { get; construct; } + public signal void default_action_invoked (); + Actor content_container; NormalNotificationContent notification_content; NormalNotificationContent? old_notification_content = null; @@ -234,6 +236,7 @@ namespace Gala.Plugins.Notify }); } + notification_actions = actions; update_base (icon, expire_timeout); } @@ -270,6 +273,17 @@ namespace Gala.Plugins.Notify public override void activate () { + // we currently only support the default action, which can be triggered by clicking + // on the notification according to spec + for (var i = 0; i < notification_actions.length; i += 2) { + if (notification_actions[i] == "default") { + default_action_invoked (); + return; + } + } + + // if no default action has been set, we fallback to trying to find a window for the + // notification's sender process var window = get_window (); if (window != null) { var workspace = window.get_workspace (); diff --git a/plugins/notify/NotifyServer.vala b/plugins/notify/NotifyServer.vala index f8a47b56..4a1e6c68 100644 --- a/plugins/notify/NotifyServer.vala +++ b/plugins/notify/NotifyServer.vala @@ -91,6 +91,11 @@ namespace Gala.Plugins.Notify "body", "body-markup", "sound", + // even though we don't fully support actions, we still want to receive the default + // action. Well written applications will check if the actions capability is available + // before settings a default action, so we have to specify it here. Also, not displaying + // certain actions even though requested is allowed according to spec, so we should be fine + "actions", "x-canonical-private-synchronous", "x-canonical-private-icon-only" }; @@ -146,7 +151,7 @@ namespace Gala.Plugins.Notify var confirmation = hints.contains ("x-canonical-private-synchronous"); var progress = confirmation && hints.contains ("value"); -#if 0 // enable to debug notifications +#if true // enable to debug notifications print ("Notification from '%s', replaces: %u\n" + "\tapp icon: '%s'\n\tsummary: '%s'\n\tbody: '%s'\n\tn actions: %u\n\texpire: %i\n\tHints:\n", app_name, replaces_id, app_icon, summary, body, actions.length); @@ -154,6 +159,11 @@ namespace Gala.Plugins.Notify print ("\t\t%s => %s\n", key, val.is_of_type (VariantType.STRING) ? val.get_string () : "<" + val.get_type ().dup_string () + ">"); }); + print ("\tActions: "); + foreach (var action in actions) { + print ("%s, ", action); + } + print ("\n"); #endif uint32 pid = 0; @@ -204,9 +214,11 @@ namespace Gala.Plugins.Notify notification = new ConfirmationNotification (id, pixbuf, icon_only, progress ? hints.@get ("value").get_int32 () : -1, hints.@get ("x-canonical-private-synchronous").get_string ()); - else + else { notification = new NormalNotification (stack.screen, id, summary, body, pixbuf, urgency, timeout, pid, actions); + ((NormalNotification) notification).default_action_invoked.connect (default_action_invoked); + } notification.closed.connect (notification_closed_callback); stack.show_notification (notification); @@ -456,8 +468,17 @@ namespace Gala.Plugins.Notify { notification.closed.disconnect (notification_closed_callback); + var normal_notification = notification as NormalNotification; + if (normal_notification != null) + normal_notification.default_action_invoked.disconnect (default_action_invoked); + notification_closed (id, reason); } + + void default_action_invoked (Notification notification) + { + action_invoked (notification.id, "default"); + } } }