Commit e9c7b5191c3ed783489d66ba825f2101810a9b58

Alex Szpakowski 2022-05-16T21:03:41

macOS: Fix reference counts of internal window data. Fixes crashes when destroying or recreating a window (#5664).

diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h
index 0fd29ce..6132455 100644
--- a/src/video/cocoa/SDL_cocoawindow.h
+++ b/src/video/cocoa/SDL_cocoawindow.h
@@ -40,7 +40,10 @@ typedef enum
 } PendingWindowOperation;
 
 @interface Cocoa_WindowListener : NSResponder <NSWindowDelegate> {
-    SDL_WindowData *_data;
+    /* SDL_WindowData owns this Listener and has a strong reference to it.
+     * To avoid reference cycles, we could have either a weak or an
+     * unretained ref to the WindowData. */
+    __weak SDL_WindowData *_data;
     BOOL observingVisible;
     BOOL wasCtrlLeft;
     BOOL wasVisible;
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index 7943025..44e9144 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -1653,6 +1653,12 @@ SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, NSView *nsview, 
         SDL_SetKeyboardFocus(data.window);
     }
 
+    /* SDL_WindowData will be holding a strong reference to the NSWindow, and
+     * it will also call [NSWindow close] in DestroyWindow before releasing the
+     * NSWindow, so the extra release provided by releasedWhenClosed isn't
+     * necessary. */
+    nswindow.releasedWhenClosed = NO;
+
     /* Prevents the window's "window device" from being destroyed when it is
      * hidden. See http://www.mikeash.com/pyblog/nsopenglcontext-and-one-shot.html
      */