Avoid using wx GDI classes from non-main thread in wxOSX/Cocoa.

OS X uses a background thread for pulsing the default button and we intercept
the draw requests from it. As our drawing code is not MT-safe, executing it
from the non-main thread can result in crashes.

Avoid this by simply not doing anything fancy when called from a background
thread and simply deferring to the superclass instead.

Closes #12407.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@66041 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2010-11-05 21:43:18 +00:00
parent ed310c35b4
commit c71096a055

View File

@@ -784,12 +784,34 @@ BOOL wxOSX_isFlipped(NSView* self, SEL _cmd)
return impl->isFlipped(self, _cmd) ? YES:NO;
}
typedef void (*wxOSX_DrawRectHandlerPtr)(NSView* self, SEL _cmd, NSRect rect);
void wxOSX_drawRect(NSView* self, SEL _cmd, NSRect rect)
{
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
if (impl == NULL)
return;
#ifdef wxUSE_THREADS
// OS X starts a NSUIHeartBeatThread for animating the default button in a
// dialog. This causes a drawRect of the active dialog from outside the
// main UI thread. This causes an occasional crash since the wx drawing
// objects (like wxPen) are not thread safe.
//
// Notice that NSUIHeartBeatThread seems to be undocumented and doing
// [NSWindow setAllowsConcurrentViewDrawing:NO] does not affect it.
if ( !wxThread::IsMain() )
{
// just call the superclass handler, we don't need any custom wx drawing
// here and it seems to work fine:
wxOSX_DrawRectHandlerPtr
superimpl = (wxOSX_DrawRectHandlerPtr)
[[self superclass] instanceMethodForSelector:_cmd];
superimpl(self, _cmd, rect);
return;
}
#endif // wxUSE_THREADS
return impl->drawRect(&rect, self, _cmd);
}
@@ -960,7 +982,6 @@ typedef void (*wxOSX_EventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
typedef BOOL (*wxOSX_PerformKeyEventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
typedef BOOL (*wxOSX_FocusHandlerPtr)(NSView* self, SEL _cmd);
typedef BOOL (*wxOSX_ResetCursorRectsHandlerPtr)(NSView* self, SEL _cmd);
typedef void (*wxOSX_DrawRectHandlerPtr)(NSView* self, SEL _cmd, NSRect rect);
void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
{