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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
namespace AstalTray {
[DBus (name="org.kde.StatusNotifierWatcher")]
internal interface IWatcher : Object {
public abstract string[] RegisteredStatusNotifierItems { owned get; }
public abstract int ProtocolVersion { 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();
}
/**
* Get the singleton instance of [[email protected]]
*/
public Tray get_default() {
return Tray.get_default();
}
public class Tray : Object {
private static Tray? instance;
/**
* Get the singleton instance of [[email protected]]
*/
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);
/**
* List of currently registered tray items
*/
public List<weak TrayItem> items { owned get { return _items.get_values(); }}
/**
* emitted when a new tray item was added.
*/
public signal void item_added(string item_id) {
notify_property("items");
}
/**
* emitted when a tray item was removed.
*/
public signal void item_removed(string item_id) {
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);
}
/**
* gets the TrayItem with the given item-id.
*/
public TrayItem get_item(string item_id) {
return _items.get(item_id);
}
}
}
|