dwlb

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 834464978192e3e0c482323ad27210eddd9171b2
parent 6ac814595fcfed4b54d103b84e1851d3737db24b
Author: Janne Veteläinen <janne.vetelainen@elisanet.fi>
Date:   Thu, 27 Jun 2024 00:47:23 +0300

Move gmenu and actiongroup to sndbusmenu

Diffstat:
Msystray/sndbusmenu.c | 64+++++++++++++++++++++++++++++++++++++++++++++-------------------
Msystray/snitem.c | 82+++++++++++++++++++++++++++++++------------------------------------------------
Msystray/snitem.h | 6+++---
3 files changed, 80 insertions(+), 72 deletions(-)

diff --git a/systray/sndbusmenu.c b/systray/sndbusmenu.c @@ -19,6 +19,7 @@ struct _SnDbusmenu { SnItem* snitem; GMenu* menu; + GSimpleActionGroup* actiongroup; GDBusProxy* proxy; uint32_t revision; @@ -45,6 +46,8 @@ enum static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; static uint signals[LAST_SIGNAL]; +static const char actiongroup_pfx[] = "menuitem"; +static const int layout_update_freq = 100; typedef struct { uint32_t id; @@ -121,6 +124,8 @@ create_action(uint32_t id, SnDbusmenu *self) static GMenuItem* create_menuitem(int32_t id, GVariant *menuitem_data, GVariant *submenuitem_data, SnDbusmenu *self) { + GActionMap *actionmap = G_ACTION_MAP(self->actiongroup); + // a{sv] // GVariant *data GMenuItem *menuitem = NULL; @@ -167,8 +172,8 @@ create_menuitem(int32_t id, GVariant *menuitem_data, GVariant *submenuitem_data, if ((label && isvisible && isenabled) && !(type && strcmp(type, "separator") == 0)) { GSimpleAction *action = create_action(id, self); - char *action_name = g_strdup_printf("%s.%u", "menuitem", id); - sn_item_add_action(self->snitem, action); + char *action_name = g_strdup_printf("%s.%u", actiongroup_pfx, id); + g_action_map_add_action(actionmap, G_ACTION(action)); menuitem = g_menu_item_new(label, action_name); g_free(action_name); @@ -177,8 +182,8 @@ create_menuitem(int32_t id, GVariant *menuitem_data, GVariant *submenuitem_data, } else if ((label && isvisible && !isenabled && !(type && strcmp(type, "separator") == 0))) { GSimpleAction *action = create_action(id, self); g_simple_action_set_enabled(action, FALSE); - char *action_name = g_strdup_printf("%s.%u", "menuitem", id); - sn_item_add_action(self->snitem, action); + char *action_name = g_strdup_printf("%s.%u", actiongroup_pfx, id); + g_action_map_add_action(actionmap, G_ACTION(action)); menuitem = g_menu_item_new(label, action_name); g_free(action_name); @@ -254,18 +259,22 @@ layout_update(SnDbusmenu *self) layout = g_variant_get_child_value(data, 1); menuitems = g_variant_get_child_value(layout, 2); - gboolean isvisible = sn_item_get_popover_visible(self->snitem); if (isvisible) { self->reschedule = TRUE; g_debug("Popover was visible, couldn't update menu %s", self->busname); } else { + GSimpleActionGroup *newag = g_simple_action_group_new(); + sn_item_set_actiongroup(self->snitem, actiongroup_pfx, newag); + g_object_unref(self->actiongroup); + self->actiongroup = newag; + GMenu *newmenu = create_menumodel(menuitems, self); - // sn_item_remove_all_actions(self->snitem); sn_item_set_menu_model(self->snitem, newmenu); g_object_unref(self->menu); - self->menu = create_menumodel(menuitems, self); + self->menu = newmenu; } + g_variant_unref(menuitems); g_variant_unref(layout); @@ -296,10 +305,7 @@ reschedule_update(SnItem *snitem, GParamSpec *pspec, void *data) } // Update signals are often received multiple times in row, -// we throttle update frequency to 100ms - -static const int update_freq = 100; - +// we throttle update frequency to *layout_update_freq* static void proxy_signal_handler(GDBusProxy *proxy, const char *sender, @@ -324,7 +330,7 @@ proxy_signal_handler(GDBusProxy *proxy, if (!self->update_pending) { self->update_pending = TRUE; g_object_ref(self->snitem); - g_timeout_add_once(update_freq, (GSourceOnceFunc)layout_update, g_object_ref(self)); + g_timeout_add_once(layout_update_freq, (GSourceOnceFunc)layout_update, g_object_ref(self)); } else { g_debug("skipping update"); } @@ -335,7 +341,7 @@ proxy_signal_handler(GDBusProxy *proxy, if (!self->update_pending) { self->update_pending = TRUE; g_object_ref(self->snitem); - g_timeout_add_once(update_freq, (GSourceOnceFunc)layout_update, g_object_ref(self)); + g_timeout_add_once(layout_update_freq, (GSourceOnceFunc)layout_update, g_object_ref(self)); } else { g_debug("skipping update"); } @@ -553,6 +559,8 @@ sn_dbusmenu_init(SnDbusmenu *self) // When reschedule is TRUE, menu will be updated next time it is closed. self->reschedule = FALSE; self->update_pending = FALSE; + + self->actiongroup = g_simple_action_group_new(); } static void @@ -560,6 +568,8 @@ sn_dbusmenu_constructed(GObject *obj) { SnDbusmenu *self = SN_DBUSMENU(obj); + sn_item_set_actiongroup(self->snitem, actiongroup_pfx, self->actiongroup); + GDBusNodeInfo *nodeinfo = g_dbus_node_info_new_for_xml(DBUSMENU_XML, NULL); g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, @@ -584,11 +594,29 @@ sn_dbusmenu_dispose(GObject *obj) { SnDbusmenu *self = SN_DBUSMENU(obj); - g_debug("Disposing sndbusmenu %s %s", - self->busname, - self->busobj); + g_debug("Disposing sndbusmenu %s %s", self->busname, self->busobj); - g_object_unref(self->proxy); + if (self->proxy) { + g_object_unref(self->proxy); + self->proxy = NULL; + } + + if (self->actiongroup) { + sn_item_clear_actiongroup(self->snitem, actiongroup_pfx); + g_object_unref(self->actiongroup); + self->actiongroup = NULL; + } + + if (self->menu) { + sn_item_clear_menu_model(self->snitem); + g_object_unref(self->menu); + self->menu = NULL; + } + + if (self->snitem) { + g_object_unref(self->snitem); + self->snitem = NULL; + } G_OBJECT_CLASS(sn_dbusmenu_parent_class)->dispose(obj); } @@ -597,8 +625,6 @@ static void sn_dbusmenu_finalize(GObject *obj) { SnDbusmenu *self = SN_DBUSMENU(obj); - if (self->menu) - g_object_unref(self->menu); g_free(self->busname); g_free(self->busobj); G_OBJECT_CLASS(sn_dbusmenu_parent_class)->finalize(obj); diff --git a/systray/snitem.c b/systray/snitem.c @@ -28,7 +28,7 @@ struct _SnItem GtkWidget* image; GtkWidget* popovermenu; - GSimpleActionGroup* actiongroup; + GMenu* init_menu; GSList* cachedicons; int iconsize; @@ -47,7 +47,6 @@ enum PROP_BUSOBJ, PROP_ICONSIZE, PROP_PROXY, - PROP_ACTIONGROUP, PROP_DBUSMENU, PROP_MENUVISIBLE, N_PROPERTIES @@ -583,9 +582,6 @@ sn_item_set_property(GObject *object, uint property_id, const GValue *value, GPa case PROP_ICONSIZE: self->iconsize = g_value_get_int(value); break; - case PROP_ACTIONGROUP: - self->actiongroup = g_value_get_object(value); - break; case PROP_DBUSMENU: self->dbusmenu = g_value_get_object(value); break; @@ -612,9 +608,6 @@ sn_item_get_property(GObject *object, uint property_id, GValue *value, GParamSpe case PROP_ICONSIZE: g_value_set_int(value, self->iconsize); break; - case PROP_ACTIONGROUP: - g_value_set_object(value, self->actiongroup); - break; case PROP_DBUSMENU: g_value_set_object(value, self->dbusmenu); break; @@ -642,7 +635,6 @@ sn_item_class_init(SnItemClass *klass) object_class->dispose = sn_item_dispose; object_class->finalize = sn_item_finalize; - obj_properties[PROP_BUSNAME] = g_param_spec_string("busname", NULL, NULL, NULL, @@ -666,12 +658,6 @@ sn_item_class_init(SnItemClass *klass) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_ACTIONGROUP] = - g_param_spec_object("actiongroup", NULL, NULL, - G_TYPE_SIMPLE_ACTION_GROUP, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_PROXY] = g_param_spec_object("proxy", NULL, NULL, G_TYPE_DBUS_PROXY, @@ -710,12 +696,6 @@ sn_item_init(SnItem *self) GtkWidget *widget = GTK_WIDGET(self); self->exiting = FALSE; - GSimpleActionGroup *actiongroup = g_simple_action_group_new(); - g_object_set(self, "actiongroup", actiongroup, NULL); - - gtk_widget_insert_action_group(GTK_WIDGET(self), - "menuitem", - G_ACTION_GROUP(self->actiongroup)); gtk_widget_set_hexpand(widget, TRUE); gtk_widget_set_vexpand(widget, TRUE); @@ -726,9 +706,8 @@ sn_item_init(SnItem *self) gtk_widget_set_parent(self->image, widget); - GMenu *init_menu = g_menu_new(); - self->popovermenu = gtk_popover_menu_new_from_model(G_MENU_MODEL(init_menu)); - g_object_unref(init_menu); + self->init_menu = g_menu_new(); + self->popovermenu = gtk_popover_menu_new_from_model(G_MENU_MODEL(self->init_menu)); gtk_popover_menu_set_flags(GTK_POPOVER_MENU(self->popovermenu), GTK_POPOVER_MENU_NESTED); gtk_popover_set_has_arrow(GTK_POPOVER(self->popovermenu), FALSE); gtk_widget_set_parent(self->popovermenu, widget); @@ -777,6 +756,9 @@ sn_item_dispose(GObject *obj) self->exiting = TRUE; if (self->dbusmenu) { + // Unref will be called from sndbusmenu dispose function + g_object_ref(self); + g_signal_handler_disconnect(self->dbusmenu, self->popup_sig_id); self->popup_sig_id = 0; g_object_unref(self->dbusmenu); @@ -788,11 +770,11 @@ sn_item_dispose(GObject *obj) self->proxy = NULL; } - sn_item_set_menu_model(self, NULL); - if (self->popovermenu) { gtk_widget_unparent(self->popovermenu); self->popovermenu = NULL; + g_object_unref(self->init_menu); + self->init_menu = NULL; } if (self->image) { @@ -800,8 +782,6 @@ sn_item_dispose(GObject *obj) self->image = NULL; } - gtk_widget_insert_action_group(GTK_WIDGET(self), "menuitem", NULL); - G_OBJECT_CLASS(sn_item_parent_class)->dispose(obj); } @@ -810,8 +790,6 @@ sn_item_finalize(GObject *object) { SnItem *self = SN_ITEM(object); - g_object_unref(self->actiongroup); - g_free(self->busname); g_free(self->busobj); @@ -824,50 +802,52 @@ sn_item_finalize(GObject *object) void sn_item_set_menu_model(SnItem *self, GMenu* menu) { + g_return_if_fail(SN_IS_ITEM(self)); + g_return_if_fail(G_IS_MENU(menu)); + if (!self->popovermenu) return; gtk_popover_menu_set_menu_model(GTK_POPOVER_MENU(self->popovermenu), G_MENU_MODEL(menu)); } -GSimpleActionGroup* -sn_item_get_actiongroup(SnItem *self) +void +sn_item_clear_menu_model(SnItem *self) { - GSimpleActionGroup *actiongroup; - g_object_get(self, "actiongroup", &actiongroup, NULL); + g_return_if_fail(SN_IS_ITEM(self)); - return actiongroup; -} + if (!self->popovermenu) + return; -void -sn_item_add_action(SnItem *self, GSimpleAction *action) -{ - g_action_map_add_action(G_ACTION_MAP(self->actiongroup), G_ACTION(action)); + gtk_popover_menu_set_menu_model(GTK_POPOVER_MENU(self->popovermenu), G_MENU_MODEL(self->init_menu)); } void -sn_item_remove_action(SnItem *self, const char *action_name) +sn_item_set_actiongroup(SnItem *self, const char *prefix, GSimpleActionGroup *group) { - g_action_map_remove_action(G_ACTION_MAP(self->actiongroup), action_name); + g_return_if_fail(SN_IS_ITEM(self)); + g_return_if_fail(G_IS_SIMPLE_ACTION_GROUP(group)); + + gtk_widget_insert_action_group(GTK_WIDGET(self), + prefix, + G_ACTION_GROUP(group)); } void -sn_item_remove_all_actions(SnItem *self) +sn_item_clear_actiongroup(SnItem *self, const char *prefix) { - GtkWidget *widget = GTK_WIDGET(self); + g_return_if_fail(SN_IS_ITEM(self)); - gtk_widget_insert_action_group(widget, "menuitem", NULL); - g_object_unref(self->actiongroup); - GSimpleActionGroup *actiongroup = g_simple_action_group_new(); - g_object_set(self, "actiongroup", actiongroup, NULL); gtk_widget_insert_action_group(GTK_WIDGET(self), - "menuitem", - G_ACTION_GROUP(self->actiongroup)); + prefix, + NULL); } char* sn_item_get_busname(SnItem *self) { + g_return_val_if_fail(SN_IS_ITEM(self), NULL); + char *busname; g_object_get(self, "busname", &busname, NULL); @@ -877,6 +857,8 @@ sn_item_get_busname(SnItem *self) gboolean sn_item_get_popover_visible(SnItem *self) { + g_return_val_if_fail(SN_IS_ITEM(self), FALSE); + gboolean visible; g_object_get(self, "menuvisible", &visible, NULL); diff --git a/systray/snitem.h b/systray/snitem.h @@ -14,11 +14,11 @@ SnItem* sn_item_new (const char *busname, int iconsize); void sn_item_set_menu_model (SnItem *widget, GMenu *menu); -void sn_item_add_action (SnItem *self, GSimpleAction *action); +void sn_item_clear_menu_model (SnItem *widget); char* sn_item_get_busname (SnItem *self); gboolean sn_item_get_popover_visible (SnItem *self); -void sn_item_remove_action (SnItem *self, const char *action_name); -void sn_item_remove_all_actions (SnItem *self); +void sn_item_set_actiongroup(SnItem *self, const char *prefix, GSimpleActionGroup *group); +void sn_item_clear_actiongroup(SnItem *self, const char *prefix); G_END_DECLS