From 4402f6924f14847c1570b22ef06ba54125a9c41c Mon Sep 17 00:00:00 2001 From: MikalaiR Date: Fri, 28 Aug 2015 11:32:10 +0000 Subject: Toaster: hiding toasts git-svn-id: http://svn.miranda-ng.org/main/trunk@15053 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Toaster/src/main.cpp | 13 ++++++++- plugins/Toaster/src/services.cpp | 42 ++++++++++++++++++----------- plugins/Toaster/src/stdafx.h | 13 ++++++++- plugins/Toaster/src/toast_event_handler.cpp | 25 ++++++++++++++--- plugins/Toaster/src/toast_event_handler.h | 9 +++++-- plugins/Toaster/src/toast_notification.cpp | 14 +++++++--- plugins/Toaster/src/toast_notification.h | 4 +++ 7 files changed, 94 insertions(+), 26 deletions(-) diff --git a/plugins/Toaster/src/main.cpp b/plugins/Toaster/src/main.cpp index 6ce8fd69af..4f3515ffdf 100644 --- a/plugins/Toaster/src/main.cpp +++ b/plugins/Toaster/src/main.cpp @@ -39,7 +39,7 @@ extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD) extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); - + HookEvent(ME_SYSTEM_SHUTDOWN, &OnPreShutdown); InitServices(); return 0; @@ -49,3 +49,14 @@ extern "C" int __declspec(dllexport) Unload(void) { return 0; } + +int OnPreShutdown(WPARAM, LPARAM) +{ + mir_cslock lck(csNotifications); + for (int i = 0; i < lstNotifications.getCount(); i++) + lstNotifications[0].Hide(); + + lstNotifications.destroy(); + + return 0; +} \ No newline at end of file diff --git a/plugins/Toaster/src/services.cpp b/plugins/Toaster/src/services.cpp index 79e8fba2b0..1168e8cc95 100644 --- a/plugins/Toaster/src/services.cpp +++ b/plugins/Toaster/src/services.cpp @@ -1,12 +1,16 @@ #include "stdafx.h" +mir_cs csNotifications; +OBJLIST lstNotifications(1); + __forceinline bool isChatRoom(MCONTACT hContact) -{ return (bool)db_get_b(hContact, GetContactProto(hContact), "ChatRoom", 0); +{ return (db_get_b(hContact, GetContactProto(hContact), "ChatRoom", 0) == 1); } static void __cdecl OnToastNotificationClicked(void* arg) { - MCONTACT hContact = (MCONTACT)arg; + callbackArg *cb = (callbackArg*)arg; + MCONTACT hContact = cb->hContact; if (hContact) { if (!isChatRoom(hContact)) @@ -16,13 +20,13 @@ static void __cdecl OnToastNotificationClicked(void* arg) else { const char *szProto = GetContactProto(hContact); - ptrT szChatRoom(db_get_tsa(hContact, szProto, "ChatRoomID")); - GCDEST gcd = { szProto, szChatRoom, GC_EVENT_CONTROL }; + ptrT tszChatRoom(db_get_tsa(hContact, szProto, "ChatRoomID")); + GCDEST gcd = { szProto, tszChatRoom, GC_EVENT_CONTROL }; GCEVENT gce = { sizeof(gce), &gcd }; - gce.time = time(NULL); - CallServiceSync(MS_GC_EVENT, WINDOW_VISIBLE, reinterpret_cast(&gce)); + CallServiceSync(MS_GC_EVENT, WINDOW_VISIBLE, (LPARAM)&gce); } } + lstNotifications.remove(cb->notification); } static void ShowToastNotification(TCHAR* text, TCHAR* title, MCONTACT hContact) @@ -31,25 +35,25 @@ static void ShowToastNotification(TCHAR* text, TCHAR* title, MCONTACT hContact) return; ptrT imagePath; - ToastEventHandler *eventHandler; + callbackArg *arg = (callbackArg*)mir_calloc(sizeof(callbackArg)); if (hContact) { - eventHandler = new ToastEventHandler(OnToastNotificationClicked, (void*)hContact); - + arg->hContact = hContact; const char* szProto = GetContactProto(hContact); - PROTO_AVATAR_INFORMATION pai = { 0 }; - pai.hContact = hContact; + if (ProtoServiceExists(szProto, PS_GETAVATARINFO)) { + PROTO_AVATAR_INFORMATION pai = { 0 }; + pai.hContact = hContact; CallProtoService(szProto, PS_GETAVATARINFO, (WPARAM)0, (LPARAM)&pai); imagePath = mir_tstrdup(pai.filename); } } - else - eventHandler = new ToastEventHandler(nullptr); - ToastNotification notification(text, title, imagePath); - notification.Show(eventHandler); + ToastNotification* notification = new ToastNotification (text, title, imagePath); + arg->notification = notification; + notification->Show(new ToastEventHandler(OnToastNotificationClicked, arg)); + lstNotifications.insert(notification); } static INT_PTR CreatePopup(WPARAM wParam, LPARAM) @@ -107,6 +111,14 @@ static INT_PTR PopupQuery(WPARAM wParam, LPARAM) { bool enabled = db_get_b(0, "Popup", "ModuleIsEnabled", 1) != 0; if (enabled) db_set_b(0, "Popup", "ModuleIsEnabled", 0); + + while (lstNotifications.getCount()) + { + mir_cslock lck(csNotifications); + lstNotifications[0].Hide(); + lstNotifications.remove(0); + } + return enabled; } break; diff --git a/plugins/Toaster/src/stdafx.h b/plugins/Toaster/src/stdafx.h index a113024828..8df66f4598 100644 --- a/plugins/Toaster/src/stdafx.h +++ b/plugins/Toaster/src/stdafx.h @@ -13,6 +13,8 @@ #include #include +#include +#include #include #include #include @@ -33,10 +35,19 @@ const wchar_t AppUserModelID[] = _T("MirandaNG"); #include "toast_event_handler.h" #include "toast_notification.h" +extern mir_cs csNotifications; +extern OBJLIST lstNotifications; + +struct callbackArg +{ + MCONTACT hContact; + ToastNotification* notification; +}; + #define MODULE "Toaster" extern HINSTANCE g_hInstance; void InitServices(); - +int OnPreShutdown(WPARAM, LPARAM); #endif //_COMMON_H_ diff --git a/plugins/Toaster/src/toast_event_handler.cpp b/plugins/Toaster/src/toast_event_handler.cpp index e2ed29e165..c7f43ad115 100644 --- a/plugins/Toaster/src/toast_event_handler.cpp +++ b/plugins/Toaster/src/toast_event_handler.cpp @@ -1,5 +1,7 @@ #include "stdafx.h" +using namespace ABI::Windows::UI::Notifications; + ToastEventHandler::ToastEventHandler() : _ref(1), _callback(nullptr), _arg(nullptr) { } @@ -30,10 +32,13 @@ IFACEMETHODIMP ToastEventHandler::QueryInterface(_In_ REFIID riid, _COM_Outptr_ *ppv = static_cast(static_cast(this)); else if (IsEqualIID(riid, __uuidof(DesktopToastActivatedEventHandler))) *ppv = static_cast(this); + else if (IsEqualIID(riid, __uuidof(DesktopToastDismissedEventHandler))) + *ppv = static_cast(this); + else if (IsEqualIID(riid, __uuidof(DesktopToastFailedEventHandler))) + *ppv = static_cast(this); else *ppv = nullptr; - if (*ppv) - { + if (*ppv) { reinterpret_cast(*ppv)->AddRef(); return S_OK; } @@ -41,10 +46,24 @@ IFACEMETHODIMP ToastEventHandler::QueryInterface(_In_ REFIID riid, _COM_Outptr_ return E_NOINTERFACE; } -IFACEMETHODIMP ToastEventHandler::Invoke(_In_ ABI::Windows::UI::Notifications::IToastNotification* /* sender */, _In_::IInspectable* /* args */) +IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IInspectable* /* args */) { if (_callback != nullptr) _callback(_arg); return S_OK; } + +IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastDismissedEventArgs* /* e */) +{ + callbackArg *cb = (callbackArg*)_arg; + lstNotifications.remove(cb->notification); + return S_OK; +} + +IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */, _In_ IToastFailedEventArgs* /* e */) +{ + callbackArg *cb = (callbackArg*)_arg; + lstNotifications.remove(cb->notification); + return S_OK; +} \ No newline at end of file diff --git a/plugins/Toaster/src/toast_event_handler.h b/plugins/Toaster/src/toast_event_handler.h index 10d2f1422f..8cf82b3e21 100644 --- a/plugins/Toaster/src/toast_event_handler.h +++ b/plugins/Toaster/src/toast_event_handler.h @@ -1,9 +1,12 @@ #ifndef _TOAST_EVENT_HANDLER_H_ #define _TOAST_EVENT_HANDLER_H_ -typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastActivatedEventHandler; +typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastActivatedEventHandler; +typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastDismissedEventHandler; +typedef ABI::Windows::Foundation::ITypedEventHandler DesktopToastFailedEventHandler; -class ToastEventHandler : public Microsoft::WRL::Implements> + +class ToastEventHandler : public Microsoft::WRL::Implements { public: ToastEventHandler::ToastEventHandler(); @@ -16,6 +19,8 @@ public: IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppv); IFACEMETHODIMP Invoke(_In_ ABI::Windows::UI::Notifications::IToastNotification* sender, _In_ IInspectable* args); + IFACEMETHODIMP Invoke(_In_ ABI::Windows::UI::Notifications::IToastNotification* /* sender */, _In_ ABI::Windows::UI::Notifications::IToastDismissedEventArgs* e); + IFACEMETHODIMP Invoke(_In_ ABI::Windows::UI::Notifications::IToastNotification* /* sender */, _In_ ABI::Windows::UI::Notifications::IToastFailedEventArgs* /* e */); private: ULONG _ref; diff --git a/plugins/Toaster/src/toast_notification.cpp b/plugins/Toaster/src/toast_notification.cpp index 9e3ad1b915..7d11f9318e 100644 --- a/plugins/Toaster/src/toast_notification.cpp +++ b/plugins/Toaster/src/toast_notification.cpp @@ -215,21 +215,27 @@ HRESULT ToastNotification::Show(_In_ ToastEventHandler* handler) if (FAILED(hr)) RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); - Microsoft::WRL::ComPtr notifier; hr = notificationManager->CreateToastNotifierWithId(StringReferenceWrapper(::AppUserModelID).Get(), ¬ifier); if (FAILED(hr)) return hr; - - Microsoft::WRL::ComPtr notification; hr = Create(¬ification); if (FAILED(hr)) return hr; - EventRegistrationToken activatedToken; + EventRegistrationToken activatedToken, dismissedToken, failedToken; Microsoft::WRL::ComPtr eventHandler(handler); hr = notification->add_Activated(eventHandler.Get(), &activatedToken); if (FAILED(hr)) return hr; + notification->add_Activated(eventHandler.Get(), &activatedToken); + notification->add_Dismissed(eventHandler.Get(), &dismissedToken); + notification->add_Failed(eventHandler.Get(), &failedToken); + return notifier->Show(notification.Get()); +} + +HRESULT ToastNotification::Hide() +{ + return notifier->Hide(notification.Get()); } \ No newline at end of file diff --git a/plugins/Toaster/src/toast_notification.h b/plugins/Toaster/src/toast_notification.h index 727966ac8f..0e4131b945 100644 --- a/plugins/Toaster/src/toast_notification.h +++ b/plugins/Toaster/src/toast_notification.h @@ -8,6 +8,9 @@ private: wchar_t* _caption; wchar_t* _imagePath; + Microsoft::WRL::ComPtr notifier; + Microsoft::WRL::ComPtr notification; + HRESULT GetNodeByTag(_In_ HSTRING tagName, _Outptr_ ABI::Windows::Data::Xml::Dom::IXmlNode **node, _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument* xml); HRESULT AddNode(_In_ HSTRING name, _Outptr_ ABI::Windows::Data::Xml::Dom::IXmlNode **node, _In_ ABI::Windows::Data::Xml::Dom::IXmlNode *rootNode, _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument* xml); HRESULT SetNodeValueString(_In_ HSTRING inputString, _In_ ABI::Windows::Data::Xml::Dom::IXmlNode* node, _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument* xml); @@ -26,6 +29,7 @@ public: HRESULT Show(); HRESULT Show(_In_ ToastEventHandler* handler); + HRESULT Hide(); }; #endif //_TOAST_NOTIFICATION_H_ \ No newline at end of file -- cgit v1.2.3