diff --git a/atom/browser/api/atom_api_notification.cc b/atom/browser/api/atom_api_notification.cc index 9812852ce6..502184c2eb 100644 --- a/atom/browser/api/atom_api_notification.cc +++ b/atom/browser/api/atom_api_notification.cc @@ -4,6 +4,7 @@ #include "atom/browser/api/atom_api_notification.h" +#include #include #include "atom/browser/api/atom_api_menu.h" @@ -25,7 +26,9 @@ namespace api { int id_counter = 1; std::map notifications_; -Notification::Notification(v8::Isolate* isolate, v8::Local wrapper, mate::Arguments* args) { +Notification::Notification(v8::Isolate* isolate, + v8::Local wrapper, + mate::Arguments* args) { InitWith(isolate, wrapper); mate::Dictionary opts; @@ -65,19 +68,46 @@ Notification* Notification::FromID(int id) { } // Getters -int Notification::GetID() { return id_; } -base::string16 Notification::GetTitle() { return title_; } -base::string16 Notification::GetBody() { return body_; } -bool Notification::GetSilent() { return silent_; } -base::string16 Notification::GetReplyPlaceholder() { return reply_placeholder_; } -bool Notification::GetHasReply() { return has_reply_; } +int Notification::GetID() { + return id_; +} +base::string16 Notification::GetTitle() { + return title_; +} +base::string16 Notification::GetBody() { + return body_; +} +bool Notification::GetSilent() { + return silent_; +} +base::string16 Notification::GetReplyPlaceholder() { + return reply_placeholder_; +} +bool Notification::GetHasReply() { + return has_reply_; +} // Setters -void Notification::SetTitle(base::string16 new_title) { title_ = new_title; NotifyPropsUpdated(); } -void Notification::SetBody(base::string16 new_body) { body_ = new_body; NotifyPropsUpdated(); } -void Notification::SetSilent(bool new_silent) { silent_ = new_silent; NotifyPropsUpdated(); } -void Notification::SetReplyPlaceholder(base::string16 new_reply_placeholder) { reply_placeholder_ = new_reply_placeholder; NotifyPropsUpdated(); } -void Notification::SetHasReply(bool new_has_reply) { has_reply_ = new_has_reply; NotifyPropsUpdated(); } +void Notification::SetTitle(base::string16 new_title) { + title_ = new_title; + NotifyPropsUpdated(); +} +void Notification::SetBody(base::string16 new_body) { + body_ = new_body; + NotifyPropsUpdated(); +} +void Notification::SetSilent(bool new_silent) { + silent_ = new_silent; + NotifyPropsUpdated(); +} +void Notification::SetReplyPlaceholder(base::string16 new_reply_placeholder) { + reply_placeholder_ = new_reply_placeholder; + NotifyPropsUpdated(); +} +void Notification::SetHasReply(bool new_has_reply) { + has_reply_ = new_has_reply; + NotifyPropsUpdated(); +} void Notification::OnClicked() { Emit("click"); @@ -93,7 +123,7 @@ void Notification::OnShown() { // static void Notification::BuildPrototype(v8::Isolate* isolate, - v8::Local prototype) { + v8::Local prototype) { prototype->SetClassName(mate::StringToV8(isolate, "Notification")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .MakeDestroyable() @@ -102,26 +132,30 @@ void Notification::BuildPrototype(v8::Isolate* isolate, .SetProperty("title", &Notification::GetTitle, &Notification::SetTitle) .SetProperty("body", &Notification::GetBody, &Notification::SetBody) .SetProperty("silent", &Notification::GetSilent, &Notification::SetSilent) - .SetProperty("replyPlaceholder", &Notification::GetReplyPlaceholder, &Notification::SetReplyPlaceholder) - .SetProperty("hasReply", &Notification::GetHasReply, &Notification::SetHasReply); + .SetProperty("replyPlaceholder", &Notification::GetReplyPlaceholder, + &Notification::SetReplyPlaceholder) + .SetProperty("hasReply", &Notification::GetHasReply, + &Notification::SetHasReply); } } // namespace api } // namespace atom - namespace { using atom::api::Notification; -void Initialize(v8::Local exports, v8::Local unused, - v8::Local context, void* priv) { +void Initialize(v8::Local exports, + v8::Local unused, + v8::Local context, + void* priv) { v8::Isolate* isolate = context->GetIsolate(); Notification::SetConstructor(isolate, base::Bind(&Notification::New)); mate::Dictionary dict(isolate, exports); - dict.Set("Notification", Notification::GetConstructor(isolate)->GetFunction()); + dict.Set("Notification", + Notification::GetConstructor(isolate)->GetFunction()); } } // namespace diff --git a/atom/browser/api/atom_api_notification.h b/atom/browser/api/atom_api_notification.h index 6704b84f46..7882c145f7 100644 --- a/atom/browser/api/atom_api_notification.h +++ b/atom/browser/api/atom_api_notification.h @@ -20,7 +20,7 @@ namespace atom { namespace api { class Notification : public mate::TrackableObject, - public NotifictionObserver { + public NotifictionObserver { public: static mate::WrappableBase* New(mate::Arguments* args); static bool HasID(int id); @@ -35,7 +35,9 @@ class Notification : public mate::TrackableObject, void OnShown() override; protected: - Notification(v8::Isolate* isolate, v8::Local wrapper, mate::Arguments* args); + Notification(v8::Isolate* isolate, + v8::Local wrapper, + mate::Arguments* args); ~Notification() override; void OnInitialProps(); diff --git a/atom/browser/api/atom_api_notification_win.cc b/atom/browser/api/atom_api_notification_win.cc index c92a1b2ce7..c740fa9a9e 100644 --- a/atom/browser/api/atom_api_notification_win.cc +++ b/atom/browser/api/atom_api_notification_win.cc @@ -48,7 +48,8 @@ void Notification::Show() { if (can_toast_) { atom::AtomToastHandler* handler = new atom::AtomToastHandler(this); - WinToastLib::WinToastTemplate::WinToastTemplateType toastType = WinToastLib::WinToastTemplate::TextOneLine; + WinToastLib::WinToastTemplate::WinToastTemplateType toastType = + WinToastLib::WinToastTemplate::TextOneLine; if (!has_icon_) { if (body_ != L"") { toastType = WinToastLib::WinToastTemplate::TextTwoLines; @@ -62,40 +63,41 @@ void Notification::Show() { toastType = WinToastLib::WinToastTemplate::ImageWithOneLine; } } - WinToastLib::WinToastTemplate toast = WinToastLib::WinToastTemplate(toastType); + WinToastLib::WinToastTemplate toast = + WinToastLib::WinToastTemplate(toastType); - std::string filename = base::MD5String(base::UTF16ToUTF8(icon_path_)) + ".png"; - base::FilePath savePath = temp_dir_.GetPath().Append(base::UTF8ToUTF16(filename)); + std::string filename = + base::MD5String(base::UTF16ToUTF8(icon_path_)) + ".png"; + base::FilePath savePath = + temp_dir_.GetPath().Append(base::UTF8ToUTF16(filename)); if (has_icon_ && SaveIconToPath(image, savePath)) { toast.setImagePath(savePath.value()); } - toast.setTextField(title_, WinToastLib::WinToastTemplate::TextField::FirstLine); - toast.setTextField(body_, WinToastLib::WinToastTemplate::TextField::SecondLine); + toast.setTextField(title_, + WinToastLib::WinToastTemplate::TextField::FirstLine); + toast.setTextField(body_, + WinToastLib::WinToastTemplate::TextField::SecondLine); toast.setSilent(silent_); WinToastLib::WinToast::instance()->showToast(toast, handler); OnShown(); } else { - AtomNotificationDelegateAdapter* adapter = new AtomNotificationDelegateAdapter(this); + AtomNotificationDelegateAdapter* adapter = + new AtomNotificationDelegateAdapter(this); auto notif = presenter->CreateNotification(adapter); GURL nullUrl = *(new GURL); - notif->Show( - title_, - body_, - "", - nullUrl, - image, - silent_ - ); + notif->Show(title_, body_, "", nullUrl, image, silent_); } } void Notification::OnInitialProps() { if (!initialized_) { Browser* browser = Browser::Get(); - WinToastLib::WinToast::instance()->setAppName(base::UTF8ToUTF16(browser->GetName())); - WinToastLib::WinToast::instance()->setAppUserModelId(browser->GetAppUserModelID()); + WinToastLib::WinToast::instance()->setAppName( + base::UTF8ToUTF16(browser->GetName())); + WinToastLib::WinToast::instance()->setAppUserModelId( + browser->GetAppUserModelID()); can_toast_ = WinToastLib::WinToast::instance()->initialize(); temp_dir_.CreateUniqueTempDir(); } @@ -104,10 +106,6 @@ void Notification::OnInitialProps() { } } -void Notification::NotifyPropsUpdated() { - -} - -} - -} \ No newline at end of file +void Notification::NotifyPropsUpdated() {} +} // namespace api +} // namespace atom diff --git a/atom/browser/ui/notification_delegate_adapter.cc b/atom/browser/ui/notification_delegate_adapter.cc index bea8f3f296..d141be43ea 100644 --- a/atom/browser/ui/notification_delegate_adapter.cc +++ b/atom/browser/ui/notification_delegate_adapter.cc @@ -1,3 +1,7 @@ +// Copyright (c) 2014 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + #include "atom/browser/ui/notification_delegate_adapter.h" #include "atom/browser/api/atom_api_notification.h" @@ -5,17 +9,18 @@ namespace atom { -AtomNotificationDelegateAdapter::AtomNotificationDelegateAdapter(atom::api::Notification* target) { - observer_ = target; +AtomNotificationDelegateAdapter::AtomNotificationDelegateAdapter( + atom::api::Notification* target) { + observer_ = target; } void AtomNotificationDelegateAdapter::NotificationDisplayed() { - observer_->OnShown(); + observer_->OnShown(); } void AtomNotificationDelegateAdapter::NotificationClosed() {} void AtomNotificationDelegateAdapter::NotificationClick() { - observer_->OnClicked(); + observer_->OnClicked(); } void AtomNotificationDelegateAdapter::NotificationDestroyed() {} void AtomNotificationDelegateAdapter::NotificationFailed() {} -} \ No newline at end of file +} // namespace atom diff --git a/atom/browser/ui/notification_delegate_adapter.h b/atom/browser/ui/notification_delegate_adapter.h index 2bbbc0512a..89e06e3ad1 100644 --- a/atom/browser/ui/notification_delegate_adapter.h +++ b/atom/browser/ui/notification_delegate_adapter.h @@ -12,17 +12,17 @@ namespace atom { class AtomNotificationDelegateAdapter : public brightray::NotificationDelegate { - public: - atom::api::Notification* observer_; - AtomNotificationDelegateAdapter(atom::api::Notification* target); + public: + atom::api::Notification* observer_; + explicit AtomNotificationDelegateAdapter(atom::api::Notification* target); - void NotificationDisplayed(); - void NotificationClosed(); - void NotificationClick(); - void NotificationDestroyed(); - void NotificationFailed(); + void NotificationDisplayed(); + void NotificationClosed(); + void NotificationClick(); + void NotificationDestroyed(); + void NotificationFailed(); }; -} +} // namespace atom -#endif // ATOM_BROWSER_UI_NOTIFICATION_DELEGATE_ADAPTER_H_ \ No newline at end of file +#endif // ATOM_BROWSER_UI_NOTIFICATION_DELEGATE_ADAPTER_H_ diff --git a/atom/browser/ui/notification_observer.h b/atom/browser/ui/notification_observer.h index 8619e5d360..5b1ba053ec 100644 --- a/atom/browser/ui/notification_observer.h +++ b/atom/browser/ui/notification_observer.h @@ -5,6 +5,8 @@ #ifndef ATOM_BROWSER_UI_NOTIFICATION_OBSERVER_H_ #define ATOM_BROWSER_UI_NOTIFICATION_OBSERVER_H_ +#include + namespace atom { class NotifictionObserver { diff --git a/atom/browser/ui/win/toast_handler.cc b/atom/browser/ui/win/toast_handler.cc index 5108c63020..6ce01ef371 100644 --- a/atom/browser/ui/win/toast_handler.cc +++ b/atom/browser/ui/win/toast_handler.cc @@ -15,14 +15,15 @@ AtomToastHandler::AtomToastHandler(atom::api::Notification* target) { void AtomToastHandler::toastActivated() { observer_->OnClicked(); -}; +} -void AtomToastHandler::toastDismissed(WinToastLib::WinToastHandler::WinToastDismissalReason state) { +void AtomToastHandler::toastDismissed( + WinToastLib::WinToastHandler::WinToastDismissalReason state) { // observer_->OnDismissed(); -}; +} void AtomToastHandler::toastFailed() { // observer_->OnErrored(); -}; - } + +} // namespace atom diff --git a/atom/browser/ui/win/toast_handler.h b/atom/browser/ui/win/toast_handler.h index d88c21d32d..70b8ad6048 100644 --- a/atom/browser/ui/win/toast_handler.h +++ b/atom/browser/ui/win/toast_handler.h @@ -5,21 +5,22 @@ #include "atom/browser/ui/win/toast_lib.h" #include "atom/browser/api/atom_api_notification.h" -#ifndef ATOM_BROWSER_UI_TOAST_HANDLER_H_ -#define ATOM_BROWSER_UI_TOAST_HANDLER_H_ +#ifndef ATOM_BROWSER_UI_WIN_TOAST_HANDLER_H_ +#define ATOM_BROWSER_UI_WIN_TOAST_HANDLER_H_ namespace atom { class AtomToastHandler : public WinToastLib::WinToastHandler { public: atom::api::Notification* observer_; - AtomToastHandler(atom::api::Notification* target); + explicit AtomToastHandler(atom::api::Notification* target); void toastActivated() override; - void toastDismissed(WinToastLib::WinToastHandler::WinToastDismissalReason state); + void toastDismissed( + WinToastLib::WinToastHandler::WinToastDismissalReason state); void toastFailed(); }; -} +} // namespace atom -#endif // ATOM_BROWSER_UI_TOAST_HANDLER_H_ +#endif // ATOM_BROWSER_UI_WIN_TOAST_HANDLER_H_ diff --git a/atom/browser/ui/win/toast_lib.cc b/atom/browser/ui/win/toast_lib.cc index 3fdd657a26..1141a3d73a 100644 --- a/atom/browser/ui/win/toast_lib.cc +++ b/atom/browser/ui/win/toast_lib.cc @@ -9,8 +9,8 @@ // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -20,518 +20,589 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "toast_lib.h" -#include "browser/win/scoped_hstring.h" -#pragma comment(lib,"shlwapi") -#pragma comment(lib,"user32") +#include "atom/browser/ui/win/toast_lib.h" + +#include + +#include "browser/win/scoped_hstring.h" + +#pragma comment(lib, "shlwapi") +#pragma comment(lib, "user32") + +using WinToastLib::WinToast; +using WinToastLib::WinToastHandler; +using WinToastLib::WinToastStringWrapper; +using WinToastLib::WinToastTemplate; -using namespace WinToastLib; namespace DllImporter { - // Function load a function from library - template - HRESULT loadFunctionFromLibrary(HINSTANCE library, LPCSTR name, Function &func) { - if (!library) - return false; +// Function load a function from library +template +HRESULT loadFunctionFromLibrary(HINSTANCE library, + LPCSTR name, + Function& func) { // NOLINT + if (!library) + return false; - func = reinterpret_cast(GetProcAddress(library, name)); - return (func != nullptr) ? S_OK : E_FAIL; - } - - typedef HRESULT(FAR STDAPICALLTYPE *f_SetCurrentProcessExplicitAppUserModelID)(__in PCWSTR AppID); - typedef HRESULT(FAR STDAPICALLTYPE *f_PropVariantToString)(_In_ REFPROPVARIANT propvar, _Out_writes_(cch) PWSTR psz, _In_ UINT cch); - typedef HRESULT(FAR STDAPICALLTYPE *f_RoGetActivationFactory)(_In_ HSTRING activatableClassId, _In_ REFIID iid, _COM_Outptr_ void ** factory); - typedef HRESULT(FAR STDAPICALLTYPE *f_WindowsCreateStringReference)(_In_reads_opt_(length + 1) PCWSTR sourceString, UINT32 length, _Out_ HSTRING_HEADER * hstringHeader, _Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING * string); - typedef HRESULT(FAR STDAPICALLTYPE *f_WindowsDeleteString)(_In_opt_ HSTRING string); - - f_SetCurrentProcessExplicitAppUserModelID SetCurrentProcessExplicitAppUserModelID; - f_PropVariantToString PropVariantToString; - f_RoGetActivationFactory RoGetActivationFactory; - f_WindowsCreateStringReference WindowsCreateStringReference; - f_WindowsDeleteString WindowsDeleteString; - - - template - _Check_return_ __inline HRESULT _1_GetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ T** factory) { - return RoGetActivationFactory(activatableClassId, IID_INS_ARGS(factory)); - } - - template - inline HRESULT Wrap_GetActivationFactory(_In_ HSTRING activatableClassId, _Inout_ Details::ComPtrRef factory) throw() { - return _1_GetActivationFactory(activatableClassId, factory.ReleaseAndGetAddressOf()); - } - - inline HRESULT initialize() { - HINSTANCE LibShell32 = LoadLibrary(L"SHELL32.DLL"); - HRESULT hr = loadFunctionFromLibrary(LibShell32, "SetCurrentProcessExplicitAppUserModelID", SetCurrentProcessExplicitAppUserModelID); - if (SUCCEEDED(hr)) { - HINSTANCE LibPropSys = LoadLibrary(L"PROPSYS.DLL"); - hr = loadFunctionFromLibrary(LibPropSys, "PropVariantToString", PropVariantToString); - if (SUCCEEDED(hr)) { - HINSTANCE LibComBase = LoadLibrary(L"COMBASE.DLL"); - return SUCCEEDED(loadFunctionFromLibrary(LibComBase, "RoGetActivationFactory", RoGetActivationFactory)) - && SUCCEEDED(loadFunctionFromLibrary(LibComBase, "WindowsCreateStringReference", WindowsCreateStringReference)) - && SUCCEEDED(loadFunctionFromLibrary(LibComBase, "WindowsDeleteString", WindowsDeleteString)); - } - } - return hr; - } + func = reinterpret_cast(GetProcAddress(library, name)); + return (func != nullptr) ? S_OK : E_FAIL; } +typedef HRESULT(FAR STDAPICALLTYPE* f_SetCurrentProcessExplicitAppUserModelID)( + __in PCWSTR AppID); +typedef HRESULT(FAR STDAPICALLTYPE* f_PropVariantToString)( + _In_ REFPROPVARIANT propvar, + _Out_writes_(cch) PWSTR psz, + _In_ UINT cch); +typedef HRESULT(FAR STDAPICALLTYPE* f_RoGetActivationFactory)( + _In_ HSTRING activatableClassId, + _In_ REFIID iid, + _COM_Outptr_ void** factory); +typedef HRESULT(FAR STDAPICALLTYPE* f_WindowsCreateStringReference)( + _In_reads_opt_(length + 1) PCWSTR sourceString, + UINT32 length, + _Out_ HSTRING_HEADER* hstringHeader, + _Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING* string); +typedef HRESULT(FAR STDAPICALLTYPE* f_WindowsDeleteString)( + _In_opt_ HSTRING string); + +f_SetCurrentProcessExplicitAppUserModelID + SetCurrentProcessExplicitAppUserModelID; +f_PropVariantToString PropVariantToString; +f_RoGetActivationFactory RoGetActivationFactory; +f_WindowsCreateStringReference WindowsCreateStringReference; +f_WindowsDeleteString WindowsDeleteString; + +template +_Check_return_ __inline HRESULT _1_GetActivationFactory( + _In_ HSTRING activatableClassId, + _COM_Outptr_ T** factory) { + return RoGetActivationFactory(activatableClassId, IID_INS_ARGS(factory)); +} + +template +inline HRESULT Wrap_GetActivationFactory( + _In_ HSTRING activatableClassId, + _Inout_ ComPtrRef factory) throw() { + return _1_GetActivationFactory(activatableClassId, + factory.ReleaseAndGetAddressOf()); +} + +inline HRESULT initialize() { + HINSTANCE LibShell32 = LoadLibrary(L"SHELL32.DLL"); + HRESULT hr = loadFunctionFromLibrary( + LibShell32, "SetCurrentProcessExplicitAppUserModelID", + SetCurrentProcessExplicitAppUserModelID); + if (SUCCEEDED(hr)) { + HINSTANCE LibPropSys = LoadLibrary(L"PROPSYS.DLL"); + hr = loadFunctionFromLibrary(LibPropSys, "PropVariantToString", + PropVariantToString); + if (SUCCEEDED(hr)) { + HINSTANCE LibComBase = LoadLibrary(L"COMBASE.DLL"); + return SUCCEEDED(loadFunctionFromLibrary(LibComBase, + "RoGetActivationFactory", + RoGetActivationFactory)) && + SUCCEEDED(loadFunctionFromLibrary(LibComBase, + "WindowsCreateStringReference", + WindowsCreateStringReference)) && + SUCCEEDED(loadFunctionFromLibrary( + LibComBase, "WindowsDeleteString", WindowsDeleteString)); + } + } + return hr; +} + +} // namespace DllImporter + namespace Util { - inline HRESULT defaultExecutablePath(_In_ WCHAR* path, _In_ DWORD nSize = MAX_PATH) { - DWORD written = GetModuleFileNameEx(GetCurrentProcess(), nullptr, path, nSize); - return (written > 0) ? S_OK : E_FAIL; - } - - - inline HRESULT defaultShellLinksDirectory(_In_ WCHAR* path, _In_ DWORD nSize = MAX_PATH) { - DWORD written = GetEnvironmentVariable(L"APPDATA", path, nSize); - HRESULT hr = written > 0 ? S_OK : E_INVALIDARG; - if (SUCCEEDED(hr)) { - errno_t result = wcscat_s(path, nSize, DEFAULT_SHELL_LINKS_PATH); - hr = (result == 0) ? S_OK : E_INVALIDARG; - } - return hr; - } - - inline HRESULT defaultShellLinkPath(const std::wstring& appname, _In_ WCHAR* path, _In_ DWORD nSize = MAX_PATH) { - HRESULT hr = defaultShellLinksDirectory(path, nSize); - if (SUCCEEDED(hr)) { - const std::wstring appLink(appname + DEFAULT_LINK_FORMAT); - errno_t result = wcscat_s(path, nSize, appLink.c_str()); - hr = (result == 0) ? S_OK : E_INVALIDARG; - } - return hr; - } - - - inline HRESULT setNodeStringValue(const std::wstring& string, IXmlNode *node, IXmlDocument *xml) { - ComPtr textNode; - HRESULT hr = xml->CreateTextNode( WinToastStringWrapper(string).Get(), &textNode); - if (SUCCEEDED(hr)) { - ComPtr stringNode; - hr = textNode.As(&stringNode); - if (SUCCEEDED(hr)) { - ComPtr appendedChild; - hr = node->AppendChild(stringNode.Get(), &appendedChild); - } - } - return hr; - } - - inline HRESULT setEventHandlers(_In_ IToastNotification* notification, _In_ WinToastHandler* eventHandler) { - EventRegistrationToken activatedToken, dismissedToken, failedToken; - HRESULT hr = notification->add_Activated( - Callback < Implements < RuntimeClassFlags, - ITypedEventHandler> >( - [eventHandler](IToastNotification*, IInspectable*) - { - eventHandler->toastActivated(); - return S_OK; - }).Get(), &activatedToken); - - if (SUCCEEDED(hr)) { - hr = notification->add_Dismissed(Callback < Implements < RuntimeClassFlags, - ITypedEventHandler> >( - [eventHandler](IToastNotification*, IToastDismissedEventArgs* e) - { - ToastDismissalReason reason; - if (SUCCEEDED(e->get_Reason(&reason))) - { - eventHandler->toastDismissed(static_cast(reason)); - } - return S_OK; - }).Get(), &dismissedToken); - if (SUCCEEDED(hr)) { - hr = notification->add_Failed(Callback < Implements < RuntimeClassFlags, - ITypedEventHandler> >( - [eventHandler](IToastNotification*, IToastFailedEventArgs*) - { - eventHandler->toastFailed(); - return S_OK; - }).Get(), &failedToken); - } - } - return hr; - } +inline HRESULT defaultExecutablePath(_In_ WCHAR* path, + _In_ DWORD nSize = MAX_PATH) { + DWORD written = + GetModuleFileNameEx(GetCurrentProcess(), nullptr, path, nSize); + return (written > 0) ? S_OK : E_FAIL; } +inline HRESULT defaultShellLinksDirectory(_In_ WCHAR* path, + _In_ DWORD nSize = MAX_PATH) { + DWORD written = GetEnvironmentVariable(L"APPDATA", path, nSize); + HRESULT hr = written > 0 ? S_OK : E_INVALIDARG; + if (SUCCEEDED(hr)) { + errno_t result = wcscat_s(path, nSize, DEFAULT_SHELL_LINKS_PATH); + hr = (result == 0) ? S_OK : E_INVALIDARG; + } + return hr; +} + +inline HRESULT defaultShellLinkPath(const std::wstring& appname, + _In_ WCHAR* path, + _In_ DWORD nSize = MAX_PATH) { + HRESULT hr = defaultShellLinksDirectory(path, nSize); + if (SUCCEEDED(hr)) { + const std::wstring appLink(appname + DEFAULT_LINK_FORMAT); + errno_t result = wcscat_s(path, nSize, appLink.c_str()); + hr = (result == 0) ? S_OK : E_INVALIDARG; + } + return hr; +} + +inline HRESULT setNodeStringValue(const std::wstring& string, + IXmlNode* node, + IXmlDocument* xml) { + ComPtr textNode; + HRESULT hr = + xml->CreateTextNode(WinToastStringWrapper(string).Get(), &textNode); + if (SUCCEEDED(hr)) { + ComPtr stringNode; + hr = textNode.As(&stringNode); + if (SUCCEEDED(hr)) { + ComPtr appendedChild; + hr = node->AppendChild(stringNode.Get(), &appendedChild); + } + } + return hr; +} + +inline HRESULT setEventHandlers(_In_ IToastNotification* notification, + _In_ WinToastHandler* eventHandler) { + EventRegistrationToken activatedToken, dismissedToken, failedToken; + HRESULT hr = notification->add_Activated( + Callback< + Implements, + ITypedEventHandler>>( + [eventHandler](IToastNotification*, IInspectable*) { + eventHandler->toastActivated(); + return S_OK; + }) + .Get(), + &activatedToken); + + if (SUCCEEDED(hr)) { + hr = notification->add_Dismissed( + Callback, + ITypedEventHandler>>( + [eventHandler](IToastNotification*, IToastDismissedEventArgs* e) { + ToastDismissalReason reason; + if (SUCCEEDED(e->get_Reason(&reason))) { + eventHandler->toastDismissed( + static_cast( + reason)); + } + return S_OK; + }) + .Get(), + &dismissedToken); + if (SUCCEEDED(hr)) { + hr = notification->add_Failed( + Callback, + ITypedEventHandler>>( + [eventHandler](IToastNotification*, IToastFailedEventArgs*) { + eventHandler->toastFailed(); + return S_OK; + }) + .Get(), + &failedToken); + } + } + return hr; +} + +} // namespace Util + WinToast* WinToast::_instance = nullptr; WinToast* WinToast::instance() { - if (_instance == nullptr) { - _instance = new WinToast(); - } - return _instance; + if (_instance == nullptr) { + _instance = new WinToast(); + } + return _instance; } -WinToast::WinToast() : _isInitialized(false) -{ - DllImporter::initialize(); +WinToast::WinToast() : _isInitialized(false) { + DllImporter::initialize(); } void WinToast::setAppName(_In_ const std::wstring& appName) { - _appName = appName; + _appName = appName; } std::wstring WinToast::appName() const { - return _appName; + return _appName; } std::wstring WinToast::appUserModelId() const { - return _aumi; + return _aumi; } void WinToast::setAppUserModelId(_In_ const std::wstring& aumi) { - _aumi = aumi; + _aumi = aumi; } bool WinToast::isCompatible() { - return !((DllImporter::SetCurrentProcessExplicitAppUserModelID == nullptr) - || (DllImporter::PropVariantToString == nullptr) - || (DllImporter::RoGetActivationFactory == nullptr) - || (DllImporter::WindowsCreateStringReference == nullptr) - || (DllImporter::WindowsDeleteString == nullptr)); + return !((DllImporter::SetCurrentProcessExplicitAppUserModelID == nullptr) || + (DllImporter::PropVariantToString == nullptr) || + (DllImporter::RoGetActivationFactory == nullptr) || + (DllImporter::WindowsCreateStringReference == nullptr) || + (DllImporter::WindowsDeleteString == nullptr)); } -std::wstring WinToast::configureAUMI(_In_ const std::wstring &company, - _In_ const std::wstring &name, - _In_ const std::wstring &surname, - _In_ const std::wstring &versionInfo) -{ - std::wstring aumi = company; - aumi += L"." + name; - aumi += L"." + surname; - aumi += L"." + versionInfo; +std::wstring WinToast::configureAUMI(_In_ const std::wstring& company, + _In_ const std::wstring& name, + _In_ const std::wstring& surname, + _In_ const std::wstring& versionInfo) { + std::wstring aumi = company; + aumi += L"." + name; + aumi += L"." + surname; + aumi += L"." + versionInfo; - return aumi; + return aumi; } bool WinToast::initialize() { - if (_aumi.empty() || _appName.empty()) { - return _isInitialized = false; - } + if (_aumi.empty() || _appName.empty()) { + return _isInitialized = false; + } - if (!isCompatible()) { - return _isInitialized = false; - } + if (!isCompatible()) { + return _isInitialized = false; + } - if (FAILED(DllImporter::SetCurrentProcessExplicitAppUserModelID(_aumi.c_str()))) { - return _isInitialized = false; - } + if (FAILED(DllImporter::SetCurrentProcessExplicitAppUserModelID( + _aumi.c_str()))) { + return _isInitialized = false; + } + HRESULT hr = validateShellLink(); + if (FAILED(hr)) { + hr = createShellLink(); + } - HRESULT hr = validateShellLink(); - if (FAILED(hr)) { - hr = createShellLink(); - } - + if (SUCCEEDED(hr)) { + hr = DllImporter::Wrap_GetActivationFactory( + WinToastStringWrapper( + RuntimeClass_Windows_UI_Notifications_ToastNotificationManager) + .Get(), + &_notificationManager); if (SUCCEEDED(hr)) { - hr = DllImporter::Wrap_GetActivationFactory(WinToastStringWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &_notificationManager); + hr = notificationManager()->CreateToastNotifierWithId( + WinToastStringWrapper(_aumi).Get(), &_notifier); + if (SUCCEEDED(hr)) { + hr = DllImporter::Wrap_GetActivationFactory( + WinToastStringWrapper( + RuntimeClass_Windows_UI_Notifications_ToastNotification) + .Get(), + &_notificationFactory); + } + } + } + + return _isInitialized = SUCCEEDED(hr); +} + +HRESULT WinToast::validateShellLink() { + WCHAR _path[MAX_PATH]; + Util::defaultShellLinkPath(_appName, _path); + // Check if the file exist + DWORD attr = GetFileAttributes(_path); + if (attr >= 0xFFFFFFF) { + std::wcout << "Error, shell link not found. Try to create a new one in: " + << _path << std::endl; + return E_FAIL; + } + + // Let's load the file as shell link to validate. + // - Create a shell link + // - Create a persistant file + // - Load the path as data for the persistant file + // - Read the property AUMI and validate with the current + // - Review if AUMI is equal. + ComPtr shellLink; + HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&shellLink)); + if (SUCCEEDED(hr)) { + ComPtr persistFile; + hr = shellLink.As(&persistFile); + if (SUCCEEDED(hr)) { + hr = persistFile->Load(_path, STGM_READWRITE); + if (SUCCEEDED(hr)) { + ComPtr propertyStore; + hr = shellLink.As(&propertyStore); if (SUCCEEDED(hr)) { - hr = notificationManager()->CreateToastNotifierWithId(WinToastStringWrapper(_aumi).Get(), &_notifier); + PROPVARIANT appIdPropVar; + hr = propertyStore->GetValue(PKEY_AppUserModel_ID, &appIdPropVar); + if (SUCCEEDED(hr)) { + WCHAR AUMI[MAX_PATH]; + hr = DllImporter::PropVariantToString(appIdPropVar, AUMI, MAX_PATH); if (SUCCEEDED(hr)) { - hr = DllImporter::Wrap_GetActivationFactory(WinToastStringWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &_notificationFactory); + hr = (_aumi == AUMI) ? S_OK : E_FAIL; + } else { // AUMI Changed for the same app, let's update the current + // value! =) + PropVariantClear(&appIdPropVar); + hr = InitPropVariantFromString(_aumi.c_str(), &appIdPropVar); + if (SUCCEEDED(hr)) { + hr = + propertyStore->SetValue(PKEY_AppUserModel_ID, appIdPropVar); + if (SUCCEEDED(hr)) { + hr = propertyStore->Commit(); + if (SUCCEEDED(hr) && SUCCEEDED(persistFile->IsDirty())) { + hr = persistFile->Save(_path, TRUE); + } + } + } } + PropVariantClear(&appIdPropVar); + } } + } } - - return _isInitialized = SUCCEEDED(hr); + } + return hr; } -HRESULT WinToast::validateShellLink() { - - WCHAR _path[MAX_PATH]; - Util::defaultShellLinkPath(_appName, _path); - // Check if the file exist - DWORD attr = GetFileAttributes(_path); - if (attr >= 0xFFFFFFF) { - std::wcout << "Error, shell link not found. Try to create a new one in: " << _path << std::endl; - return E_FAIL; - } - - // Let's load the file as shell link to validate. - // - Create a shell link - // - Create a persistant file - // - Load the path as data for the persistant file - // - Read the property AUMI and validate with the current - // - Review if AUMI is equal. - ComPtr shellLink; - HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)); +HRESULT WinToast::createShellLink() { + WCHAR exePath[MAX_PATH]; + WCHAR slPath[MAX_PATH]; + Util::defaultShellLinkPath(_appName, slPath); + Util::defaultExecutablePath(exePath); + ComPtr shellLink; + HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&shellLink)); + if (SUCCEEDED(hr)) { + hr = shellLink->SetPath(exePath); if (SUCCEEDED(hr)) { - ComPtr persistFile; - hr = shellLink.As(&persistFile); + hr = shellLink->SetArguments(L""); + if (SUCCEEDED(hr)) { + hr = shellLink->SetWorkingDirectory(exePath); if (SUCCEEDED(hr)) { - hr = persistFile->Load(_path, STGM_READWRITE); + ComPtr propertyStore; + hr = shellLink.As(&propertyStore); + if (SUCCEEDED(hr)) { + PROPVARIANT appIdPropVar; + hr = InitPropVariantFromString(_aumi.c_str(), &appIdPropVar); if (SUCCEEDED(hr)) { - ComPtr propertyStore; - hr = shellLink.As(&propertyStore); + hr = propertyStore->SetValue(PKEY_AppUserModel_ID, appIdPropVar); + if (SUCCEEDED(hr)) { + hr = propertyStore->Commit(); if (SUCCEEDED(hr)) { - PROPVARIANT appIdPropVar; - hr = propertyStore->GetValue(PKEY_AppUserModel_ID, &appIdPropVar); - if (SUCCEEDED(hr)) { - WCHAR AUMI[MAX_PATH]; - hr = DllImporter::PropVariantToString(appIdPropVar, AUMI, MAX_PATH); - if (SUCCEEDED(hr)) { - hr = (_aumi == AUMI) ? S_OK : E_FAIL; - } else { // AUMI Changed for the same app, let's update the current value! =) - PropVariantClear(&appIdPropVar); - hr = InitPropVariantFromString(_aumi.c_str(), &appIdPropVar); - if (SUCCEEDED(hr)) { - hr = propertyStore->SetValue(PKEY_AppUserModel_ID, appIdPropVar); - if (SUCCEEDED(hr)) { - hr = propertyStore->Commit(); - if (SUCCEEDED(hr) && SUCCEEDED(persistFile->IsDirty())) { - hr = persistFile->Save(_path, TRUE); - } - } - } - } - PropVariantClear(&appIdPropVar); - } + ComPtr persistFile; + hr = shellLink.As(&persistFile); + if (SUCCEEDED(hr)) { + hr = persistFile->Save(slPath, TRUE); + } } + } } + PropVariantClear(&appIdPropVar); + } } + } } - return hr; + } + CoTaskMemFree(exePath); + CoTaskMemFree(slPath); + return hr; } +bool WinToast::showToast(_In_ const WinToastTemplate& toast, + _In_ WinToastHandler* handler) { + if (!isInitialized()) { + return _isInitialized; + } - -HRESULT WinToast::createShellLink() { - WCHAR exePath[MAX_PATH]; - WCHAR slPath[MAX_PATH]; - Util::defaultShellLinkPath(_appName, slPath); - Util::defaultExecutablePath(exePath); - ComPtr shellLink; - HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)); - if (SUCCEEDED(hr)) { - hr = shellLink->SetPath(exePath); + HRESULT hr = _notificationManager->GetTemplateContent( + ToastTemplateType(toast.type()), &_xmlDocument); + if (SUCCEEDED(hr)) { + const int fieldsCount = toast.textFieldsCount(); + for (int i = 0; i < fieldsCount && SUCCEEDED(hr); i++) { + hr = setTextField(toast.textField(WinToastTemplate::TextField(i)), i); + } + if (makeSilent(toast.isSilent())) { + if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) { - hr = shellLink->SetArguments(L""); + hr = toast.hasImage() ? setImageField(toast.imagePath()) : hr; + if (SUCCEEDED(hr)) { + hr = _notificationFactory->CreateToastNotification(xmlDocument(), + &_notification); if (SUCCEEDED(hr)) { - hr = shellLink->SetWorkingDirectory(exePath); - if (SUCCEEDED(hr)) { - ComPtr propertyStore; - hr = shellLink.As(&propertyStore); - if (SUCCEEDED(hr)) { - PROPVARIANT appIdPropVar; - hr = InitPropVariantFromString(_aumi.c_str(), &appIdPropVar); - if (SUCCEEDED(hr)) { - hr = propertyStore->SetValue(PKEY_AppUserModel_ID, appIdPropVar); - if (SUCCEEDED(hr)) { - hr = propertyStore->Commit(); - if (SUCCEEDED(hr)) { - ComPtr persistFile; - hr = shellLink.As(&persistFile); - if (SUCCEEDED(hr)) { - hr = persistFile->Save(slPath, TRUE); - } - } - } - } - PropVariantClear(&appIdPropVar); - } - } + hr = Util::setEventHandlers(notification(), handler); + if (SUCCEEDED(hr)) { + hr = _notifier->Show(notification()); + } } + } } + } + } else { + return false; } - CoTaskMemFree(exePath); - CoTaskMemFree(slPath); - return hr; + } + + return SUCCEEDED(hr); } - - -bool WinToast::showToast(_In_ const WinToastTemplate& toast, _In_ WinToastHandler* handler) { - if (!isInitialized()) { - return _isInitialized; - } - - HRESULT hr = _notificationManager->GetTemplateContent(ToastTemplateType(toast.type()), &_xmlDocument); - if (SUCCEEDED(hr)) { - const int fieldsCount = toast.textFieldsCount(); - for (int i = 0; i < fieldsCount && SUCCEEDED(hr); i++) { - hr = setTextField(toast.textField(WinToastTemplate::TextField(i)), i); - } - if (makeSilent(toast.isSilent())) { - if (SUCCEEDED(hr)) { - if (SUCCEEDED(hr)) { - hr = toast.hasImage() ? setImageField(toast.imagePath()) : hr; - if (SUCCEEDED(hr)) { - hr = _notificationFactory->CreateToastNotification(xmlDocument(), &_notification); - if (SUCCEEDED(hr)) { - hr = Util::setEventHandlers(notification(), handler); - if (SUCCEEDED(hr)) { - hr = _notifier->Show(notification()); - } - } - } - } - } - } else { - return false; - } - } - - return SUCCEEDED(hr); -} - - HRESULT WinToast::setTextField(_In_ const std::wstring& text, _In_ int pos) { - ComPtr nodeList; - HRESULT hr = _xmlDocument->GetElementsByTagName(WinToastStringWrapper(L"text").Get(), &nodeList); + ComPtr nodeList; + HRESULT hr = _xmlDocument->GetElementsByTagName( + WinToastStringWrapper(L"text").Get(), &nodeList); + if (SUCCEEDED(hr)) { + ComPtr node; + hr = nodeList->Item(pos, &node); if (SUCCEEDED(hr)) { - ComPtr node; - hr = nodeList->Item(pos, &node); - if (SUCCEEDED(hr)) { - hr = Util::setNodeStringValue(text, node.Get(), xmlDocument()); - } + hr = Util::setNodeStringValue(text, node.Get(), xmlDocument()); } - return hr; + } + return hr; } bool WinToast::makeSilent(bool is_silent) { - if (!is_silent) return true; - ScopedHString tag(L"toast"); - if (!tag.success()) - return false; + if (!is_silent) + return true; + ScopedHString tag(L"toast"); + if (!tag.success()) + return false; - ComPtr node_list; - if (FAILED(xmlDocument()->GetElementsByTagName(tag, &node_list))) - return false; + ComPtr node_list; + if (FAILED(xmlDocument()->GetElementsByTagName(tag, &node_list))) + return false; - ComPtr root; - if (FAILED(node_list->Item(0, &root))) - return false; + ComPtr root; + if (FAILED(node_list->Item(0, &root))) + return false; - ComPtr audio_element; - ScopedHString audio_str(L"audio"); - if (FAILED(xmlDocument()->CreateElement(audio_str, &audio_element))) - return false; + ComPtr audio_element; + ScopedHString audio_str(L"audio"); + if (FAILED(xmlDocument()->CreateElement(audio_str, &audio_element))) + return false; - ComPtr audio_node_tmp; - if (FAILED(audio_element.As(&audio_node_tmp))) - return false; + ComPtr audio_node_tmp; + if (FAILED(audio_element.As(&audio_node_tmp))) + return false; - // Append audio node to toast xml - ComPtr audio_node; - if (FAILED(root->AppendChild(audio_node_tmp.Get(), &audio_node))) - return false; + // Append audio node to toast xml + ComPtr audio_node; + if (FAILED(root->AppendChild(audio_node_tmp.Get(), &audio_node))) + return false; - // Create silent attribute - ComPtr attributes; - if (FAILED(audio_node->get_Attributes(&attributes))) - return false; + // Create silent attribute + ComPtr attributes; + if (FAILED(audio_node->get_Attributes(&attributes))) + return false; - ComPtr silent_attribute; - ScopedHString silent_str(L"silent"); - if (FAILED(xmlDocument()->CreateAttribute(silent_str, &silent_attribute))) - return false; + ComPtr silent_attribute; + ScopedHString silent_str(L"silent"); + if (FAILED(xmlDocument()->CreateAttribute(silent_str, &silent_attribute))) + return false; - ComPtr silent_attribute_node; - if (FAILED(silent_attribute.As(&silent_attribute_node))) - return false; + ComPtr silent_attribute_node; + if (FAILED(silent_attribute.As(&silent_attribute_node))) + return false; - // Set silent attribute to true - ScopedHString silent_value(L"true"); - if (!silent_value.success()) - return false; + // Set silent attribute to true + ScopedHString silent_value(L"true"); + if (!silent_value.success()) + return false; - ComPtr silent_text; - if (FAILED(xmlDocument()->CreateTextNode(silent_value, &silent_text))) - return false; + ComPtr silent_text; + if (FAILED(xmlDocument()->CreateTextNode(silent_value, &silent_text))) + return false; - ComPtr silent_node; - if (FAILED(silent_text.As(&silent_node))) - return false; + ComPtr silent_node; + if (FAILED(silent_text.As(&silent_node))) + return false; - ComPtr child_node; - if (FAILED( - silent_attribute_node->AppendChild(silent_node.Get(), &child_node))) - return false; + ComPtr child_node; + if (FAILED( + silent_attribute_node->AppendChild(silent_node.Get(), &child_node))) + return false; - ComPtr silent_attribute_pnode; - return SUCCEEDED(attributes.Get()->SetNamedItem(silent_attribute_node.Get(), - &silent_attribute_pnode)); + ComPtr silent_attribute_pnode; + return SUCCEEDED(attributes.Get()->SetNamedItem(silent_attribute_node.Get(), + &silent_attribute_pnode)); } - -HRESULT WinToast::setImageField(_In_ const std::wstring& path) { - wchar_t imagePath[MAX_PATH] = L"file:///"; - HRESULT hr = StringCchCat(imagePath, MAX_PATH, path.c_str()); +HRESULT WinToast::setImageField(_In_ const std::wstring& path) { + wchar_t imagePath[MAX_PATH] = L"file:///"; + HRESULT hr = StringCchCat(imagePath, MAX_PATH, path.c_str()); + if (SUCCEEDED(hr)) { + ComPtr nodeList; + hr = _xmlDocument->GetElementsByTagName( + WinToastStringWrapper(L"image").Get(), &nodeList); if (SUCCEEDED(hr)) { - ComPtr nodeList; - hr = _xmlDocument->GetElementsByTagName(WinToastStringWrapper(L"image").Get(), &nodeList); + ComPtr node; + hr = nodeList->Item(0, &node); + if (SUCCEEDED(hr)) { + ComPtr attributes; + hr = node->get_Attributes(&attributes); if (SUCCEEDED(hr)) { - ComPtr node; - hr = nodeList->Item(0, &node); - if (SUCCEEDED(hr)) { - ComPtr attributes; - hr = node->get_Attributes(&attributes); - if (SUCCEEDED(hr)) { - ComPtr editedNode; - hr = attributes->GetNamedItem(WinToastStringWrapper(L"src").Get(), &editedNode); - if (SUCCEEDED(hr)) { - Util::setNodeStringValue(imagePath, editedNode.Get(), xmlDocument()); - } - } - } + ComPtr editedNode; + hr = attributes->GetNamedItem(WinToastStringWrapper(L"src").Get(), + &editedNode); + if (SUCCEEDED(hr)) { + Util::setNodeStringValue(imagePath, editedNode.Get(), + xmlDocument()); + } } + } } - return hr; + } + return hr; } -WinToastTemplate::WinToastTemplate(const WinToastTemplateType& type) : - _type(type) -{ - initComponentsFromType(); +WinToastTemplate::WinToastTemplate(const WinToastTemplateType& type) + : _type(type) { + initComponentsFromType(); } - -WinToastTemplate::~WinToastTemplate() -{ - _textFields.clear(); +WinToastTemplate::~WinToastTemplate() { + _textFields.clear(); } -void WinToastTemplate::setTextField(_In_ const std::wstring& txt, _In_ const WinToastTemplate::TextField& pos) { - _textFields[pos] = txt; +void WinToastTemplate::setTextField( + _In_ const std::wstring& txt, + _In_ const WinToastTemplate::TextField& pos) { + _textFields[pos] = txt; } void WinToastTemplate::setImagePath(_In_ const std::wstring& imgPath) { - if (!_hasImage) - return; - _imagePath = imgPath; + if (!_hasImage) + return; + _imagePath = imgPath; } void WinToastTemplate::setSilent(bool is_silent) { - _silent = is_silent; + _silent = is_silent; } -int WinToastTemplate::TextFieldsCount[WinToastTemplateTypeCount] = { 1, 2, 2, 3, 1, 2, 2, 3}; +int WinToastTemplate::TextFieldsCount[WinToastTemplateTypeCount] = {1, 2, 2, 3, + 1, 2, 2, 3}; void WinToastTemplate::initComponentsFromType() { - _hasImage = _type < ToastTemplateType_ToastText01; - _textFields = std::vector(TextFieldsCount[_type], L""); + _hasImage = _type < ToastTemplateType_ToastText01; + _textFields = std::vector(TextFieldsCount[_type], L""); } -WinToastStringWrapper::WinToastStringWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() { - HRESULT hr = DllImporter::WindowsCreateStringReference(stringRef, length, &_header, &_hstring); - if (!SUCCEEDED(hr)) { - RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); - } +WinToastStringWrapper::WinToastStringWrapper(_In_reads_(length) + PCWSTR stringRef, + _In_ UINT32 length) throw() { + HRESULT hr = DllImporter::WindowsCreateStringReference(stringRef, length, + &_header, &_hstring); + if (!SUCCEEDED(hr)) { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), + EXCEPTION_NONCONTINUABLE, 0, nullptr); + } } - -WinToastStringWrapper::WinToastStringWrapper(const std::wstring &stringRef) -{ - HRESULT hr = DllImporter::WindowsCreateStringReference(stringRef.c_str(), static_cast(stringRef.length()), &_header, &_hstring); - if (FAILED(hr)) { - RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); - } +WinToastStringWrapper::WinToastStringWrapper(const std::wstring& stringRef) { + HRESULT hr = DllImporter::WindowsCreateStringReference( + stringRef.c_str(), static_cast(stringRef.length()), &_header, + &_hstring); + if (FAILED(hr)) { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), + EXCEPTION_NONCONTINUABLE, 0, nullptr); + } } WinToastStringWrapper::~WinToastStringWrapper() { - DllImporter::WindowsDeleteString(_hstring); + DllImporter::WindowsDeleteString(_hstring); } HSTRING WinToastStringWrapper::Get() const { - return _hstring; -} \ No newline at end of file + return _hstring; +} diff --git a/atom/browser/ui/win/toast_lib.h b/atom/browser/ui/win/toast_lib.h index c7fd0f81d6..8b9907767b 100644 --- a/atom/browser/ui/win/toast_lib.h +++ b/atom/browser/ui/win/toast_lib.h @@ -9,8 +9,8 @@ // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -20,149 +20,179 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#ifndef WINTOASTLIB_H -#define WINTOASTLIB_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -using namespace Microsoft::WRL; -using namespace ABI::Windows::Data::Xml::Dom; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::UI::Notifications; -using namespace Windows::Foundation; +#ifndef ATOM_BROWSER_UI_WIN_TOAST_LIB_H_ +#define ATOM_BROWSER_UI_WIN_TOAST_LIB_H_ -#define DEFAULT_SHELL_LINKS_PATH L"\\Microsoft\\Windows\\Start Menu\\Programs\\" -#define DEFAULT_LINK_FORMAT L".lnk" +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using Microsoft::WRL::ComPtr; +using Microsoft::WRL::Details::ComPtrRef; +using Microsoft::WRL::Callback; +using Microsoft::WRL::Implements; +using Microsoft::WRL::RuntimeClassFlags; +using Microsoft::WRL::ClassicCom; +using ABI::Windows::Data::Xml::Dom::IXmlAttribute; +using ABI::Windows::Data::Xml::Dom::IXmlDocument; +using ABI::Windows::Data::Xml::Dom::IXmlElement; +using ABI::Windows::Data::Xml::Dom::IXmlNamedNodeMap; +using ABI::Windows::Data::Xml::Dom::IXmlNode; +using ABI::Windows::Data::Xml::Dom::IXmlNodeList; +using ABI::Windows::Data::Xml::Dom::IXmlText; +using ABI::Windows::UI::Notifications::ToastDismissalReason; +using ABI::Windows::UI::Notifications::ToastTemplateType; +using ABI::Windows::UI::Notifications::IToastNotificationManagerStatics; +using ABI::Windows::UI::Notifications::IToastNotifier; +using ABI::Windows::UI::Notifications::IToastNotificationFactory; +using ABI::Windows::UI::Notifications::IToastNotification; +using ABI::Windows::UI::Notifications::ToastNotification; +using ABI::Windows::UI::Notifications::ToastDismissedEventArgs; +using ABI::Windows::UI::Notifications::IToastDismissedEventArgs; +using ABI::Windows::UI::Notifications::ToastFailedEventArgs; +using ABI::Windows::UI::Notifications::IToastFailedEventArgs; +using ABI::Windows::UI::Notifications::ToastTemplateType_ToastText01; +using ABI::Windows::Foundation::ITypedEventHandler; + +#define DEFAULT_SHELL_LINKS_PATH L"\\Microsoft\\Windows\\Start Menu\\Programs\\" +#define DEFAULT_LINK_FORMAT L".lnk" namespace WinToastLib { - class WinToastStringWrapper { - public: - WinToastStringWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw(); - WinToastStringWrapper(_In_ const std::wstring &stringRef) throw(); - ~WinToastStringWrapper(); - HSTRING Get() const throw(); - private: - HSTRING _hstring; - HSTRING_HEADER _header; +class WinToastStringWrapper { + public: + WinToastStringWrapper(_In_reads_(length) PCWSTR stringRef, + _In_ UINT32 length) throw(); + explicit WinToastStringWrapper(_In_ const std::wstring& stringRef) throw(); + ~WinToastStringWrapper(); + HSTRING Get() const throw(); - }; + private: + HSTRING _hstring; + HSTRING_HEADER _header; +}; +class WinToastHandler { + public: + enum WinToastDismissalReason { + UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled, + ApplicationHidden = + ToastDismissalReason::ToastDismissalReason_ApplicationHidden, + TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut + }; - class WinToastHandler { - public: - enum WinToastDismissalReason { - UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled, - ApplicationHidden = ToastDismissalReason::ToastDismissalReason_ApplicationHidden, - TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut - }; + virtual void toastActivated() {} + virtual void toastDismissed(WinToastDismissalReason state) {} + virtual void toastFailed() {} +}; - virtual void toastActivated() {}; - virtual void toastDismissed(WinToastDismissalReason state) {}; - virtual void toastFailed() {}; - }; +class WinToastTemplate { + public: + enum TextField { FirstLine = 0, SecondLine, ThirdLine, LineCount }; - class WinToastTemplate - { - public: - enum TextField { - FirstLine = 0, - SecondLine, - ThirdLine, - LineCount - }; + enum WinToastTemplateType { + ImageWithOneLine = ToastTemplateType::ToastTemplateType_ToastImageAndText01, + ImageWithTwoLines = + ToastTemplateType::ToastTemplateType_ToastImageAndText02, + ImageWithThreeLines = + ToastTemplateType::ToastTemplateType_ToastImageAndText03, + ImageWithFourLines = + ToastTemplateType::ToastTemplateType_ToastImageAndText04, + TextOneLine = ToastTemplateType::ToastTemplateType_ToastText01, + TextTwoLines = ToastTemplateType::ToastTemplateType_ToastText02, + TextThreeLines = ToastTemplateType::ToastTemplateType_ToastText03, + TextFourLines = ToastTemplateType::ToastTemplateType_ToastText04, + WinToastTemplateTypeCount + }; - enum WinToastTemplateType { - ImageWithOneLine = ToastTemplateType::ToastTemplateType_ToastImageAndText01, - ImageWithTwoLines = ToastTemplateType::ToastTemplateType_ToastImageAndText02, - ImageWithThreeLines = ToastTemplateType::ToastTemplateType_ToastImageAndText03, - ImageWithFourLines = ToastTemplateType::ToastTemplateType_ToastImageAndText04, - TextOneLine = ToastTemplateType::ToastTemplateType_ToastText01, - TextTwoLines = ToastTemplateType::ToastTemplateType_ToastText02, - TextThreeLines = ToastTemplateType::ToastTemplateType_ToastText03, - TextFourLines = ToastTemplateType::ToastTemplateType_ToastText04, - WinToastTemplateTypeCount - }; + explicit WinToastTemplate( + _In_ const WinToastTemplateType& type = ImageWithTwoLines); + ~WinToastTemplate(); - WinToastTemplate(_In_ const WinToastTemplateType& type = ImageWithTwoLines); - ~WinToastTemplate(); + int textFieldsCount() const { return _textFields.size(); } + bool hasImage() const { return _hasImage; } + std::vector textFields() const { return _textFields; } + std::wstring textField(_In_ const TextField& pos) const { + return _textFields[pos]; + } + std::wstring imagePath() const { return _imagePath; } + WinToastTemplateType type() const { return _type; } + void setTextField(_In_ const std::wstring& txt, _In_ const TextField& pos); + void setImagePath(_In_ const std::wstring& imgPath); + void setSilent(bool is_silent); + bool isSilent() const { return _silent; } - int textFieldsCount() const { return _textFields.size(); } - bool hasImage() const { return _hasImage; } - std::vector textFields() const { return _textFields; } - std::wstring textField(_In_ const TextField& pos) const { return _textFields[pos]; } - std::wstring imagePath() const { return _imagePath; } - WinToastTemplateType type() const { return _type; } - void setTextField(_In_ const std::wstring& txt, _In_ const TextField& pos); - void setImagePath(_In_ const std::wstring& imgPath); - void setSilent(bool is_silent); - bool isSilent() const { return _silent; } - private: - static int TextFieldsCount[WinToastTemplateTypeCount]; - bool _hasImage; - bool _silent = false; - std::vector _textFields; - std::wstring _imagePath; - WinToastTemplateType _type; - void initComponentsFromType(); - }; + private: + static int TextFieldsCount[WinToastTemplateTypeCount]; + bool _hasImage; + bool _silent = false; + std::vector _textFields; + std::wstring _imagePath; + WinToastTemplateType _type; + void initComponentsFromType(); +}; - class WinToast { - public: - static WinToast* instance(); - static bool isCompatible(); - static std::wstring configureAUMI(_In_ const std::wstring& company, - _In_ const std::wstring& name, - _In_ const std::wstring& surname, - _In_ const std::wstring& versionInfo - ); - bool initialize(); - bool isInitialized() const { return _isInitialized; } - bool showToast(_In_ const WinToastTemplate& toast, _In_ WinToastHandler* handler); - std::wstring appName() const; - std::wstring appUserModelId() const; - void setAppUserModelId(_In_ const std::wstring& appName); - void setAppName(_In_ const std::wstring& appName); - private: - bool _isInitialized; - std::wstring _appName; - std::wstring _aumi; - ComPtr _xmlDocument; - ComPtr _notificationManager; - ComPtr _notifier; - ComPtr _notificationFactory; - ComPtr _notification; - static WinToast* _instance; +class WinToast { + public: + static WinToast* instance(); + static bool isCompatible(); + static std::wstring configureAUMI(_In_ const std::wstring& company, + _In_ const std::wstring& name, + _In_ const std::wstring& surname, + _In_ const std::wstring& versionInfo); + bool initialize(); + bool isInitialized() const { return _isInitialized; } + bool showToast(_In_ const WinToastTemplate& toast, + _In_ WinToastHandler* handler); + std::wstring appName() const; + std::wstring appUserModelId() const; + void setAppUserModelId(_In_ const std::wstring& appName); + void setAppName(_In_ const std::wstring& appName); - WinToast(void); - IXmlDocument* xmlDocument() const { return _xmlDocument.Get(); } - IToastNotifier* notifier() const { return _notifier.Get(); } - IToastNotificationFactory* notificationFactory() const { return _notificationFactory.Get(); } - IToastNotificationManagerStatics* notificationManager() const { return _notificationManager.Get(); } - IToastNotification* notification() const { return _notification.Get(); } + private: + bool _isInitialized; + std::wstring _appName; + std::wstring _aumi; + ComPtr _xmlDocument; + ComPtr _notificationManager; + ComPtr _notifier; + ComPtr _notificationFactory; + ComPtr _notification; + static WinToast* _instance; - HRESULT validateShellLink(); - HRESULT createShellLink(); - HRESULT setImageField(_In_ const std::wstring& path); - HRESULT setTextField(_In_ const std::wstring& text, _In_ int pos); - bool makeSilent(bool is_silent); - }; + WinToast(void); + IXmlDocument* xmlDocument() const { return _xmlDocument.Get(); } + IToastNotifier* notifier() const { return _notifier.Get(); } + IToastNotificationFactory* notificationFactory() const { + return _notificationFactory.Get(); + } + IToastNotificationManagerStatics* notificationManager() const { + return _notificationManager.Get(); + } + IToastNotification* notification() const { return _notification.Get(); } + HRESULT validateShellLink(); + HRESULT createShellLink(); + HRESULT setImageField(_In_ const std::wstring& path); + HRESULT setTextField(_In_ const std::wstring& text, _In_ int pos); + bool makeSilent(bool is_silent); +}; +} // namespace WinToastLib - -} - -#endif // WINTOASTLIB_H \ No newline at end of file +#endif // ATOM_BROWSER_UI_WIN_TOAST_LIB_H_ diff --git a/default_app/default_app.js b/default_app/default_app.js index d002a8d24a..afff67669e 100644 --- a/default_app/default_app.js +++ b/default_app/default_app.js @@ -32,14 +32,14 @@ exports.load = (appUrl) => { title: 'Hello World', body: 'This is the long and complicated body for this notification that just goes on and on and on and never really seems to stop', silent: true, - icon: '/Users/samuel/Downloads/ninja.png', + icon: path.resolve('C:\\Users\\Samuel\\Downloads\\icon.png'), hasReply: true, replyPlaceholder: 'Type Here!!' - }); - n.on('show', () => console.log('showed')); - n.on('click', () => console.info('clicked!!')); - n.on('reply', (e, reply) => console.log('Replied:', reply)); + }) + n.on('show', () => console.log('showed')) + n.on('click', () => console.info('clicked!!')) + n.on('reply', (e, reply) => console.log('Replied:', reply)) - n.show(); + n.show() }) }