From 40bf3d2fd4c2465a2d21d5a6629691d0dc2dd4a1 Mon Sep 17 00:00:00 2001 From: LAGonauta Date: Tue, 23 Feb 2021 07:08:56 -0300 Subject: [PATCH] Actions can stack --- .../gobject/winrt-toast-notification.h | 2 +- .../src/gobject/winrt-toast-notification.cpp | 99 +++++++++++-------- plugins/windows-notification/src/plugin.vala | 2 +- .../vapi/winrt_windows_ui_notifications.vapi | 2 +- 4 files changed, 63 insertions(+), 42 deletions(-) diff --git a/plugins/windows-notification/api/include/gobject/winrt-toast-notification.h b/plugins/windows-notification/api/include/gobject/winrt-toast-notification.h index 373c0eab..92bf1a7f 100644 --- a/plugins/windows-notification/api/include/gobject/winrt-toast-notification.h +++ b/plugins/windows-notification/api/include/gobject/winrt-toast-notification.h @@ -41,7 +41,7 @@ void winrt_windows_ui_notifications_toast_notification_set_Group(winrtWindowsUIN gchar* winrt_windows_ui_notifications_toast_notification_get_Group(winrtWindowsUINotificationsToastNotification* self); winrtEventToken* winrt_windows_ui_notifications_toast_notification_Activated(winrtWindowsUINotificationsToastNotification* self, NotificationCallbackActivated callback, void* context, void(*free)(void*)); -void winrt_windows_ui_notifications_toast_notification_RemoveActivatedAction(winrtWindowsUINotificationsToastNotification* self, winrtEventToken* token); +void winrt_windows_ui_notifications_toast_notification_RemoveActivated(winrtWindowsUINotificationsToastNotification* self, winrtEventToken* token); winrtEventToken* winrt_windows_ui_notifications_toast_notification_Failed(winrtWindowsUINotificationsToastNotification* self, NotificationCallbackSimple callback, void* context, void(*free)(void*)); //winrtEventToken* winrt_windows_ui_notifications_toast_notification_Dismissed(winrtWindowsUINotificationsToastNotification* self, NotificationCallbackDismissed callback, void* context, void(*free)(void*)); diff --git a/plugins/windows-notification/api/src/gobject/winrt-toast-notification.cpp b/plugins/windows-notification/api/src/gobject/winrt-toast-notification.cpp index 0b077112..dac44880 100644 --- a/plugins/windows-notification/api/src/gobject/winrt-toast-notification.cpp +++ b/plugins/windows-notification/api/src/gobject/winrt-toast-notification.cpp @@ -22,22 +22,45 @@ public: T callback; void* context; void(*free)(void*); - winrtEventToken* token; + + Callback(T callback, void* context, void(*free)(void*)) + { + this->callback = callback; + this->free = free; + this->context = context; + } + + ~Callback() + { + Clear(); + } void Clear() { + if (this->callback && this->context && this->free) + { + this->free(this->context); + } + callback = nullptr; context = nullptr; free = nullptr; - g_clear_object(&token); } + + // delete copy + Callback(const Callback&) = delete; + Callback& operator=(const Callback&) = delete; + + // allow move + Callback(Callback&&) = default; + Callback& operator=(Callback&&) = default; }; typedef struct { - Callback activated; + std::unordered_map> activated; - Callback failed; + std::unordered_map> failed; // Notification_Callback_Dismissed callback; // void* context; @@ -52,26 +75,30 @@ static void winrt_windows_ui_notifications_toast_notification_finalize(GObject* { winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE (self); - if (winrt_event_token_operator_bool(priv->activated.token)) + for (const auto& item : priv->activated) { - priv->notification->data.Activated(*winrt_event_token_get_internal(priv->activated.token)); - g_clear_object(&priv->activated.token); + auto token = std::get<0>(item); + if (winrt_event_token_operator_bool(token)) + { + priv->notification->data.Activated(*winrt_event_token_get_internal(token)); + } + g_object_unref(token); } + priv->activated.clear(); + + for (const auto& item : priv->failed) + { + auto token = std::get<0>(item); + if (winrt_event_token_operator_bool(token)) + { + priv->notification->data.Failed(*winrt_event_token_get_internal(token)); + } + g_object_unref(token); + } + priv->failed.clear(); delete priv->notification; - if (priv->activated.callback && priv->activated.context && priv->activated.free) - { - priv->activated.free(priv->activated.context); - priv->activated.Clear(); - } - - if (priv->failed.callback && priv->failed.context && priv->failed.free) - { - priv->failed.free(priv->failed.context); - priv->failed.Clear(); - } - G_OBJECT_CLASS(winrt_windows_ui_notifications_toast_notification_parent_class)->dispose(self); } @@ -200,13 +227,7 @@ winrtEventToken* winrt_windows_ui_notifications_toast_notification_Activated(win g_return_val_if_fail (WINRT_IS_WINDOWS_UI_NOTIFICATIONS_TOAST_NOTIFICATION (self), NULL); g_return_val_if_fail (callback != nullptr && context != nullptr && free != nullptr, NULL); - winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE(self); - - winrt_windows_ui_notifications_toast_notification_RemoveActivatedAction(self, priv->activated.token); - - priv->activated.callback = callback; - priv->activated.context = context; - priv->activated.free = free; + winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE(self); auto token = priv->notification->data.Activated([&](auto sender, winrt::Windows::Foundation::IInspectable inspectable) { @@ -233,30 +254,30 @@ winrtEventToken* winrt_windows_ui_notifications_toast_notification_Activated(win } std::cout << "Notification activated!" << std::endl; - priv->activated.callback(wsview_to_char(arguments.data()), nullptr /* user_input */ , 0 /* user_input.size() */, priv->activated.context); + callback(wsview_to_char(arguments.data()), nullptr /* user_input */ , 0 /* user_input.size() */, context); }); - priv->activated.token = winrt_event_token_new_from_token(&token); - g_object_ref(priv->activated.token); - return priv->activated.token; + auto new_token = winrt_event_token_new_from_token(&token); + g_object_ref(new_token); + + priv->activated.emplace(new_token, Callback(callback, context, free)); + return new_token; } -void winrt_windows_ui_notifications_toast_notification_RemoveActivatedAction(winrtWindowsUINotificationsToastNotification* self, winrtEventToken* token) +void winrt_windows_ui_notifications_toast_notification_RemoveActivated(winrtWindowsUINotificationsToastNotification* self, winrtEventToken* token) { g_return_if_fail (WINRT_IS_WINDOWS_UI_NOTIFICATIONS_TOAST_NOTIFICATION (self)); winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE(self); - if (winrt_event_token_get_value(token) == winrt_event_token_get_value(priv->activated.token)) + auto item = priv->activated.find(token); + if (item != priv->activated.end()) { - if (winrt_event_token_operator_bool(token)) + auto local_token = std::get<0>(*item); + if (winrt_event_token_operator_bool(local_token)) { - priv->notification->data.Activated(*winrt_event_token_get_internal(token)); + priv->notification->data.Activated(*winrt_event_token_get_internal(local_token)); } - if (priv->activated.callback && priv->activated.context && priv->activated.free) - { - priv->activated.free(priv->activated.context); - priv->activated.Clear(); - } + priv->activated.erase(item); } } \ No newline at end of file diff --git a/plugins/windows-notification/src/plugin.vala b/plugins/windows-notification/src/plugin.vala index 31207e1d..3a6b3758 100644 --- a/plugins/windows-notification/src/plugin.vala +++ b/plugins/windows-notification/src/plugin.vala @@ -31,7 +31,7 @@ public class Plugin : RootInterface, Object { var token = m.Activated((c, d) => { var i = 2; }); - m.RemoveActivatedAction(token); + m.RemoveActivated(token); var h = m.ExpiresOnReboot; m.ExpiresOnReboot = false; diff --git a/plugins/windows-notification/vapi/winrt_windows_ui_notifications.vapi b/plugins/windows-notification/vapi/winrt_windows_ui_notifications.vapi index c3bdc251..f127327f 100644 --- a/plugins/windows-notification/vapi/winrt_windows_ui_notifications.vapi +++ b/plugins/windows-notification/vapi/winrt_windows_ui_notifications.vapi @@ -16,7 +16,7 @@ namespace winrt.Windows.UI.Notifications { public string Tag { get; set; } // TODO: check if valac is cleaning this string public string Group { get; set; } public winrt.EventToken Activated(owned NotificationCallbackActivated handler); - public void RemoveActivatedAction(winrt.EventToken token); + public void RemoveActivated(winrt.EventToken token); } [CCode (type_id = "winrt_windows_ui_notifications_toast_notifier_get_type ()")]