diff options
Diffstat (limited to 'main/src/ui/status_notifier_item.vala')
| -rw-r--r-- | main/src/ui/status_notifier_item.vala | 212 |
1 files changed, 212 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..70db17d5 --- /dev/null +++ b/main/src/ui/status_notifier_item.vala @@ -0,0 +1,212 @@ +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 { + if (application.window != null && application.window.is_active) { + application.window.visible = false; + activation_token = null; + return; + } + + 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(); + } +} + +} |
