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:
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