using GLib; namespace Dino.Ui { public struct DBusMenuLayout { public int id; public HashTable 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 get_item_properties(int id, string[] property_names) { HashTable properties = new HashTable(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 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) }); } } }