Skip to content

Commit

Permalink
Added support for withdrawing notifications from the indicator
Browse files Browse the repository at this point in the history
  • Loading branch information
donadigo committed Dec 7, 2016
1 parent b3911de commit 3d12554
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 43 deletions.
16 changes: 15 additions & 1 deletion src/Indicator.vala
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ public class Indicator : Wingpanel.Indicator {

nlist.close_popover.connect (() => close ());
nlist.switch_stack.connect (on_switch_stack);
NotificationMonitor.get_instance ().received.connect (on_notification_received);

var monitor = NotificationMonitor.get_instance ();
monitor.received.connect (on_notification_received);
monitor.notification_closed.connect (on_notification_closed);

NotifySettings.get_instance ().changed[NotifySettings.DO_NOT_DISTURB_KEY].connect (() => {
not_disturb_switch.get_switch ().active = NotifySettings.get_instance ().do_not_disturb;
Expand Down Expand Up @@ -171,6 +174,17 @@ public class Indicator : Wingpanel.Indicator {
dynamic_icon.set_main_icon_name (get_display_icon_name ());
}

private void on_notification_closed (uint32 id) {
foreach (var app_entry in nlist.get_entries ()) {
foreach (var item in app_entry.app_notifications) {
if (item.notification.id == id) {
item.notification.close ();
return;
}
}
}
}

private void restore_previous_session () {
var previous_session = Session.get_instance ().get_session_notifications ();
previous_session.foreach ((notification) => {
Expand Down
5 changes: 5 additions & 0 deletions src/Services/Notification.vala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class Notification : Object {
public string desktop_id;
public AppInfo? app_info = null;

public signal void closed ();
public signal bool time_changed (TimeSpan span);

private enum Column {
Expand Down Expand Up @@ -129,6 +130,10 @@ public class Notification : Object {
return app_info != null && hints.lookup_value (X_CANONICAL_PRIVATE_KEY, null) == null;
}

public void close () {
closed ();
}

public bool run_default_action () {
if (DEFAULT_ACTION in actions && NotificationMonitor.get_instance ().notifications_iface != null) {
NotificationMonitor.get_instance ().notifications_iface.action_invoked (DEFAULT_ACTION, id);
Expand Down
91 changes: 49 additions & 42 deletions src/Services/NotificationsMonitor.vala
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@
public class NotificationMonitor : Object {
private const string NOTIFY_IFACE = "org.freedesktop.Notifications";
private const string NOTIFY_PATH = "/org/freedesktop/Notifications";
private const string MATCH_STRING = "eavesdrop='true',type='method_call',interface='org.freedesktop.Notifications',member='Notify'";
private const string METHOD_CALL_MATCH_STRING = "eavesdrop='true',type='method_call',interface='org.freedesktop.Notifications'";
private const string METHOD_RETURN_MATCH_STRING = "eavesdrop='true',type='method_return'";
private const string ERROR_MATCH_STRING = "eavesdrop='true',type='error'";
private const uint32 REASON_DISMISSED = 2;

private static NotificationMonitor? instance = null;

private DBusConnection connection;
public INotifications? notifications_iface = null;
public IDBus? dbus_iface = null;
private uint32 id_counter = 0;
private DBusMessage? awaiting_reply = null;

public signal void received (DBusMessage message, uint32 id);
public signal void notification_closed (uint32 id);

public static NotificationMonitor get_instance () {
if (instance == null) {
Expand All @@ -43,75 +44,81 @@ public class NotificationMonitor : Object {
return instance;
}

public INotifications? notifications_iface = null;

private NotificationMonitor () {
try {
connection = Bus.get_sync (BusType.SESSION);
add_filter ();
add_rule (ERROR_MATCH_STRING);
add_rule (METHOD_CALL_MATCH_STRING);
add_rule (METHOD_RETURN_MATCH_STRING);
connection.add_filter (message_filter);
} catch (Error e) {
error ("%s\n", e.message);
}

try {
notifications_iface = Bus.get_proxy_sync (BusType.SESSION, NOTIFY_IFACE, NOTIFY_PATH);
} catch (Error e) {
error ("%s\n", e.message);
}
}

private void add_filter () {
private void add_rule (string rule) {
var message = new DBusMessage.method_call ("org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"AddMatch");

var body = new Variant.parsed ("(%s,)", MATCH_STRING);
var body = new Variant.parsed ("(%s,)", rule);
message.set_body (body);

try {
notifications_iface = Bus.get_proxy_sync (BusType.SESSION, NOTIFY_IFACE, NOTIFY_PATH);
} catch (Error e) {
error ("%s\n", e.message);
}

id_counter = get_current_notification_id ();
try {
connection.send_message (message, DBusSendMessageFlags.NONE, null);
} catch (Error e) {
error ("%s\n", e.message);
}

connection.add_filter (message_filter);
}

private DBusMessage message_filter (DBusConnection con, owned DBusMessage message, bool incoming) {
if (incoming) {
if ((message.get_message_type () == DBusMessageType.METHOD_CALL) &&
(message.get_interface () == NOTIFY_IFACE) &&
(message.get_member () == "Notify")) {
uint32 replaces_id = message.get_body ().get_child_value (1).get_uint32 ();
uint32 current_id = replaces_id;

if (replaces_id == 0) {
id_counter++;
current_id = id_counter;
if (incoming && message.get_interface () == NOTIFY_IFACE && message.get_message_type () == DBusMessageType.METHOD_CALL) {
if (message.get_member () == "Notify") {
try {
awaiting_reply = message.copy ();
} catch (Error e) {
warning (e.message);
}

} else if (message.get_member () == "CloseNotification") {
uint32 id = message.get_body ().get_child_value (0).get_uint32 ();
Idle.add (() => {
this.received (message, current_id);
message = null;
notification_closed (id);
return false;
});
}

message = null;
return null;
} else if (awaiting_reply != null && awaiting_reply.get_serial () == message.get_reply_serial ()) {
if (message.get_message_type () == DBusMessageType.METHOD_RETURN) {
uint32 id = message.get_body ().get_child_value (0).get_uint32 ();

try {
var copy = awaiting_reply.copy ();
Idle.add (() => {
received (copy, id);
return false;
});
} catch (Error e) {
warning (e.message);
}

return null;

awaiting_reply = null;
} else if (message.get_message_type () == DBusMessageType.ERROR) {
awaiting_reply = null;
}
}

return message;
}

/* Check what's the current notification id */
private uint32 get_current_notification_id () {
var hints = new HashTable<string, Variant> (str_hash, str_equal);
hints.insert ("suppress-sound", new Variant.boolean (true));
string[] actions = {};
try {
return notifications_iface.notify ("", 0, "", "", "", actions, hints, 1);
} catch (Error e) {
error ("%s\n", e.message);
}
}
}
4 changes: 4 additions & 0 deletions src/Widgets/NotificationEntry.vala
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public class NotificationEntry : Gtk.ListBoxRow {
return active;
});

notification.closed.connect (() => {
clear ();
});

hexpand = true;

var grid = new Gtk.Grid ();
Expand Down
4 changes: 4 additions & 0 deletions src/Widgets/NotificationsList.vala
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public class NotificationsList : Gtk.ListBox {
}


public unowned List<AppEntry> get_entries () {
return app_entries;
}

public uint get_entries_length () {
return app_entries.length ();
}
Expand Down

0 comments on commit 3d12554

Please sign in to comment.