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
126
127
128
129
130
131
132
133
134
135
|
namespace AstalTray {
[DBus (name="org.kde.StatusNotifierWatcher")]
internal interface IWatcher : Object {
public abstract string[] RegisteredStatusNotifierItems { owned get; }
public abstract int ProtocolVersion { owned get; }
public abstract void RegisterStatusNotifierItem(string service, BusName sender) throws DBusError, IOError;
public abstract void RegisterStatusNotifierHost(string service) throws DBusError, IOError;
public signal void StatusNotifierItemRegistered(string service);
public signal void StatusNotifierItemUnregistered(string service);
public signal void StatusNotifierHostRegistered();
public signal void StatusNotifierHostUnregistered();
}
public Tray get_default() {
return Tray.get_default();
}
public class Tray : Object {
private static Tray? instance;
public static unowned Tray get_default() {
if (instance == null)
instance = new Tray();
return instance;
}
private StatusNotifierWatcher watcher;
private IWatcher proxy;
private HashTable<string, TrayItem> _items =
new HashTable<string, TrayItem>(str_hash, str_equal);
public List<weak TrayItem> items { owned get { return _items.get_values(); }}
public signal void item_added(string service) {
notify_property("items");
}
public signal void item_removed(string service) {
notify_property("items");
}
construct {
try {
Bus.own_name(
BusType.SESSION,
"org.kde.StatusNotifierWatcher",
BusNameOwnerFlags.NONE,
start_watcher,
() => {
if (proxy != null) {
proxy = null;
}
},
start_host
);
} catch (Error err) {
critical(err.message);
}
}
private void start_watcher(DBusConnection conn) {
try {
watcher = new StatusNotifierWatcher();
conn.register_object("/StatusNotifierWatcher", watcher);
watcher.StatusNotifierItemRegistered.connect(on_item_register);
watcher.StatusNotifierItemUnregistered.connect(on_item_unregister);
} catch (Error err) {
critical(err.message);
}
}
private void start_host() {
if (proxy != null)
return;
try {
proxy = Bus.get_proxy_sync(BusType.SESSION,
"org.kde.StatusNotifierWatcher",
"/StatusNotifierWatcher");
proxy.StatusNotifierItemRegistered.connect(on_item_register);
proxy.StatusNotifierItemUnregistered.connect(on_item_unregister);
proxy.notify["g-name-owner"].connect(() => {
_items.foreach((service, _) => {
item_removed(service);
});
_items.remove_all();
if(proxy != null) {
foreach (string item in proxy.RegisteredStatusNotifierItems) {
on_item_register(item);
}
} else {
foreach (string item in watcher.RegisteredStatusNotifierItems) {
on_item_register(item);
}
}
});
foreach (string item in proxy.RegisteredStatusNotifierItems) {
on_item_register(item);
}
} catch (Error err) {
critical("cannot get proxy: %s", err.message);
}
}
private void on_item_register(string service) {
if (_items.contains(service))
return;
var parts = service.split("/", 2);
TrayItem item = new TrayItem(parts[0], "/" + parts[1]);
item.ready.connect(() => {
_items.set(service, item);
item_added(service);
});
}
private void on_item_unregister(string service) {
_items.remove(service);
item_removed(service);
}
public TrayItem get_item(string service) {
return _items.get(service);
}
}
}
|