Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ligfx committed Mar 25, 2020
1 parent 8641f6e commit 361417c
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 33 deletions.
13 changes: 1 addition & 12 deletions src/video/cocoa/SDL_cocoaopengl.m
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions src/video/cocoa/SDL_cocoashape.m
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/video/cocoa/SDL_cocoawindow.h
Expand Up @@ -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;
Expand Down
44 changes: 26 additions & 18 deletions src/video/cocoa/SDL_cocoawindow.m
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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];
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 */
Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 361417c

Please sign in to comment.