Fields must be created in the private struct

Also change unordered_map to list, we do not need hashing and stuff.
This commit is contained in:
LAGonauta 2021-02-23 22:05:02 -03:00
parent 91d61843f2
commit 6cdaad315a
6 changed files with 91 additions and 65 deletions

View file

@ -2,7 +2,9 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include <list>
#include <tuple> #include <tuple>
#include <memory>
#include "winrt-toast-notification-private.h" #include "winrt-toast-notification-private.h"
#include "winrt-event-token-private.h" #include "winrt-event-token-private.h"
@ -11,23 +13,19 @@
#define WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE(obj) \ #define WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE(obj) \
((winrtWindowsUINotificationsToastNotificationPrivate*) winrt_windows_ui_notifications_toast_notification_get_instance_private ((winrtWindowsUINotificationsToastNotification*) (obj))) ((winrtWindowsUINotificationsToastNotificationPrivate*) winrt_windows_ui_notifications_toast_notification_get_instance_private ((winrtWindowsUINotificationsToastNotification*) (obj)))
typedef struct
{
winrt::Windows::UI::Notifications::ToastNotification data;
} _winrtWindowsUINotificationsToastNotificationPrivate;
template<class T> template<class T>
class Callback { struct Callback {
public:
T callback; T callback;
void* context; void* context;
void(*free)(void*); void(*free)(void*);
winrtEventToken* token;
Callback(T callback, void* context, void(*free)(void*)) Callback(T callback, void* context, void(*free)(void*), winrtEventToken* token)
{ {
this->callback = callback; this->callback = callback;
this->free = free; this->free = free;
this->context = context; this->context = context;
this->token = token;
} }
~Callback() ~Callback()
@ -42,30 +40,32 @@ public:
this->free(this->context); this->free(this->context);
} }
callback = nullptr; this->callback = nullptr;
context = nullptr; this->context = nullptr;
free = nullptr; this->free = nullptr;
this->token = nullptr;
} }
// delete copy // delete copy
Callback(const Callback&) = delete; Callback(const Callback&) = delete;
Callback& operator=(const Callback&) = delete; Callback& operator=(const Callback&) = delete;
// allow move // delete move
Callback(Callback&&) = default; Callback(Callback&&) = delete;
Callback& operator=(Callback&&) = default; Callback& operator=(Callback&&) = delete;
};
struct _winrtWindowsUINotificationsToastNotificationPrivate
{
winrt::Windows::UI::Notifications::ToastNotification data;
std::list<std::shared_ptr<Callback<NotificationCallbackActivated>>> activated;
std::list<std::shared_ptr<Callback<NotificationCallbackSimple>>> failed;
std::list<std::shared_ptr<Callback<NotificationCallbackSimple>>> dismissed;
}; };
typedef struct typedef struct
{ {
std::unordered_map<winrtEventToken*, Callback<NotificationCallbackActivated>> activated;
std::unordered_map<winrtEventToken*, Callback<NotificationCallbackSimple>> failed;
// Notification_Callback_Dismissed callback;
// void* context;
// void(*free)(void*);
_winrtWindowsUINotificationsToastNotificationPrivate* notification; _winrtWindowsUINotificationsToastNotificationPrivate* notification;
} winrtWindowsUINotificationsToastNotificationPrivate; } winrtWindowsUINotificationsToastNotificationPrivate;
@ -75,27 +75,25 @@ static void winrt_windows_ui_notifications_toast_notification_finalize(GObject*
{ {
winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE (self); winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE (self);
for (const auto& item : priv->activated) for (const auto& item : priv->notification->activated)
{ {
auto token = std::get<0>(item); auto token = item->token;
if (winrt_event_token_operator_bool(token)) if (winrt_event_token_operator_bool(token))
{ {
priv->notification->data.Activated(*winrt_event_token_get_internal(token)); priv->notification->data.Activated(*winrt_event_token_get_internal(token));
} }
g_object_unref(token); g_object_unref(token);
} }
priv->activated.clear();
for (const auto& item : priv->failed) for (const auto& item : priv->notification->failed)
{ {
auto token = std::get<0>(item); auto token = item->token;
if (winrt_event_token_operator_bool(token)) if (winrt_event_token_operator_bool(token))
{ {
priv->notification->data.Failed(*winrt_event_token_get_internal(token)); priv->notification->data.Failed(*winrt_event_token_get_internal(token));
} }
g_object_unref(token); g_object_unref(token);
} }
priv->failed.clear();
delete priv->notification; delete priv->notification;
@ -155,7 +153,7 @@ void winrt_windows_ui_notifications_toast_notification_set_internal(winrtWindows
*/ */
winrtWindowsUINotificationsToastNotification* winrt_windows_ui_notifications_toast_notification_new(const char* doc) winrtWindowsUINotificationsToastNotification* winrt_windows_ui_notifications_toast_notification_new(const char* doc)
{ {
g_return_val_if_fail (doc == NULL, NULL); g_return_val_if_fail (doc != NULL, NULL);
auto ret = static_cast<winrtWindowsUINotificationsToastNotification*>(g_object_new (WINRT_TYPE_WINDOWS_UI_NOTIFICATIONS_TOAST_NOTIFICATION, NULL)); auto ret = static_cast<winrtWindowsUINotificationsToastNotification*>(g_object_new (WINRT_TYPE_WINDOWS_UI_NOTIFICATIONS_TOAST_NOTIFICATION, NULL));
winrt::Windows::Data::Xml::Dom::XmlDocument xmlDoc; winrt::Windows::Data::Xml::Dom::XmlDocument xmlDoc;
@ -229,7 +227,7 @@ winrtEventToken* winrt_windows_ui_notifications_toast_notification_Activated(win
winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE(self); winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE(self);
auto token = priv->notification->data.Activated([&](auto sender, winrt::Windows::Foundation::IInspectable inspectable) auto token = priv->notification->data.Activated([=](auto sender, winrt::Windows::Foundation::IInspectable inspectable)
{ {
std::wstring arguments; std::wstring arguments;
std::vector<std::tuple<std::wstring, std::wstring>> user_input; std::vector<std::tuple<std::wstring, std::wstring>> user_input;
@ -254,12 +252,12 @@ winrtEventToken* winrt_windows_ui_notifications_toast_notification_Activated(win
} }
std::cout << "Notification activated!" << std::endl; std::cout << "Notification activated!" << std::endl;
callback(wsview_to_char(arguments.data()), nullptr /* user_input */ , 0 /* user_input.size() */, context); callback(wsview_to_char(arguments), nullptr /* user_input */ , 0 /* user_input.size() */, context);
}); });
auto new_token = winrt_event_token_new_from_token(&token); auto new_token = winrt_event_token_new_from_token(&token);
g_object_ref(new_token); g_object_ref(new_token);
priv->activated.emplace(new_token, Callback<NotificationCallbackActivated>(callback, context, free)); priv->notification->activated.push_back(std::make_shared<Callback<NotificationCallbackActivated>>(callback, context, free, new_token));
return new_token; return new_token;
} }
@ -269,15 +267,16 @@ void winrt_windows_ui_notifications_toast_notification_RemoveActivated(winrtWind
winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE(self); winrtWindowsUINotificationsToastNotificationPrivate* priv = WINRT_WINDOWS_UI_NOTIFICATION_TOAST_NOTIFICATION_GET_PRIVATE(self);
auto item = priv->activated.find(token); priv->notification->activated.remove_if([&](const auto& callback) {
if (item != priv->activated.end()) if (winrt_event_token_get_value(token) == winrt_event_token_get_value(callback->token))
{ {
auto local_token = std::get<0>(*item); if (winrt_event_token_operator_bool(callback->token))
if (winrt_event_token_operator_bool(local_token))
{ {
priv->notification->data.Activated(*winrt_event_token_get_internal(local_token)); priv->notification->data.Activated(*winrt_event_token_get_internal(callback->token));
} }
g_object_unref(callback->token);
priv->activated.erase(item); return true;
} }
return false;
});
} }

View file

@ -83,9 +83,9 @@ void winrt_windows_ui_notifications_toast_notifier_set_internal(winrtWindowsUINo
*/ */
winrtWindowsUINotificationsToastNotifier* winrt_windows_ui_notifications_toast_notifier_new(const gchar* aumid) winrtWindowsUINotificationsToastNotifier* winrt_windows_ui_notifications_toast_notifier_new(const gchar* aumid)
{ {
g_return_val_if_fail (aumid == NULL, NULL); g_return_val_if_fail (aumid != NULL, NULL);
auto ret = static_cast<winrtWindowsUINotificationsToastNotifier*>(g_object_new (WINRT_TYPE_WINDOWS_UI_NOTIFICATIONS_TOAST_NOTIFICATION, NULL)); auto ret = static_cast<winrtWindowsUINotificationsToastNotifier*>(g_object_new (WINRT_TYPE_WINDOWS_UI_NOTIFICATIONS_TOAST_NOTIFIER, NULL));
auto notifier = winrt::Windows::UI::Notifications::ToastNotificationManager::CreateToastNotifier(sview_to_wstr(aumid)); auto notifier = winrt::Windows::UI::Notifications::ToastNotificationManager::CreateToastNotifier(sview_to_wstr(aumid));
winrt_windows_ui_notifications_toast_notifier_set_internal(ret, notifier); winrt_windows_ui_notifications_toast_notifier_set_internal(ret, notifier);
return ret; return ret;

View file

@ -1,17 +1,24 @@
#include <iostream> #include <iostream>
#include "gobject/winrt-private.h" #include "gobject/winrt-private.h"
#include "converter.hpp"
gboolean winrt_InitApartment() gboolean winrt_InitApartment()
{ {
try try
{ {
winrt::init_apartment(); // TODO: FIXME, header only works with unity build winrt::init_apartment();
return true; return true;
} }
catch(const std::exception& e) catch(const winrt::hresult_error& e)
{ {
std::cerr << e.what() << '\n'; auto message = wsview_to_char(e.message());
std::cerr << message << '\n';
delete[] message;
if (e.code() == -2147417850 /* RPC_E_CHANGED_MODE */) // harmless
{
return true;
}
} }
return false; return false;

View file

@ -131,7 +131,7 @@ int32_t TryCreateShortcutInternal(const std::wstring& aumid)
if (shortcutPath && exePath) if (shortcutPath && exePath)
{ {
auto path = shortcutPath.value() + LR"(\Microsoft\Windows\Start Menu\Programs\Testando.lnk)"; auto path = shortcutPath.value() + LR"(\Microsoft\Windows\Start Menu\Programs\Dino.lnk)";
if (!std::filesystem::exists(path)) if (!std::filesystem::exists(path))
{ {
return InstallShortcut(exePath.value(), aumid, path); return InstallShortcut(exePath.value(), aumid, path);

View file

@ -1,13 +1,14 @@
using Gee; using Gee;
using Dino.Entities; using Dino.Entities;
using Dino.Plugins.WindowsNotification.Vapi; using Dino.Plugins.WindowsNotification.Vapi;
using winrt.Windows.UI.Notifications;
namespace Dino.Plugins.WindowsNotification { namespace Dino.Plugins.WindowsNotification {
public class Plugin : RootInterface, Object { public class Plugin : RootInterface, Object {
private static string AUMID = "org.dino.Dino"; private static string AUMID = "org.dino.Dino";
private ToastNotifier notifier;
public int m { get; set; } private ToastNotification notification; // Notifications remove their actions when they get out of scope
public void registered(Dino.Application app) { public void registered(Dino.Application app) {
if (!winrt.InitApartment()) if (!winrt.InitApartment())
@ -26,23 +27,40 @@ public class Plugin : RootInterface, Object {
} }
{ {
var notifier = new winrt.Windows.UI.Notifications.ToastNotifier(AUMID); var text = "<toast launch=\"action=viewPhoto&amp;photoId=92187\">
var m = new winrt.Windows.UI.Notifications.ToastNotification("Test"); <visual>
var token = m.Activated((c, d) => { <binding template=\"ToastGeneric\">
<image placement=\"appLogoOverride\" hint-crop=\"circle\" src=\"https://unsplash.it/64?image=669\"/>
<text>Adam Wilson tagged you in a photo</text>
<text>On top of McClellan Butte - with Andrew Bares</text>
<image src=\"https://unsplash.it/360/202?image=883\"/>
</binding>
</visual>
<actions>
<action
content=\"Like\"
activationType=\"background\"
arguments=\"likePhoto&amp;photoId=92187\"/>
<action
content=\"Comment\"
arguments=\"action=commentPhoto&amp;photoId=92187\"/>
</actions>
</toast>";
this.notifier = new ToastNotifier(AUMID);
this.notification = new ToastNotification(text);
var token = notification.Activated((c, d) => {
var i = 2; var i = 2;
stdout.printf("Yay! Activated 1!\n");
}); });
m.RemoveActivated(token); notification.RemoveActivated(token);
var h = m.ExpiresOnReboot; token = notification.Activated((c, d) => {
m.ExpiresOnReboot = false; var i = 2;
stdout.printf("Yay! Activated 2!\n");
});
var a = m.Tag; notifier.Show(notification);
m.Tag = "a";
a = m.Group;
m.Group = "a";
notifier.Show(m);
} }
// var provider = new WindowsNotificationProvider(app, Win32Api.SupportsModernNotifications()); // var provider = new WindowsNotificationProvider(app, Win32Api.SupportsModernNotifications());

View file

@ -1,3 +1,5 @@
using winrt;
[CCode (cheader_filename = "gobject/winrt-glib.h")] [CCode (cheader_filename = "gobject/winrt-glib.h")]
namespace winrt.Windows.UI.Notifications { namespace winrt.Windows.UI.Notifications {
[CCode (cname = "NotificationCallbackSimple", has_target = true)] [CCode (cname = "NotificationCallbackSimple", has_target = true)]
@ -15,8 +17,8 @@ namespace winrt.Windows.UI.Notifications {
public bool ExpiresOnReboot { get; set; } public bool ExpiresOnReboot { get; set; }
public string Tag { get; set; } // TODO: check if valac is cleaning this string public string Tag { get; set; } // TODO: check if valac is cleaning this string
public string Group { get; set; } public string Group { get; set; }
public winrt.EventToken Activated(owned NotificationCallbackActivated handler); public EventToken Activated(owned NotificationCallbackActivated handler);
public void RemoveActivated(winrt.EventToken token); public void RemoveActivated(EventToken token);
} }
[CCode (type_id = "winrt_windows_ui_notifications_toast_notifier_get_type ()")] [CCode (type_id = "winrt_windows_ui_notifications_toast_notifier_get_type ()")]