1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
[DBus (name = "org.freedesktop.Notifications")]
internal interface AstalNotifd.IDaemon : DBusProxy {
public abstract bool ignore_timeout { get; set; }
public abstract bool dont_disturb { get; set; }
public abstract uint[] notification_ids() throws DBusError, IOError;
public abstract string get_notification_json(uint id) throws DBusError, IOError;
public signal void notified(uint id, bool replaced);
public signal void resolved(uint id, ClosedReason reason);
public signal void prop_changed(string prop);
public abstract void emit_resolved(uint id, ClosedReason reason);
public abstract void emit_action_invoked(uint id, string action);
}
internal class AstalNotifd.DaemonProxy : Object {
private HashTable<uint, Notification> notifs =
new HashTable<uint, Notification>((i) => i, (a, b) => a == b);
public List<weak Notification> notifications {
owned get { return notifs.get_values(); }
}
public bool ignore_timeout {
get { return proxy.ignore_timeout; }
set { proxy.ignore_timeout = value; }
}
public bool dont_disturb {
get { return proxy.dont_disturb; }
set { proxy.dont_disturb = value; }
}
public Notification get_notification(uint id) {
return notifs.get(id);
}
public signal void notified(uint id, bool replaced);
public signal void resolved(uint id, ClosedReason reason);
private IDaemon proxy;
private List<ulong> ids = new List<ulong>();
public void stop() {
if (ids.length() > 0) {
foreach (var id in ids)
SignalHandler.disconnect(proxy, id);
}
}
public bool start() {
try {
var bus = Bus.get_sync(BusType.SESSION, null);
var variant = bus.call_sync(
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications",
"GetServerInformation",
null,
null,
DBusCallFlags.NONE,
-1,
null);
var name = variant.get_child_value(0).get_string();
var vendor = variant.get_child_value(1).get_string();
var version = variant.get_child_value(2).get_string();
var running = name == Daemon.name
&& vendor == Daemon.vendor
&& version == Daemon.version;
if (running) {
setup_proxy();
return true;
} else {
critical("cannot get proxy: %s is already running", name);
}
} catch (Error err) {
critical("cannot get proxy: %s", err.message);
}
return false;
}
private void setup_proxy() throws Error {
proxy = Bus.get_proxy_sync(
BusType.SESSION,
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications"
);
foreach (var id in proxy.notification_ids())
add_notification(id);
ids.append(proxy.prop_changed.connect((prop) => {
if (prop == "ignore-timeout" || prop == "dont-disturb")
notify_property(prop);
}));
ids.append(proxy.notified.connect((id, replaced) => {
add_notification(id);
notified(id, replaced);
notify_property("notifications");
}));
ids.append(proxy.resolved.connect((id, reason) => {
notifs.remove(id);
resolved(id, reason);
notify_property("notifications");
}));
}
private void add_notification(uint id) {
try {
var n = Notification.from_json_string(proxy.get_notification_json(id));
proxy.resolved.connect((id, reason) => n.resolved(reason));
n.dismissed.connect(() => proxy.emit_resolved(id, ClosedReason.DISMISSED_BY_USER));
n.invoked.connect((action) => proxy.emit_action_invoked(id, action));
notifs.set(id, n);
} catch (Error err) {
critical(err.message);
}
}
}
|