mirror of
https://github.com/gnustep/libs-back.git
synced 2025-04-22 15:31:14 +00:00
Fix memory leaks in toast notifications
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/branches/gnustep_testplant_branch@39818 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
f8ce8e4ccd
commit
f9303f7bbd
12 changed files with 171 additions and 64 deletions
|
@ -68,7 +68,11 @@ static NSString * const kButtonActionKey = @"show";
|
|||
@implementation NSImage (Private)
|
||||
- (void)_setFilename:(NSString*)filename
|
||||
{
|
||||
#if 0
|
||||
_fileName = [filename copy];
|
||||
#else
|
||||
ASSIGN(_fileName, filename);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (NSString*)_filename
|
||||
|
@ -115,7 +119,9 @@ static NSString * const kButtonActionKey = @"show";
|
|||
|
||||
appIcon = [self _iconFromImage:image];
|
||||
appIconPath = [[image _filename] copy];
|
||||
#if defined(DEBUG)
|
||||
NSLog(@"%s:bundle: %@ image: %@ icon: %p path: %@", __PRETTY_FUNCTION__, classBundle, image, appIcon, appIconPath);
|
||||
#endif
|
||||
|
||||
if (appIcon == NULL)
|
||||
{
|
||||
|
@ -165,7 +171,7 @@ static NSString * const kButtonActionKey = @"show";
|
|||
{
|
||||
pSendNotification = (SendNotificationFunctionPtr)GetProcAddress(hNotificationLib, "sendNotification");
|
||||
pRemoveNotification = (RemoveNotificationFunctionPtr)GetProcAddress(hNotificationLib, "removeNotification");
|
||||
#if 1 //defined(DEBUG)
|
||||
#if defined(DEBUG)
|
||||
NSLog(@"%s:DLL ptr: %p send notification ptr: %p remove ptr: %p", __PRETTY_FUNCTION__,
|
||||
hNotificationLib, pSendNotification, pRemoveNotification);
|
||||
#endif
|
||||
|
@ -183,6 +189,9 @@ static NSString * const kButtonActionKey = @"show";
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
NSLog(@"%s:", __PRETTY_FUNCTION__);
|
||||
#endif
|
||||
// Cleanup any icons we generated...
|
||||
NSEnumerator *iter = [imageToIcon objectEnumerator];
|
||||
HICON icon = NULL;
|
||||
|
@ -191,8 +200,8 @@ static NSString * const kButtonActionKey = @"show";
|
|||
DestroyIcon(icon);
|
||||
}
|
||||
|
||||
RELEASE(appIconPath);
|
||||
RELEASE(imageToIcon);
|
||||
DESTROY(appIconPath);
|
||||
DESTROY(imageToIcon);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -229,10 +238,10 @@ static NSString * const kButtonActionKey = @"show";
|
|||
* must first check that any existing image of the same name has its
|
||||
* name removed.
|
||||
*/
|
||||
[(NSImage*)[NSImage imageNamed: @"NSApplicationIcon"] setName: nil];
|
||||
//[(NSImage*)[NSImage imageNamed: @"NSApplicationIcon"] setName: nil];
|
||||
// We need to copy the image as we may have a proxy here
|
||||
image = AUTORELEASE([image copy]);
|
||||
[image setName: @"NSApplicationIcon"];
|
||||
//[image setName: @"NSApplicationIcon"];
|
||||
}
|
||||
}
|
||||
return image;
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -5,12 +5,12 @@ using namespace ABI::Windows::UI::Notifications;
|
|||
|
||||
ToastEventHandler::ToastEventHandler(_In_ HWND hToActivate, _In_ HWND hEdit) : _ref(1), _hToActivate(hToActivate), _hEdit(hEdit)
|
||||
{
|
||||
dll_dlog("");
|
||||
dll_dlog("this: %p", this);
|
||||
}
|
||||
|
||||
ToastEventHandler::~ToastEventHandler()
|
||||
{
|
||||
dll_dlog("");
|
||||
dll_dlog("this: %p", this);
|
||||
}
|
||||
|
||||
// DesktopToastActivatedEventHandler
|
||||
|
@ -52,6 +52,7 @@ IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* sender, _In_ I
|
|||
}
|
||||
|
||||
dll_dlogw(L"IToastNotePtr: %p msg: %s", sender, outputText);
|
||||
//notifier->RemoveFromSchedule
|
||||
|
||||
LRESULT succeeded = SendMessage(_hEdit, WM_SETTEXT, reinterpret_cast<WPARAM>(nullptr), reinterpret_cast<LPARAM>(outputText));
|
||||
hr = succeeded ? S_OK : E_FAIL;
|
||||
|
@ -67,3 +68,22 @@ IFACEMETHODIMP ToastEventHandler::Invoke(_In_ IToastNotification* /* sender */,
|
|||
LRESULT succeeded = SendMessage(_hEdit, WM_SETTEXT, reinterpret_cast<WPARAM>(nullptr), reinterpret_cast<LPARAM>(L"The toast encountered an error."));
|
||||
return succeeded ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) ToastEventHandler::AddRef()
|
||||
{
|
||||
LONG value = InterlockedIncrement(&_ref);
|
||||
dll_dlog("ref: %d value: %d", _ref, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) ToastEventHandler::Release()
|
||||
{
|
||||
ULONG l = InterlockedDecrement(&_ref);
|
||||
dll_dlog("ref: %d value: %d", _ref, l);
|
||||
if (l == 0)
|
||||
{
|
||||
dll_dlog("deleting this: %p", this);
|
||||
delete this;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
|
|
@ -21,13 +21,9 @@ public:
|
|||
IFACEMETHODIMP Invoke(_In_ ABI::Windows::UI::Notifications::IToastNotification *sender, _In_ ABI::Windows::UI::Notifications::IToastFailedEventArgs *e);
|
||||
|
||||
// IUnknown
|
||||
IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_ref); }
|
||||
IFACEMETHODIMP_(ULONG) AddRef();
|
||||
|
||||
IFACEMETHODIMP_(ULONG) Release() {
|
||||
ULONG l = InterlockedDecrement(&_ref);
|
||||
if (l == 0) delete this;
|
||||
return l;
|
||||
}
|
||||
IFACEMETHODIMP_(ULONG) Release();
|
||||
|
||||
IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _COM_Outptr_ void **ppv) {
|
||||
if (IsEqualIID(riid, IID_IUnknown))
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
#include "stdafx.h"
|
||||
#include "ToastNotification.h"
|
||||
#include "ToastEventHandler.h"
|
||||
|
||||
using namespace ABI::Windows::UI::Notifications;
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
CToastNotification::CToastNotification(IToastNotification *toastNotification, HWND _hwnd)
|
||||
{
|
||||
dll_dlog("this: %p, toast: %p", this, toastNotification);
|
||||
|
||||
this->toastNotification = toastNotification;
|
||||
|
||||
// Register the event handlers
|
||||
ComPtr<ToastEventHandler> eventHandler(new ToastEventHandler(_hwnd, _hwnd));
|
||||
toastEventHandler = eventHandler.Get();
|
||||
|
||||
HRESULT hr = toastNotification->add_Activated(eventHandler.Get(), &activatedToken);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dll_log("toast->add_Activated failed - status: %d", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
dll_dlog("activatedToken: %d", activatedToken.value);
|
||||
hr = toastNotification->add_Dismissed(eventHandler.Get(), &dismissedToken);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dll_log("toast->add_Dismissed failed - status: %d", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
dll_dlog("dismissedToken: %d", dismissedToken.value);
|
||||
hr = toastNotification->add_Failed(eventHandler.Get(), &failedToken);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dll_log("toast->add_Failed failed - status: %d", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
dll_dlog("failedToken: %d - DONE", failedToken.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CToastNotification::~CToastNotification()
|
||||
{
|
||||
dll_dlog("this: %p toast: %p", this, toastNotification);
|
||||
#if 0
|
||||
toastNotification->remove_Activated(activatedToken);
|
||||
toastNotification->remove_Dismissed(dismissedToken);
|
||||
toastNotification->remove_Failed(failedToken);
|
||||
#endif
|
||||
delete toastEventHandler;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
#include "afx.h"
|
||||
|
||||
class ToastEventHandler;
|
||||
|
||||
class CToastNotification : public CObject
|
||||
{
|
||||
public:
|
||||
CToastNotification(ABI::Windows::UI::Notifications::IToastNotification * toastNotification, HWND _hwnd);
|
||||
~CToastNotification();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
ABI::Windows::UI::Notifications::IToastNotification *toastNotification;
|
||||
ToastEventHandler *toastEventHandler;
|
||||
EventRegistrationToken activatedToken;
|
||||
EventRegistrationToken dismissedToken;
|
||||
EventRegistrationToken failedToken;
|
||||
};
|
|
@ -11,7 +11,7 @@
|
|||
#include <Windows.ui.notifications.h>
|
||||
#include <strsafe.h>
|
||||
#include "ToastNotifications.h"
|
||||
#include "ToastEventHandler.h"
|
||||
#include "ToastNotification.h"
|
||||
#include "../../../MSUserNotificationAPI.h"
|
||||
|
||||
#include <locale>
|
||||
|
@ -51,7 +51,6 @@ using namespace Windows::Foundation;
|
|||
// Please see MFC Technical Notes 33 and 58 for additional
|
||||
// details.
|
||||
//
|
||||
|
||||
// CToastNotificationsApp
|
||||
|
||||
BEGIN_MESSAGE_MAP(CToastNotificationsApp, CWinApp)
|
||||
|
@ -62,12 +61,12 @@ CToastNotificationsApp::CToastNotificationsApp()
|
|||
{
|
||||
// TODO: add construction code here,
|
||||
// Place all significant initialization in InitInstance
|
||||
dll_dlog("");
|
||||
dll_dlog("this: %p", this);
|
||||
}
|
||||
|
||||
CToastNotificationsApp::~CToastNotificationsApp()
|
||||
{
|
||||
dll_dlog("");
|
||||
dll_dlog("this: %p", this);
|
||||
}
|
||||
|
||||
// The one and only CToastNotificationsApp object
|
||||
|
@ -79,10 +78,33 @@ CToastNotificationsApp theApp;
|
|||
|
||||
BOOL CToastNotificationsApp::InitInstance()
|
||||
{
|
||||
dll_dlog("this: %p", this);
|
||||
CWinApp::InitInstance();
|
||||
|
||||
// Do our cleanup here AFTER invoking sub-class method...
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CToastNotificationsApp::ExitInstance()
|
||||
{
|
||||
dll_dlog("this: %p", this);
|
||||
|
||||
// Do our cleanup here BEFORE invoking sub-class method...
|
||||
if (toasts.size() > 0)
|
||||
{
|
||||
dll_dlog("deleting toast - cnt: %d", toasts.size());
|
||||
std::vector<CToastNotification*>::iterator toast;
|
||||
for (toast = toasts.begin(); toast < toasts.end(); ++toast)
|
||||
{
|
||||
dll_dlog("toast ptr: %p", *toast);
|
||||
delete *toast;
|
||||
}
|
||||
}
|
||||
|
||||
return CWinApp::ExitInstance();
|
||||
}
|
||||
|
||||
// In order to display toasts, a desktop application must have a shortcut on the Start menu.
|
||||
// Also, an AppUserModelID must be set on that shortcut.
|
||||
// The shortcut should be created as part of the installer. The following code shows how to create
|
||||
|
@ -91,7 +113,6 @@ BOOL CToastNotificationsApp::InitInstance()
|
|||
//
|
||||
// Included in this project is a wxs file that be used with the WiX toolkit
|
||||
// to make an installer that creates the necessary shortcut. One or the other should be used.
|
||||
|
||||
HRESULT CToastNotificationsApp::TryCreateShortcut()
|
||||
{
|
||||
wchar_t shortcutPath[MAX_PATH];
|
||||
|
@ -204,7 +225,7 @@ HRESULT CToastNotificationsApp::CreateToastXml(_In_ IToastNotificationManagerSta
|
|||
// Get full path to image...
|
||||
imagePath = _wfullpath(nullptr, imagePath, MAX_PATH);
|
||||
|
||||
dll_logw(TEXT("loading application image file: %s"), imagePath);
|
||||
dll_dlogw(TEXT("loading application image file: %s"), imagePath);
|
||||
hr = imagePath != nullptr ? S_OK : HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
|
||||
if (FAILED(hr))
|
||||
|
@ -231,6 +252,9 @@ HRESULT CToastNotificationsApp::CreateToastXml(_In_ IToastNotificationManagerSta
|
|||
UINT32 textLengths[] = { wcslen(notificationTitle), wcslen(notificationDescription), 6 };
|
||||
hr = SetTextValues(textValues, 3, textLengths, *inputXml);
|
||||
}
|
||||
|
||||
// Delete/free imagePath from _wfullpath call above...
|
||||
free(imagePath);
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
|
@ -412,35 +436,10 @@ HRESULT CToastNotificationsApp::CreateToast(_In_ IToastNotificationManagerStatic
|
|||
}
|
||||
else
|
||||
{
|
||||
// Register the event handlers
|
||||
EventRegistrationToken activatedToken, dismissedToken, failedToken;
|
||||
ComPtr<ToastEventHandler> eventHandler(new ToastEventHandler(_hwnd, _hwnd));
|
||||
|
||||
toast->add_Activated(eventHandler.Get(), &activatedToken);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dll_log("toast->add_Activated failed - status: %d", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = toast->add_Dismissed(eventHandler.Get(), &dismissedToken);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dll_log("toast->add_Dismissed failed - status: %d", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = toast->add_Failed(eventHandler.Get(), &failedToken);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dll_log("toast->add_Failed failed - status: %d", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = notifier->Show(toast.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
CToastNotification *toastNotification = new CToastNotification(toast.Get(), _hwnd);
|
||||
hr = notifier->Show(toast.Get());
|
||||
if (SUCCEEDED(hr))
|
||||
toasts.push_back(toastNotification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -519,6 +518,6 @@ extern "C" EXPORT BOOL __cdecl sendNotification(HWND hWnd, HICON icon, SEND_NOTE
|
|||
extern "C" EXPORT BOOL __cdecl removeNotification(HICON icon, REMOVE_NOTE_INFO_T *noteinfo)
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
dll_log("note %p uniqueID: %d", noteinfo, noteinfo->uniqueID);
|
||||
dll_dlog("note %p uniqueID: %d", noteinfo, noteinfo->uniqueID);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -2,21 +2,20 @@
|
|||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#
|
||||
#ifndef __AFXWIN_H__
|
||||
#error "include 'stdafx.h' before including this file for PCH"
|
||||
#endif
|
||||
|
||||
#include "resource.h" // main symbols
|
||||
#include <vector>
|
||||
|
||||
const wchar_t AppId[] = L"Testplant.Notifications.Eggplant";
|
||||
|
||||
|
||||
|
||||
|
||||
// CToastNotificationsApp
|
||||
// See ToastNotifications.cpp for the implementation of this class
|
||||
//
|
||||
class CToastNotification;
|
||||
|
||||
class CToastNotificationsApp : public CWinApp
|
||||
{
|
||||
|
@ -26,13 +25,13 @@ public:
|
|||
|
||||
// Overrides
|
||||
public:
|
||||
virtual BOOL InitInstance();
|
||||
virtual BOOL InitInstance();
|
||||
virtual BOOL ExitInstance();
|
||||
|
||||
DECLARE_MESSAGE_MAP()
|
||||
friend class ToastEventHandler;
|
||||
|
||||
public:
|
||||
//HRESULT DisplayToast(HWND hWnd, wchar_t* notificationTitle, wchar_t* notificationDescription);
|
||||
HRESULT DisplayToast(HWND hWnd, wchar_t* notificationTitle, wchar_t* notificationDescription, wchar_t* imagePath);
|
||||
HRESULT CreateToastXml(
|
||||
_In_ ABI::Windows::UI::Notifications::IToastNotificationManagerStatics *toastManager,
|
||||
|
@ -64,4 +63,5 @@ protected:
|
|||
private:
|
||||
HWND _hwnd;
|
||||
HWND _hEdit;
|
||||
std::vector<CToastNotification*> toasts;
|
||||
};
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ToastEventHandler.cpp" />
|
||||
<ClCompile Include="ToastNotification.cpp" />
|
||||
<ClCompile Include="ToastNotifications.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -117,6 +118,7 @@
|
|||
<ClInclude Include="StringReferenceWrapper.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="ToastEventHandler.h" />
|
||||
<ClInclude Include="ToastNotification.h" />
|
||||
<ClInclude Include="ToastNotifications.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -126,9 +128,6 @@
|
|||
<ItemGroup>
|
||||
<ResourceCompile Include="ToastNotifications.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="toastImageAndText.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
<ClCompile Include="ToastEventHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ToastNotification.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ToastNotifications.h">
|
||||
|
@ -47,6 +50,9 @@
|
|||
<ClInclude Include="ToastEventHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ToastNotification.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ToastNotifications.def">
|
||||
|
@ -61,9 +67,4 @@
|
|||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="toastImageAndText.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -3,12 +3,14 @@
|
|||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
void dll_log_s(const char *function, int line, const char *format, ...)
|
||||
{
|
||||
static const size_t STRBUFSIZE = 512;
|
||||
static char str[STRBUFSIZE];
|
||||
std::stringstream message;
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
sprintf_s(str, STRBUFSIZE, "%s:%d: ", function, line);
|
||||
|
|
Loading…
Reference in a new issue