Fix dbusmenu leak

The menu that was created for the sni context menu was never destroyed.
Instead of creating a new menu each time, the existing menu is recycled
and destroyed when the item is.
This commit is contained in:
scorpion-26 2024-02-16 20:03:34 +01:00
parent da4634770d
commit 4ed6c06449

View file

@ -39,6 +39,7 @@ namespace SNI
std::string menuObjectPath = ""; std::string menuObjectPath = "";
EventBox* gtkEvent = nullptr; EventBox* gtkEvent = nullptr;
GtkMenu* dbusMenu = nullptr;
int watcherID = -1; int watcherID = -1;
int propertyChangeWatcherID = -1; int propertyChangeWatcherID = -1;
@ -265,6 +266,18 @@ namespace SNI
return item; return item;
} }
static void DestroyItem(Item& item)
{
g_bus_unwatch_name(item.watcherID);
g_dbus_connection_signal_unsubscribe(dbusConnection, item.propertyChangeWatcherID);
g_object_unref(item.pixbuf);
if (item.dbusMenu)
{
gtk_menu_detach(item.dbusMenu);
g_free(item.dbusMenu);
}
}
static void InvalidateWidget(); static void InvalidateWidget();
static void DBusNameVanished(GDBusConnection*, const char* name, void*) static void DBusNameVanished(GDBusConnection*, const char* name, void*)
@ -277,9 +290,7 @@ namespace SNI
if (it != items.end()) if (it != items.end())
{ {
LOG("SNI: " << name << " vanished!"); LOG("SNI: " << name << " vanished!");
g_bus_unwatch_name(it->watcherID); DestroyItem(*it);
g_dbus_connection_signal_unsubscribe(dbusConnection, it->propertyChangeWatcherID);
g_object_unref(it->pixbuf);
items.erase(it); items.erase(it);
InvalidateWidget(); InvalidateWidget();
return; return;
@ -335,9 +346,7 @@ namespace SNI
LOG("SNI: Actual object path: " << itemObjectPath) LOG("SNI: Actual object path: " << itemObjectPath)
if (it != items.end()) if (it != items.end())
{ {
g_bus_unwatch_name(it->watcherID); DestroyItem(*it);
g_dbus_connection_signal_unsubscribe(dbusConnection, it->propertyChangeWatcherID);
g_object_unref(it->pixbuf);
items.erase(it); items.erase(it);
} }
else else
@ -433,10 +442,13 @@ namespace SNI
{ {
Item* item = (Item*)data; Item* item = (Item*)data;
GtkMenu* menu = (GtkMenu*)dbusmenu_gtkmenu_new(item->name.data(), item->menuObjectPath.data()); // Create the menu if it wasn't already created
LOG(menu); if (!item->dbusMenu)
gtk_menu_attach_to_widget(menu, item->gtkEvent->Get(), nullptr); {
gtk_menu_popup_at_pointer(menu, (GdkEvent*)event); item->dbusMenu = (GtkMenu*)dbusmenu_gtkmenu_new(item->name.data(), item->menuObjectPath.data());
gtk_menu_attach_to_widget(item->dbusMenu, item->gtkEvent->Get(), nullptr);
}
gtk_menu_popup_at_pointer(item->dbusMenu, (GdkEvent*)event);
LOG(item->menuObjectPath << " click"); LOG(item->menuObjectPath << " click");
} }
return GDK_EVENT_STOP; return GDK_EVENT_STOP;