From aeba43c7b4be927c23eb61c2644e60182be22bd5 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Wed, 20 Apr 2016 11:00:35 -0300 Subject: Fix memory leak on messaging_menu. --- src/notifications.cpp | 68 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/notifications.cpp b/src/notifications.cpp index 5b64471..076ad13 100644 --- a/src/notifications.cpp +++ b/src/notifications.cpp @@ -137,8 +137,9 @@ class Engine::Impl struct messaging_menu_data { - std::shared_ptr mm; + std::string msg_id; std::function callback; + Engine::Impl *self; }; public: @@ -151,11 +152,7 @@ public: g_critical("Unable to initialize libnotify!"); // messaging menu - GIcon *icon = g_themed_icon_new("calendar-app"); - messaging_menu_app_register(m_messaging_app.get()); - messaging_menu_app_append_source(m_messaging_app.get(), m_app_name.c_str(), icon, "Calendar"); - g_object_unref(icon); } ~Impl() @@ -285,20 +282,31 @@ public: uuid_unparse(message_uuid, message_id); GIcon *icon = g_themed_icon_new(data.m_icon_name.c_str()); - std::shared_ptr msg (messaging_menu_message_new(message_id, - icon, - data.m_title.c_str(), - nullptr, - data.m_body.c_str(), - data.m_start_time * 1000000), // secs -> microsecs - g_object_unref); + + // check if source exists + if (!messaging_menu_app_has_source(m_messaging_app.get(), m_app_name.c_str())) + messaging_menu_app_append_source(m_messaging_app.get(), m_app_name.c_str(), icon, "Calendar"); + + auto msg = messaging_menu_message_new(message_id, + icon, + data.m_title.c_str(), + nullptr, + data.m_body.c_str(), + data.m_start_time * 1000000); // secs -> microsecs g_object_unref(icon); if (msg) { - m_messaging_messages[std::string(message_id)] = { msg, data.m_missed_click_callback }; - g_signal_connect(msg.get(), "activate", - G_CALLBACK(on_message_activated), this); - messaging_menu_app_append_message(m_messaging_app.get(), msg.get(), m_app_name.c_str(), false); + std::shared_ptr msg_data(new messaging_menu_data{message_id, data.m_missed_click_callback, this}); + m_messaging_messages[std::string(message_id)] = msg_data; + g_signal_connect(G_OBJECT(msg), "activate", + G_CALLBACK(on_message_activated), msg_data.get()); + messaging_menu_app_append_message(m_messaging_app.get(), msg, m_app_name.c_str(), false); + + // we use that to keep track of messaging, in case of message get cleared from menu + g_object_set_data_full(G_OBJECT(msg), "destroy-notify", msg_data.get(), on_message_destroyed); + // keep the message control with message_menu + g_object_unref(msg); + return message_id; } else { g_warning("Fail to create messaging menu message"); @@ -312,8 +320,8 @@ public: if (it != m_messaging_messages.end()) { // tell the server to remove message - messaging_menu_app_remove_message(m_messaging_app.get(), it->second.mm.get()); - m_messaging_messages.erase(it); + messaging_menu_app_remove_message_by_id(m_messaging_app.get(), it->second->msg_id.c_str()); + // message will be remove by on_message_destroyed cb. } } @@ -370,20 +378,26 @@ private: static_cast(gself)->remove_closed_notification(GPOINTER_TO_INT(gkey)); } - static void on_message_activated (MessagingMenuMessage *msg, + static void on_message_activated (MessagingMenuMessage *, const char *, GVariant *, - gpointer gself) + gpointer data) { - auto self = static_cast(gself); - auto it = self->m_messaging_messages.find(messaging_menu_message_get_id(msg)); - g_return_if_fail (it != self->m_messaging_messages.end()); + auto msg_data = static_cast(data); + auto it = msg_data->self->m_messaging_messages.find(msg_data->msg_id.c_str()); + g_return_if_fail (it != msg_data->self->m_messaging_messages.end()); const auto& ndata = it->second; - if (ndata.callback) - ndata.callback(); + if (ndata->callback) + ndata->callback(); + } - self->m_messaging_messages.erase(it); + static void on_message_destroyed(gpointer data) + { + auto msg_data = static_cast(data); + auto it = msg_data->self->m_messaging_messages.find(msg_data->msg_id.c_str()); + if (it != msg_data->self->m_messaging_messages.end()) + msg_data->self->m_messaging_messages.erase(it); } void remove_closed_notification (int key) @@ -418,7 +432,7 @@ private: // messaging menu std::shared_ptr m_messaging_app; - std::map m_messaging_messages; + std::map > m_messaging_messages; const std::string m_app_name; -- cgit v1.2.3