Fix macOS memory leaks, also avoid false positive warnings from clang analyzer
__clang_analyzer__ is a constant that only is defined during analyze build, this helps avoiding false positives as long as there is no specific way to silence analyzer messages
This commit is contained in:
@@ -1013,6 +1013,83 @@ void wxMacCocoaRelease( void* obj );
|
|||||||
void wxMacCocoaAutorelease( void* obj );
|
void wxMacCocoaAutorelease( void* obj );
|
||||||
void* wxMacCocoaRetain( void* obj );
|
void* wxMacCocoaRetain( void* obj );
|
||||||
|
|
||||||
|
// shared_ptr like API for NSObject and subclasses
|
||||||
|
template <class T>
|
||||||
|
class wxNSObjRef
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
wxNSObjRef()
|
||||||
|
: m_ptr(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxNSObjRef( T p )
|
||||||
|
: m_ptr(p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxNSObjRef( const wxNSObjRef& otherRef )
|
||||||
|
: m_ptr(wxMacCocoaRetain(otherRef.m_ptr))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxNSObjRef& operator=( const wxNSObjRef& otherRef )
|
||||||
|
{
|
||||||
|
if (this != &otherRef)
|
||||||
|
{
|
||||||
|
wxMacCocoaRetain(otherRef.m_ptr);
|
||||||
|
wxMacCocoaRelease(m_ptr);
|
||||||
|
m_ptr = otherRef.m_ptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxNSObjRef& operator=( T ptr )
|
||||||
|
{
|
||||||
|
if (get() != ptr)
|
||||||
|
{
|
||||||
|
wxMacCocoaRetain(ptr);
|
||||||
|
wxMacCocoaRelease(m_ptr);
|
||||||
|
m_ptr = ptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
T get() const
|
||||||
|
{
|
||||||
|
return m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T() const
|
||||||
|
{
|
||||||
|
return m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator->() const
|
||||||
|
{
|
||||||
|
return m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset( T p = NULL )
|
||||||
|
{
|
||||||
|
wxMacCocoaRelease(m_ptr);
|
||||||
|
m_ptr = p; // Automatic conversion should occur
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the pointer, i.e. give up its ownership.
|
||||||
|
T release()
|
||||||
|
{
|
||||||
|
T p = m_ptr;
|
||||||
|
m_ptr = NULL;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T m_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// _WX_PRIVATE_CORE_H_
|
// _WX_PRIVATE_CORE_H_
|
||||||
|
@@ -160,11 +160,13 @@ private:
|
|||||||
|
|
||||||
OSXWebViewPtr m_webView;
|
OSXWebViewPtr m_webView;
|
||||||
|
|
||||||
|
WX_NSObject m_loadDelegate;
|
||||||
|
WX_NSObject m_policyDelegate;
|
||||||
|
WX_NSObject m_UIDelegate;
|
||||||
|
|
||||||
// we may use this later to setup our own mouse events,
|
// we may use this later to setup our own mouse events,
|
||||||
// so leave it in for now.
|
// so leave it in for now.
|
||||||
void* m_webKitCtrlEventHandler;
|
void* m_webKitCtrlEventHandler;
|
||||||
//It should be WebView*, but WebView is an Objective-C class
|
|
||||||
//TODO: look into using DECLARE_WXCOCOA_OBJC_CLASS rather than this.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class WXDLLIMPEXP_WEBVIEW wxWebViewFactoryWebKit : public wxWebViewFactory
|
class WXDLLIMPEXP_WEBVIEW wxWebViewFactoryWebKit : public wxWebViewFactory
|
||||||
|
@@ -374,17 +374,17 @@ CGImageRef wxOSXCreateCGImageFromImage( WXImage nsimage, double *scaleptr )
|
|||||||
|
|
||||||
#if wxOSX_USE_COCOA
|
#if wxOSX_USE_COCOA
|
||||||
|
|
||||||
static NSCursor* wxGetStockCursor( short sIndex )
|
static NSCursor* wxCreateStockCursor( short sIndex )
|
||||||
{
|
{
|
||||||
ClassicCursor* pCursor = &gMacCursors[sIndex];
|
|
||||||
|
|
||||||
//Classic mac cursors are 1bps 16x16 black and white with a
|
//Classic mac cursors are 1bps 16x16 black and white with a
|
||||||
//identical mask that is 1 for on and 0 for off
|
//identical mask that is 1 for on and 0 for off
|
||||||
NSImage *theImage = [[NSImage alloc] initWithSize:NSMakeSize(16.0,16.0)];
|
ClassicCursor* pCursor = &gMacCursors[sIndex];
|
||||||
|
|
||||||
|
wxNSObjRef<NSImage*> theImage( [[NSImage alloc] initWithSize:NSMakeSize(16.0,16.0)] );
|
||||||
|
|
||||||
//NSCursor takes an NSImage takes a number of Representations - here
|
//NSCursor takes an NSImage takes a number of Representations - here
|
||||||
//we need only one for the raw data
|
//we need only one for the raw data
|
||||||
NSBitmapImageRep *theRep = [[NSBitmapImageRep alloc]
|
wxNSObjRef<NSBitmapImageRep*> theRep( [[NSBitmapImageRep alloc]
|
||||||
initWithBitmapDataPlanes: NULL // Tell Cocoa to allocate the planes for us.
|
initWithBitmapDataPlanes: NULL // Tell Cocoa to allocate the planes for us.
|
||||||
pixelsWide: 16 // All classic cursors are 16x16
|
pixelsWide: 16 // All classic cursors are 16x16
|
||||||
pixelsHigh: 16
|
pixelsHigh: 16
|
||||||
@@ -394,16 +394,16 @@ static NSCursor* wxGetStockCursor( short sIndex )
|
|||||||
isPlanar: YES // Use a separate array for each sample
|
isPlanar: YES // Use a separate array for each sample
|
||||||
colorSpaceName: NSCalibratedWhiteColorSpace // 0.0=black 1.0=white
|
colorSpaceName: NSCalibratedWhiteColorSpace // 0.0=black 1.0=white
|
||||||
bytesPerRow: 2 // Rows in each plane are on 2-byte boundaries (no pad)
|
bytesPerRow: 2 // Rows in each plane are on 2-byte boundaries (no pad)
|
||||||
bitsPerPixel: 1]; // same as bitsPerSample since data is planar
|
bitsPerPixel: 1] ); // same as bitsPerSample since data is planar
|
||||||
|
|
||||||
// Ensure that Cocoa allocated 2 and only 2 of the 5 possible planes
|
// Ensure that Cocoa allocated 2 and only 2 of the 5 possible planes
|
||||||
unsigned char *planes[5];
|
unsigned char *planes[5];
|
||||||
[theRep getBitmapDataPlanes:planes];
|
[theRep getBitmapDataPlanes:planes];
|
||||||
wxASSERT(planes[0] != NULL);
|
wxCHECK(planes[0] != NULL, nil);
|
||||||
wxASSERT(planes[1] != NULL);
|
wxCHECK(planes[1] != NULL, nil);
|
||||||
wxASSERT(planes[2] == NULL);
|
wxCHECK(planes[2] == NULL, nil);
|
||||||
wxASSERT(planes[3] == NULL);
|
wxCHECK(planes[3] == NULL, nil);
|
||||||
wxASSERT(planes[4] == NULL);
|
wxCHECK(planes[4] == NULL, nil);
|
||||||
|
|
||||||
// NOTE1: The Cursor's bits field is white=0 black=1.. thus the bitwise-not
|
// NOTE1: The Cursor's bits field is white=0 black=1.. thus the bitwise-not
|
||||||
// Why not use NSCalibratedBlackColorSpace? Because that reverses the
|
// Why not use NSCalibratedBlackColorSpace? Because that reverses the
|
||||||
@@ -437,10 +437,6 @@ static NSCursor* wxGetStockCursor( short sIndex )
|
|||||||
hotSpot:NSMakePoint(pCursor->hotspot[1], pCursor->hotspot[0])
|
hotSpot:NSMakePoint(pCursor->hotspot[1], pCursor->hotspot[0])
|
||||||
];
|
];
|
||||||
|
|
||||||
//do the usual cleanups
|
|
||||||
[theRep release];
|
|
||||||
[theImage release];
|
|
||||||
|
|
||||||
//return the new cursor
|
//return the new cursor
|
||||||
return theCursor;
|
return theCursor;
|
||||||
}
|
}
|
||||||
@@ -460,7 +456,7 @@ WX_NSCursor wxMacCocoaCreateStockCursor( int cursor_type )
|
|||||||
// according to the HIG
|
// according to the HIG
|
||||||
// cursor = [[NSCursor arrowCursor] retain];
|
// cursor = [[NSCursor arrowCursor] retain];
|
||||||
// but for crossplatform compatibility we display a watch cursor
|
// but for crossplatform compatibility we display a watch cursor
|
||||||
cursor = wxGetStockCursor(kwxCursorWatch);
|
cursor = wxCreateStockCursor(kwxCursorWatch);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_IBEAM:
|
case wxCURSOR_IBEAM:
|
||||||
@@ -472,11 +468,11 @@ WX_NSCursor wxMacCocoaCreateStockCursor( int cursor_type )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_SIZENWSE:
|
case wxCURSOR_SIZENWSE:
|
||||||
cursor = wxGetStockCursor(kwxCursorSizeNWSE);
|
cursor = wxCreateStockCursor(kwxCursorSizeNWSE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_SIZENESW:
|
case wxCURSOR_SIZENESW:
|
||||||
cursor = wxGetStockCursor(kwxCursorSizeNESW);
|
cursor = wxCreateStockCursor(kwxCursorSizeNESW);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_SIZEWE:
|
case wxCURSOR_SIZEWE:
|
||||||
@@ -488,7 +484,7 @@ WX_NSCursor wxMacCocoaCreateStockCursor( int cursor_type )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_SIZING:
|
case wxCURSOR_SIZING:
|
||||||
cursor = wxGetStockCursor(kwxCursorSize);
|
cursor = wxCreateStockCursor(kwxCursorSize);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_HAND:
|
case wxCURSOR_HAND:
|
||||||
@@ -496,47 +492,47 @@ WX_NSCursor wxMacCocoaCreateStockCursor( int cursor_type )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_BULLSEYE:
|
case wxCURSOR_BULLSEYE:
|
||||||
cursor = wxGetStockCursor(kwxCursorBullseye);
|
cursor = wxCreateStockCursor(kwxCursorBullseye);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_PENCIL:
|
case wxCURSOR_PENCIL:
|
||||||
cursor = wxGetStockCursor(kwxCursorPencil);
|
cursor = wxCreateStockCursor(kwxCursorPencil);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_MAGNIFIER:
|
case wxCURSOR_MAGNIFIER:
|
||||||
cursor = wxGetStockCursor(kwxCursorMagnifier);
|
cursor = wxCreateStockCursor(kwxCursorMagnifier);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_NO_ENTRY:
|
case wxCURSOR_NO_ENTRY:
|
||||||
cursor = wxGetStockCursor(kwxCursorNoEntry);
|
cursor = wxCreateStockCursor(kwxCursorNoEntry);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_PAINT_BRUSH:
|
case wxCURSOR_PAINT_BRUSH:
|
||||||
cursor = wxGetStockCursor(kwxCursorPaintBrush);
|
cursor = wxCreateStockCursor(kwxCursorPaintBrush);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_POINT_LEFT:
|
case wxCURSOR_POINT_LEFT:
|
||||||
cursor = wxGetStockCursor(kwxCursorPointLeft);
|
cursor = wxCreateStockCursor(kwxCursorPointLeft);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_POINT_RIGHT:
|
case wxCURSOR_POINT_RIGHT:
|
||||||
cursor = wxGetStockCursor(kwxCursorPointRight);
|
cursor = wxCreateStockCursor(kwxCursorPointRight);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_QUESTION_ARROW:
|
case wxCURSOR_QUESTION_ARROW:
|
||||||
cursor = wxGetStockCursor(kwxCursorQuestionArrow);
|
cursor = wxCreateStockCursor(kwxCursorQuestionArrow);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_BLANK:
|
case wxCURSOR_BLANK:
|
||||||
cursor = wxGetStockCursor(kwxCursorBlank);
|
cursor = wxCreateStockCursor(kwxCursorBlank);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_RIGHT_ARROW:
|
case wxCURSOR_RIGHT_ARROW:
|
||||||
cursor = wxGetStockCursor(kwxCursorRightArrow);
|
cursor = wxCreateStockCursor(kwxCursorRightArrow);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_SPRAYCAN:
|
case wxCURSOR_SPRAYCAN:
|
||||||
cursor = wxGetStockCursor(kwxCursorRoller);
|
cursor = wxCreateStockCursor(kwxCursorRoller);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_OPEN_HAND:
|
case wxCURSOR_OPEN_HAND:
|
||||||
@@ -547,15 +543,21 @@ WX_NSCursor wxMacCocoaCreateStockCursor( int cursor_type )
|
|||||||
cursor = [[NSCursor closedHandCursor] retain];
|
cursor = [[NSCursor closedHandCursor] retain];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCURSOR_CHAR:
|
|
||||||
case wxCURSOR_ARROW:
|
case wxCURSOR_ARROW:
|
||||||
|
cursor = [[NSCursor arrowCursor] retain];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxCURSOR_CHAR:
|
||||||
case wxCURSOR_LEFT_BUTTON:
|
case wxCURSOR_LEFT_BUTTON:
|
||||||
case wxCURSOR_RIGHT_BUTTON:
|
case wxCURSOR_RIGHT_BUTTON:
|
||||||
case wxCURSOR_MIDDLE_BUTTON:
|
case wxCURSOR_MIDDLE_BUTTON:
|
||||||
default:
|
default:
|
||||||
cursor = [[NSCursor arrowCursor] retain];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( cursor == nil )
|
||||||
|
cursor = [[NSCursor arrowCursor] retain];
|
||||||
|
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -254,6 +254,7 @@ public :
|
|||||||
[windowMenuItem setSubmenu:windowMenu];
|
[windowMenuItem setSubmenu:windowMenu];
|
||||||
[windowMenu release];
|
[windowMenu release];
|
||||||
[m_osxMenu addItem:windowMenuItem];
|
[m_osxMenu addItem:windowMenuItem];
|
||||||
|
[windowMenuItem release];
|
||||||
}
|
}
|
||||||
return windowMenu;
|
return windowMenu;
|
||||||
}
|
}
|
||||||
|
@@ -3563,11 +3563,14 @@ bool wxWidgetCocoaImpl::EnableTouchEvents(int eventsMask)
|
|||||||
}
|
}
|
||||||
else // We do want to have gesture events.
|
else // We do want to have gesture events.
|
||||||
{
|
{
|
||||||
|
// clang does not see that the owning object always destroys its extra field
|
||||||
|
#ifndef __clang_analyzer__
|
||||||
wxCocoaGestures::StoreForObject
|
wxCocoaGestures::StoreForObject
|
||||||
(
|
(
|
||||||
this,
|
this,
|
||||||
new wxCocoaGesturesImpl(this, m_osxView, eventsMask)
|
new wxCocoaGesturesImpl(this, m_osxView, eventsMask)
|
||||||
);
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
[m_osxView setAcceptsTouchEvents:YES];
|
[m_osxView setAcceptsTouchEvents:YES];
|
||||||
}
|
}
|
||||||
|
@@ -138,16 +138,22 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
|
|||||||
|
|
||||||
[m_webView setFrameLoadDelegate:loadDelegate];
|
[m_webView setFrameLoadDelegate:loadDelegate];
|
||||||
|
|
||||||
|
m_loadDelegate = loadDelegate;
|
||||||
|
|
||||||
// this is used to veto page loads, etc.
|
// this is used to veto page loads, etc.
|
||||||
WebViewPolicyDelegate* policyDelegate =
|
WebViewPolicyDelegate* policyDelegate =
|
||||||
[[WebViewPolicyDelegate alloc] initWithWxWindow: this];
|
[[WebViewPolicyDelegate alloc] initWithWxWindow: this];
|
||||||
|
|
||||||
[m_webView setPolicyDelegate:policyDelegate];
|
[m_webView setPolicyDelegate:policyDelegate];
|
||||||
|
|
||||||
|
m_policyDelegate = policyDelegate;
|
||||||
|
|
||||||
WebViewUIDelegate* uiDelegate =
|
WebViewUIDelegate* uiDelegate =
|
||||||
[[WebViewUIDelegate alloc] initWithWxWindow: this];
|
[[WebViewUIDelegate alloc] initWithWxWindow: this];
|
||||||
|
|
||||||
[m_webView setUIDelegate:uiDelegate];
|
[m_webView setUIDelegate:uiDelegate];
|
||||||
|
|
||||||
|
m_UIDelegate = uiDelegate;
|
||||||
#endif
|
#endif
|
||||||
//Register our own class for custom scheme handling
|
//Register our own class for custom scheme handling
|
||||||
[NSURLProtocol registerClass:[WebViewCustomProtocol class]];
|
[NSURLProtocol registerClass:[WebViewCustomProtocol class]];
|
||||||
@@ -160,21 +166,13 @@ wxWebViewWebKit::~wxWebViewWebKit()
|
|||||||
{
|
{
|
||||||
#if wxOSX_USE_IPHONE
|
#if wxOSX_USE_IPHONE
|
||||||
#else
|
#else
|
||||||
WebViewLoadDelegate* loadDelegate = [m_webView frameLoadDelegate];
|
|
||||||
WebViewPolicyDelegate* policyDelegate = [m_webView policyDelegate];
|
|
||||||
WebViewUIDelegate* uiDelegate = [m_webView UIDelegate];
|
|
||||||
[m_webView setFrameLoadDelegate: nil];
|
[m_webView setFrameLoadDelegate: nil];
|
||||||
[m_webView setPolicyDelegate: nil];
|
[m_webView setPolicyDelegate: nil];
|
||||||
[m_webView setUIDelegate: nil];
|
[m_webView setUIDelegate: nil];
|
||||||
|
|
||||||
if (loadDelegate)
|
[m_loadDelegate release];
|
||||||
[loadDelegate release];
|
[m_policyDelegate release];
|
||||||
|
[m_UIDelegate release];
|
||||||
if (policyDelegate)
|
|
||||||
[policyDelegate release];
|
|
||||||
|
|
||||||
if (uiDelegate)
|
|
||||||
[uiDelegate release];
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1033,7 +1031,15 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebViewNavigationError* out)
|
|||||||
|
|
||||||
wxString wxpath = wxCFStringRef::AsString(path);
|
wxString wxpath = wxCFStringRef::AsString(path);
|
||||||
wxString scheme = wxCFStringRef::AsString([[request URL] scheme]);
|
wxString scheme = wxCFStringRef::AsString([[request URL] scheme]);
|
||||||
|
|
||||||
|
// since canInitRequest has already checked whether this scheme is supported
|
||||||
|
// the hash map contains this entry, but to satisfy static code analysis
|
||||||
|
// suspecting nullptr dereference ...
|
||||||
|
#ifndef __clang_analyzer__
|
||||||
wxFSFile* file = g_stringHandlerMap[scheme]->GetFile(wxpath);
|
wxFSFile* file = g_stringHandlerMap[scheme]->GetFile(wxpath);
|
||||||
|
#else
|
||||||
|
wxFSFile* file = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
@@ -1043,6 +1049,8 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebViewNavigationError* out)
|
|||||||
|
|
||||||
[client URLProtocol:self didFailWithError:error];
|
[client URLProtocol:self didFailWithError:error];
|
||||||
|
|
||||||
|
[error release];
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,6 +1077,8 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebViewNavigationError* out)
|
|||||||
//Notify that we have finished
|
//Notify that we have finished
|
||||||
[client URLProtocolDidFinishLoading:self];
|
[client URLProtocolDidFinishLoading:self];
|
||||||
|
|
||||||
|
[data release];
|
||||||
|
|
||||||
[response release];
|
[response release];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -111,6 +111,7 @@ WX_NSWindow CreateFloatingWindow(wxWindow* wxWin)
|
|||||||
|
|
||||||
void CloseFloatingWindow(WX_NSWindow nsWin)
|
void CloseFloatingWindow(WX_NSWindow nsWin)
|
||||||
{
|
{
|
||||||
|
[nsWin setReleasedWhenClosed:YES];
|
||||||
[nsWin close];
|
[nsWin close];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user