Files
bar/include/services/tray.hpp
2025-12-10 17:58:01 +01:00

144 lines
5.3 KiB
C++

#pragma once
#include <gdkmm/memorytexture.h>
#include <giomm/actiongroup.h>
#include <giomm/dbusconnection.h>
#include <giomm/init.h>
#include <giomm/menumodel.h>
#include <glibmm/bytes.h>
#include <glibmm/refptr.h>
#include <sigc++/sigc++.h>
#include <gio/gio.h>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>
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<Gdk::Paintable> iconPaintable;
};
TrayService();
~TrayService();
void start();
void stop();
std::vector<Item> 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<Gio::MenuModel> get_menu_model(const std::string &id);
Glib::RefPtr<Gio::ActionGroup> 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<MenuNode> children;
};
std::optional<MenuNode> get_menu_layout(const std::string &id);
bool activate_menu_item(const std::string &id, int itemId);
sigc::signal<void(const Item &)> &signal_item_added();
sigc::signal<void(const std::string &)> &signal_item_removed();
sigc::signal<void(const Item &)> &signal_item_updated();
private:
struct TrackedItem {
Item publicData;
guint signalSubscriptionId = 0;
guint ownerWatchId = 0;
Glib::RefPtr<Gio::MenuModel> menuModel;
Glib::RefPtr<Gio::ActionGroup> menuActions;
};
Glib::RefPtr<Gio::DBus::Connection> connection;
Glib::RefPtr<Gio::DBus::NodeInfo> nodeInfo;
Gio::DBus::InterfaceVTable vtable;
guint nameOwnerId = 0;
guint registrationId = 0;
bool hostRegistered = false;
std::map<std::string, std::unique_ptr<TrackedItem>> items;
sigc::signal<void(const Item &)> itemAddedSignal;
sigc::signal<void(const std::string &)> itemRemovedSignal;
sigc::signal<void(const Item &)> itemUpdatedSignal;
void on_bus_acquired(const Glib::RefPtr<Gio::DBus::Connection> &connection,
const Glib::ustring &name);
void on_name_acquired(const Glib::RefPtr<Gio::DBus::Connection> &connection,
const Glib::ustring &name);
void on_name_lost(const Glib::RefPtr<Gio::DBus::Connection> &connection,
const Glib::ustring &name);
void handle_method_call(
const Glib::RefPtr<Gio::DBus::Connection> &connection,
const Glib::ustring &sender, const Glib::ustring &object_path,
const Glib::ustring &interface_name, const Glib::ustring &method_name,
const Glib::VariantContainerBase &parameters,
const Glib::RefPtr<Gio::DBus::MethodInvocation> &invocation);
void handle_get_property_slot(
Glib::VariantBase &result,
const Glib::RefPtr<Gio::DBus::Connection> &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<Gio::DBus::Connection> &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<std::vector<Glib::ustring>>
create_registered_items_variant() const;
void emit_watcher_signal(const Glib::ustring &signal_name,
const Glib::VariantContainerBase &parameters);
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<Gdk::Paintable> parse_icon_pixmap(GVariant *variant);
};