@@ 13,11 13,10 @@ class ProxyIcon : Object {
item.changed.connect(property => {
switch(property) {
- case "icon-name":
- case "icon-pixmap": set_icon(); break;
case "tool-tip": set_tooltip(); break;
}
});
+ item.icon_changed.connect(set_icon);
set_icon();
icon.set_name(item.id); // MUST be called after an icon is set due to Gdk internals
@@ 11,6 11,12 @@ struct ToolTip {
string text;
}
+// StatusNotifierItem proxy
+//
+// Do not use the D-Bus signals directly, instead rely on icon_changed for icon changes
+// and the property changed signals for the rest (title, tooltip, ...).
+//
+// TODO: handle race conditions
[DBus (name = "org.kde.StatusNotifierItem")]
interface StatusNotifierItem : Object {
public const string OBJECT = "/StatusNotifierItem";
@@ 36,11 42,29 @@ interface StatusNotifierItem : Object {
}
public virtual signal void new_icon() {
- update_cache("IconName", "icon-name");
- update_cache("IconPixmap", "icon-pixmap");
+ handle_new_icon();
+ }
+
+ public virtual signal void icon_changed();
- // AppIndicator only
- update_cache("IconThemePath", "icon-theme-path");
+ // Asynchronously update icon data and then emit icon_changed if necessary
+ async void handle_new_icon() {
+ var changes = 0;
+
+ var done = 0;
+ AsyncReadyCallback handler = (obj, res) => {
+ try {
+ if (update_cache.end(res)) changes++;
+ } finally {
+ if (++done == 3) handle_new_icon.callback();
+ }
+ };
+ update_cache.begin("IconName", "icon-name", handler);
+ update_cache.begin("IconPixmap", "icon-pixmap", handler);
+ update_cache.begin("IconThemePath", "icon-theme-path", handler); // AppIndicator only
+ yield;
+
+ if (changes != 0) icon_changed();
}
public virtual signal void new_tool_tip() {
@@ 56,21 80,21 @@ interface StatusNotifierItem : Object {
// - this is simple and just works
internal abstract signal void changed(string property);
- void update_cache(string property, string name) {
+ async bool update_cache(string property, string name) throws Error {
var me = this as DBusProxy;
var par = new Variant("(ss)", me.get_interface_name(), property);
- me.call.begin("org.freedesktop.DBus.Properties.Get", par, 0, -1, null, (obj, result) => {
- try {
- Variant res, v;
- res = me.call.end(result);
- res.get("(v)", out v);
-
- if (v != me.get_cached_property(property)) {
- me.set_cached_property(property, v);
- (me as StatusNotifierItem).changed(name);
- }
- } catch (DBusError.INVALID_ARGS e) { /* Ignore properties that don't exist */ }
- });
+ try {
+ var res = yield me.call("org.freedesktop.DBus.Properties.Get", par, 0, -1, null);
+ Variant v;
+ res.get("(v)", out v);
+
+ if (v != me.get_cached_property(property)) {
+ me.set_cached_property(property, v);
+ (me as StatusNotifierItem).changed(name);
+ return true;
+ }
+ } catch (DBusError.UNKNOWN_PROPERTY e) {} catch (DBusError.INVALID_ARGS e) {}
+ return false;
}
}