From: Vadim Zeitlin Date: Fri, 5 Nov 2010 21:43:18 +0000 (+0000) Subject: Avoid using wx GDI classes from non-main thread in wxOSX/Cocoa. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/c71096a05575db197c20fa78a63ee1195d615d27 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 --- diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 67138edc01..d5865bfdc4 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -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) {