#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include class TrayService { public: struct Item { std::string id; std::string busName; std::string objectPath; std::string title; std::string status; std::string iconName; std::string menuPath; bool menuAvailable = false; Glib::RefPtr iconPaintable; }; TrayService(); ~TrayService(); void start(); void stop(); std::vector snapshotItems() const; const Item *findItem(const std::string &id) const; void activate(const std::string &id, int32_t x, int32_t y); void secondaryActivate(const std::string &id, int32_t x, int32_t y); void contextMenu(const std::string &id, int32_t x, int32_t y); Glib::RefPtr get_menu_model(const std::string &id); Glib::RefPtr get_menu_action_group(const std::string &id); void debug_dump_menu_layout(const std::string &id); struct MenuNode { int id = 0; std::string label; bool enabled = true; bool visible = true; bool separator = false; std::vector children; }; std::optional get_menu_layout(const std::string &id); bool activate_menu_item(const std::string &id, int itemId); sigc::signal &signal_item_added(); sigc::signal &signal_item_removed(); sigc::signal &signal_item_updated(); private: struct TrackedItem { Item publicData; guint signalSubscriptionId = 0; guint ownerWatchId = 0; Glib::RefPtr menuModel; Glib::RefPtr menuActions; }; Glib::RefPtr m_connection; Glib::RefPtr m_nodeInfo; Gio::DBus::InterfaceVTable m_vtable; guint m_nameOwnerId = 0; guint m_registrationId = 0; bool m_hostRegistered = false; std::map> m_items; sigc::signal m_itemAddedSignal; sigc::signal m_itemRemovedSignal; sigc::signal m_itemUpdatedSignal; void on_bus_acquired(const Glib::RefPtr &connection, const Glib::ustring &name); void on_name_acquired(const Glib::RefPtr &connection, const Glib::ustring &name); void on_name_lost(const Glib::RefPtr &connection, const Glib::ustring &name); void handle_method_call(const Glib::RefPtr &connection, const Glib::ustring &sender, const Glib::ustring &object_path, const Glib::ustring &interface_name, const Glib::ustring &method_name, const Glib::VariantContainerBase ¶meters, const Glib::RefPtr &invocation); void handle_get_property_slot(Glib::VariantBase &result, const Glib::RefPtr &connection, const Glib::ustring &sender, const Glib::ustring &object_path, const Glib::ustring &interface_name, const Glib::ustring &property_name); bool handle_set_property_slot(const Glib::RefPtr &connection, const Glib::ustring &sender, const Glib::ustring &object_path, const Glib::ustring &interface_name, const Glib::ustring &property_name, const Glib::VariantBase &value); Glib::VariantBase handle_get_property(const Glib::ustring &property_name); bool handle_set_property(const Glib::ustring &property_name, const Glib::VariantBase &value); void register_item(const Glib::ustring &sender, const std::string &service); void unregister_item(const std::string &id); void refresh_item(TrackedItem &item); void emit_registered_items_changed(); Glib::Variant> create_registered_items_variant() const; void emit_watcher_signal(const Glib::ustring &signal_name, const Glib::VariantContainerBase ¶meters); static void on_dbus_signal_static(GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data); void on_dbus_signal(const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters); static void on_name_vanished_static(GDBusConnection *connection, const gchar *name, gpointer user_data); void on_name_vanished(const gchar *bus_name); static Glib::RefPtr parse_icon_pixmap(GVariant *variant); };