aboutsummaryrefslogtreecommitdiff
path: root/main/src/ui/status_notifier_item.vala
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/ui/status_notifier_item.vala')
-rw-r--r--main/src/ui/status_notifier_item.vala206
1 files changed, 206 insertions, 0 deletions
diff --git a/main/src/ui/status_notifier_item.vala b/main/src/ui/status_notifier_item.vala
new file mode 100644
index 00000000..de29509d
--- /dev/null
+++ b/main/src/ui/status_notifier_item.vala
@@ -0,0 +1,206 @@
+using GLib;
+
+namespace Dino.Ui {
+
+public struct StatusNotifierIconPixmap {
+ public int width;
+ public int height;
+ public uint8[] data;
+}
+
+public struct StatusNotifierToolTip {
+ public string icon_name;
+ public StatusNotifierIconPixmap[] icon_pixmap;
+ public string title;
+ public string description;
+}
+
+[DBus (name = "org.kde.StatusNotifierItem")]
+public class StatusNotifierItem : Object {
+ private const string BUS_NAME_TEMPLATE = "org.kde.StatusNotifierItem-%d-1";
+ private const string ICON_NAME = "im.dino.Dino";
+ private const string ITEM_OBJECT_PATH = "/StatusNotifierItem";
+ private const string MENU_OBJECT_PATH = "/MenuBar";
+ private const string WATCHER_BUS_NAME = "org.kde.StatusNotifierWatcher";
+ private const string WATCHER_INTERFACE = "org.kde.StatusNotifierWatcher";
+ private const string WATCHER_OBJECT_PATH = "/StatusNotifierWatcher";
+
+ private weak Application application;
+ private DBusConnection connection;
+ private string bus_name;
+ private bool name_acquired;
+ private bool registration_in_progress;
+ private bool shutting_down;
+ private bool watcher_available;
+ private bool registered_with_watcher;
+ private string? activation_token;
+ private string? watcher_owner;
+ private Cancellable registration_cancellable = new Cancellable();
+ private StatusNotifierMenu status_notifier_menu;
+ private uint bus_name_owner_id;
+ private uint menu_registration_id;
+ private uint object_registration_id;
+ private uint watcher_id;
+
+ public string category { owned get { return "Communications"; } }
+ public string id { owned get { return "Dino"; } }
+ public string title { owned get { return "Dino"; } }
+ public string status { owned get { return "Active"; } }
+ public int window_id { get { return 0; } }
+ public string icon_theme_path { owned get { return ""; } }
+ public ObjectPath menu { owned get { return new ObjectPath(MENU_OBJECT_PATH); } }
+ public bool item_is_menu { get { return false; } }
+ public string icon_name { owned get { return ICON_NAME; } }
+ public StatusNotifierIconPixmap[] icon_pixmap { owned get { return new StatusNotifierIconPixmap[0]; } }
+ public string overlay_icon_name { owned get { return ""; } }
+ public StatusNotifierIconPixmap[] overlay_icon_pixmap { owned get { return new StatusNotifierIconPixmap[0]; } }
+ public string attention_icon_name { owned get { return ""; } }
+ public StatusNotifierIconPixmap[] attention_icon_pixmap { owned get { return new StatusNotifierIconPixmap[0]; } }
+ public string attention_movie_name { owned get { return ""; } }
+ public StatusNotifierToolTip tool_tip {
+ owned get {
+ StatusNotifierToolTip tool_tip = StatusNotifierToolTip();
+ tool_tip.icon_name = ICON_NAME;
+ tool_tip.icon_pixmap = new StatusNotifierIconPixmap[0];
+ tool_tip.title = "Dino";
+ tool_tip.description = _("Open Dino");
+ return tool_tip;
+ }
+ }
+
+ public signal void new_title();
+ public signal void new_icon();
+ public signal void new_attention_icon();
+ public signal void new_overlay_icon();
+ public signal void new_menu();
+ public signal void new_tool_tip();
+ public signal void new_status(string status);
+
+ public StatusNotifierItem(Application application) throws IOError {
+ this.application = application;
+ this.connection = Bus.get_sync(BusType.SESSION);
+ this.bus_name = BUS_NAME_TEMPLATE.printf((int) Posix.getpid());
+
+ status_notifier_menu = new StatusNotifierMenu(application);
+ menu_registration_id = connection.register_object(MENU_OBJECT_PATH, status_notifier_menu);
+ object_registration_id = connection.register_object(ITEM_OBJECT_PATH, this);
+ bus_name_owner_id = Bus.own_name_on_connection(
+ connection,
+ bus_name,
+ BusNameOwnerFlags.NONE,
+ () => {
+ name_acquired = true;
+ register_with_watcher.begin();
+ },
+ () => {
+ name_acquired = false;
+ registered_with_watcher = false;
+ });
+ watcher_id = Bus.watch_name_on_connection(
+ connection,
+ WATCHER_BUS_NAME,
+ BusNameWatcherFlags.NONE,
+ (watcher_connection, watcher_name, name_owner) => {
+ watcher_owner = name_owner;
+ watcher_available = true;
+ registered_with_watcher = false;
+ register_with_watcher.begin();
+ },
+ () => {
+ watcher_owner = null;
+ watcher_available = false;
+ registered_with_watcher = false;
+ });
+ }
+
+ internal void shutdown() {
+ shutting_down = true;
+ name_acquired = false;
+ watcher_available = false;
+ registration_cancellable.cancel();
+
+ if (watcher_id != 0) {
+ Bus.unwatch_name(watcher_id);
+ watcher_id = 0;
+ }
+ if (bus_name_owner_id != 0) {
+ Bus.unown_name(bus_name_owner_id);
+ bus_name_owner_id = 0;
+ }
+ if (object_registration_id != 0) {
+ connection.unregister_object(object_registration_id);
+ object_registration_id = 0;
+ }
+ if (menu_registration_id != 0) {
+ connection.unregister_object(menu_registration_id);
+ menu_registration_id = 0;
+ }
+ }
+
+ public void provide_xdg_activation_token(string token) throws Error {
+ activation_token = token;
+ }
+
+ public void context_menu(int x, int y) throws Error {
+ }
+
+ public void activate(int x, int y) throws Error {
+ show_window();
+ }
+
+ public void secondary_activate(int x, int y) throws Error {
+ show_window();
+ }
+
+ public void scroll(int delta, string orientation) throws Error {
+ }
+
+ private async void register_with_watcher() {
+ if (shutting_down || !name_acquired || !watcher_available ||
+ registered_with_watcher || registration_in_progress) return;
+
+ registration_in_progress = true;
+ string? registering_watcher = watcher_owner;
+
+ try {
+ yield connection.call(
+ WATCHER_BUS_NAME,
+ WATCHER_OBJECT_PATH,
+ WATCHER_INTERFACE,
+ "RegisterStatusNotifierItem",
+ new Variant("(s)", bus_name),
+ null,
+ DBusCallFlags.NONE,
+ 5000,
+ registration_cancellable);
+ if (!shutting_down && name_acquired && watcher_owner == registering_watcher) {
+ registered_with_watcher = true;
+ }
+ } catch (Error e) {
+ if (!(e is IOError.CANCELLED)) {
+ warning("Could not register Dino's tray icon: %s", e.message);
+ }
+ }
+
+ registration_in_progress = false;
+ if (!shutting_down && name_acquired && watcher_available && !registered_with_watcher &&
+ watcher_owner != registering_watcher) {
+ register_with_watcher.begin();
+ }
+ }
+
+ private void show_window() {
+ if (application.window == null) {
+ application.activate();
+ return;
+ }
+
+ if (activation_token != null) {
+ application.window.set_startup_id(activation_token);
+ activation_token = null;
+ }
+ application.window.present();
+ }
+}
+
+}