From 361417c0a4695bab3403e9c381ebaa6183633438 Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Wed, 25 Mar 2020 16:40:43 -0700 Subject: [PATCH] cocoa: allow calling CreateWindowFrom on an NSView This lets applications embed SDL with other widgets surrounding it. Already possible on Windows and X11. Fixes Bugzilla #5060. --- src/video/cocoa/SDL_cocoaopengl.m | 13 +-------- src/video/cocoa/SDL_cocoashape.m | 4 +-- src/video/cocoa/SDL_cocoawindow.h | 2 +- src/video/cocoa/SDL_cocoawindow.m | 44 ++++++++++++++++++------------- 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m index 257f1a5c599b0..6fb471139f937 100644 --- a/src/video/cocoa/SDL_cocoaopengl.m +++ b/src/video/cocoa/SDL_cocoaopengl.m @@ -97,17 +97,6 @@ - (void)setWindow:(SDL_Window *)newWindow SDL_WindowData *windowdata = (SDL_WindowData *)newWindow->driverdata; NSView *contentview = windowdata->sdlContentView; - /* This should never be nil since sdlContentView is only nil if the - window was created via SDL_CreateWindowFrom, and SDL doesn't allow - OpenGL contexts to be created in that case. However, it doesn't hurt - to check. */ - if (contentview == nil) { - /* Prefer to access the cached content view above instead of this, - since as of Xcode 11 + SDK 10.15, [window contentView] causes - Apple's Main Thread Checker to output a warning. */ - contentview = [windowdata->nswindow contentView]; - } - /* Now sign up for scheduled updates for the new window. */ NSMutableArray *contexts = windowdata->nscontexts; @synchronized (contexts) { @@ -382,7 +371,7 @@ - (void)explicitUpdate Cocoa_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) { SDL_WindowData *windata = (SDL_WindowData *) window->driverdata; - NSView *contentView = [windata->nswindow contentView]; + NSView *contentView = windata->sdlContentView; NSRect viewport = [contentView bounds]; if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { diff --git a/src/video/cocoa/SDL_cocoashape.m b/src/video/cocoa/SDL_cocoashape.m index 8a43c1127dfae..e889835a993c3 100644 --- a/src/video/cocoa/SDL_cocoashape.m +++ b/src/video/cocoa/SDL_cocoashape.m @@ -88,10 +88,10 @@ [NSGraphicsContext setCurrentContext:data->context]; [[NSColor clearColor] set]; - NSRectFill([[windata->nswindow contentView] frame]); + NSRectFill([windata->sdlContentView frame]); data->shape = SDL_CalculateShapeTree(*shape_mode,shape); - closure.view = [windata->nswindow contentView]; + closure.view = windata->sdlContentView; closure.path = [NSBezierPath bezierPath]; closure.window = shaper->window; SDL_TraverseShapeTree(data->shape,&ConvertRects,&closure); diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index 049d00f30baab..4c0570fdf9825 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -113,7 +113,7 @@ struct SDL_WindowData { SDL_Window *window; NSWindow *nswindow; - NSView *sdlContentView; /* nil if window is created via CreateWindowFrom */ + NSView *sdlContentView; NSMutableArray *nscontexts; SDL_bool created; SDL_bool inWindowFullscreenTransition; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 297fef09e13e1..bde2ed88a5bc6 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -297,15 +297,15 @@ static void ConvertNSRect(NSScreen *screen, BOOL fullscreen, NSRect *r) NSWindow *nswindow = data->nswindow; /* The view responder chain gets messed with during setStyleMask */ - if ([[nswindow contentView] nextResponder] == data->listener) { - [[nswindow contentView] setNextResponder:nil]; + if ([data->sdlContentView nextResponder] == data->listener) { + [data->sdlContentView setNextResponder:nil]; } [nswindow setStyleMask:style]; /* The view responder chain gets messed with during setStyleMask */ - if ([[nswindow contentView] nextResponder] != data->listener) { - [[nswindow contentView] setNextResponder:data->listener]; + if ([data->sdlContentView nextResponder] != data->listener) { + [data->sdlContentView setNextResponder:data->listener]; } return SDL_TRUE; @@ -318,7 +318,7 @@ - (void)listen:(SDL_WindowData *)data { NSNotificationCenter *center; NSWindow *window = data->nswindow; - NSView *view = [window contentView]; + NSView *view = data->nsview; _data = data; observingVisible = YES; @@ -1360,7 +1360,7 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent @end static int -SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created) +SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, NSView *nsview, SDL_bool created) { @autoreleasepool { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; @@ -1376,11 +1376,7 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent data->created = created; data->videodata = videodata; data->nscontexts = [[NSMutableArray alloc] init]; - - /* Only store this for windows created by us since the content view might - * get replaced from under us otherwise, and we only need it when the - * window is guaranteed to be created by us (OpenGL contexts). */ - data->sdlContentView = created ? [nswindow contentView] : nil; + data->sdlContentView = nsview; /* Create an event listener for the window */ data->listener = [[Cocoa_WindowListener alloc] init]; @@ -1541,7 +1537,7 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent [nswindow setContentView:contentView]; [contentView release]; - if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) { + if (SetupWindowData(_this, window, nswindow, contentView, SDL_TRUE) < 0) { [nswindow release]; return -1; } @@ -1571,7 +1567,19 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) { @autoreleasepool { - NSWindow *nswindow = (NSWindow *) data; + NSView* nsview; + NSWindow *nswindow; + + if ([(id)data isKindOfClass:[NSWindow class]]) { + nswindow = (NSWindow*)data; + nsview = [nswindow contentView]; + } else if ([(id)data isKindOfClass:[NSView class]]) { + nsview = (NSView*)data; + nswindow = [nsview window]; + } else { + SDL_assert(false); + } + NSString *title; /* Query the title from the existing window */ @@ -1580,7 +1588,7 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent window->title = SDL_strdup([title UTF8String]); } - return SetupWindowData(_this, window, nswindow, SDL_FALSE); + return SetupWindowData(_this, window, nswindow, nsview, SDL_FALSE); }} void @@ -1795,8 +1803,8 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent NSRect rect; /* The view responder chain gets messed with during setStyleMask */ - if ([[nswindow contentView] nextResponder] == data->listener) { - [[nswindow contentView] setNextResponder:nil]; + if ([data->sdlContentView nextResponder] == data->listener) { + [data->sdlContentView setNextResponder:nil]; } if (fullscreen) { @@ -1852,8 +1860,8 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent } /* The view responder chain gets messed with during setStyleMask */ - if ([[nswindow contentView] nextResponder] != data->listener) { - [[nswindow contentView] setNextResponder:data->listener]; + if ([data->sdlContentView nextResponder] != data->listener) { + [data->sdlContentView setNextResponder:data->listener]; } s_moveHack = 0;