diff options
| author | frosty <gabriel@bwaaa.monster> | 2026-08-25 22:50:10 -0400 |
|---|---|---|
| committer | frosty <gabriel@bwaaa.monster> | 2026-08-25 22:50:10 -0400 |
| commit | b19412a3d291f8cdbf037e00ac2f3641f7493de6 (patch) | |
| tree | 8179bc8a64c2286fde58ce829f774ac3d0a32c1b /main/src/ui/status_notifier_menu.vala | |
| parent | d2c69cfb544c23042652dee9ebf0e7031d6c2b29 (diff) | |
feat: add tray icon
Diffstat (limited to 'main/src/ui/status_notifier_menu.vala')
| -rw-r--r-- | main/src/ui/status_notifier_menu.vala | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/main/src/ui/status_notifier_menu.vala b/main/src/ui/status_notifier_menu.vala new file mode 100644 index 00000000..cc8b1375 --- /dev/null +++ b/main/src/ui/status_notifier_menu.vala @@ -0,0 +1,100 @@ +using GLib; + +namespace Dino.Ui { + +public struct DBusMenuLayout { + public int id; + public HashTable<string, Variant> properties; + public Variant[] children; +} + +[DBus (name = "com.canonical.dbusmenu")] +public class StatusNotifierMenu : Object { + private const int ROOT_ITEM_ID = 0; + private const int QUIT_ITEM_ID = 1; + + private weak Application application; + private bool quit_scheduled; + + public uint version { get { return 3; } } + public string text_direction { owned get { return "ltr"; } } + public string status { owned get { return "normal"; } } + public string[] icon_theme_path { owned get { return new string[0]; } } + + public signal void layout_updated(uint revision, int parent); + + public StatusNotifierMenu(Application application) { + this.application = application; + } + + public void get_layout(int parent_id, int recursion_depth, string[] property_names, + out uint revision, out DBusMenuLayout layout) throws Error { + revision = 1; + layout = create_layout(parent_id, recursion_depth, property_names); + } + + public void @event(int id, string event_id, Variant data, uint timestamp) throws Error { + if (id != QUIT_ITEM_ID || event_id != "clicked" || quit_scheduled) return; + + quit_scheduled = true; + Idle.add(() => { + application.quit(); + return Source.REMOVE; + }); + } + + public bool about_to_show(int id) throws Error { + return false; + } + + private DBusMenuLayout create_layout(int id, int recursion_depth, string[] property_names) { + DBusMenuLayout layout = DBusMenuLayout(); + layout.id = id; + layout.properties = get_item_properties(id, property_names); + layout.children = new Variant[0]; + + if (id == ROOT_ITEM_ID && recursion_depth != 0) { + DBusMenuLayout quit_item = create_layout(QUIT_ITEM_ID, 0, property_names); + layout.children = new Variant[] { layout_to_variant(quit_item) }; + } + return layout; + } + + private HashTable<string, Variant> get_item_properties(int id, string[] property_names) { + HashTable<string, Variant> properties = new HashTable<string, Variant>(str_hash, str_equal); + + if (id == ROOT_ITEM_ID) { + add_property(properties, property_names, "children-display", new Variant.string("submenu")); + } else if (id == QUIT_ITEM_ID) { + add_property(properties, property_names, "label", new Variant.string(_("Quit Dino"))); + } + return properties; + } + + private static void add_property(HashTable<string, Variant> properties, string[] property_names, + string name, Variant value) { + if (property_names.length == 0 || name in property_names) { + properties.insert(name, value); + } + } + + private static Variant layout_to_variant(DBusMenuLayout layout) { + VariantBuilder properties = new VariantBuilder(new VariantType("a{sv}")); + layout.properties.foreach((name, value) => { + properties.add("{sv}", name, value); + }); + + Variant[] children = new Variant[layout.children.length]; + for (int i = 0; i < layout.children.length; i++) { + children[i] = new Variant.variant(layout.children[i]); + } + + return new Variant.tuple(new Variant[] { + new Variant.int32(layout.id), + properties.end(), + new Variant.array(VariantType.VARIANT, children) + }); + } +} + +} |
