]> git.saurik.com Git - wxWidgets.git/commitdiff
Avoid using wx GDI classes from non-main thread in wxOSX/Cocoa.
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 5 Nov 2010 21:43:18 +0000 (21:43 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 5 Nov 2010 21:43:18 +0000 (21:43 +0000)
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

src/osx/cocoa/window.mm

index 67138edc014c74d9ddeedea681ec1a07bcd760bc..d5865bfdc491be2a710abed0e31f2f3bae991eb1 100644 (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)
 {