summaryrefslogtreecommitdiff
path: root/src/tray.vala
blob: 5bf9270ef0a750cfe16cdadb274ee022542a0a87 (plain)
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
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 class Tray : Object {

    private StatusNotifierWatcher watcher;
    private IWatcher proxy;

    private HashTable<string, TrayItem> _items;
    public List<weak TrayItem> items { owned get { return _items.get_values(); }}
    
    public signal void item_added(string service);
    public signal void item_removed(string service);

    construct {
      _items = new HashTable<string, TrayItem>(GLib.str_hash, GLib.str_equal);
      try {

      Bus.own_name(
            BusType.SESSION,
            "org.kde.StatusNotifierWatcher",
            BusNameOwnerFlags.NONE,
            start_watcher,
            () => {
              if (proxy != null) {
                //foreach (string item in proxy.RegisteredStatusNotifierItems) {
                //  on_item_unregister(item);
                //}
                proxy = null;
              }
            },
            start_host
        );
      
      } catch (Error err) {
          critical("%s", err.message);
      }

    }

    private void start_watcher(DBusConnection conn) {
      watcher = new StatusNotifierWatcher();
      conn.register_object("/StatusNotifierWatcher", watcher);
      watcher.StatusNotifierItemRegistered.connect(on_item_register);
      watcher.StatusNotifierItemUnregistered.connect(on_item_unregister);
    }

    private void start_host() {
      if(proxy != null) return;
      
      proxy = Bus.get_proxy_sync(
          BusType.SESSION,
          "org.kde.StatusNotifierWatcher",
          "/StatusNotifierWatcher"
        ); 
      
      proxy.StatusNotifierItemRegistered.connect(on_item_register);
      proxy.StatusNotifierItemUnregistered.connect(on_item_unregister);

      foreach (string item in proxy.RegisteredStatusNotifierItems) {
        on_item_register(item);
      }
    }

    private void on_item_register(string service) {
      if(_items.contains(service)) return;
      string[] 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);
    }

}
}