Skip to content

Commit

Permalink
Properly handle toggling fullscreen state when another fullscreen sta…
Browse files Browse the repository at this point in the history
…te change is in progress.
  • Loading branch information
slouken committed Nov 12, 2013
1 parent 819148a commit cb31a80
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 46 deletions.
9 changes: 8 additions & 1 deletion src/video/cocoa/SDL_cocoawindow.h
Expand Up @@ -34,12 +34,19 @@ typedef struct SDL_WindowData SDL_WindowData;
BOOL wasVisible;
BOOL isFullscreen;
BOOL inFullscreenTransition;

enum
{
PENDING_TRANSITION_NONE,
PENDING_TRANSITION_ENTER_FULLSCREEN,
PENDING_TRANSITION_LEAVE_FULLSCREEN
} pendingFullscreenTransition;
}

-(void) listen:(SDL_WindowData *) data;
-(void) pauseVisibleObservation;
-(void) resumeVisibleObservation;
-(BOOL) isToggledFullscreen;
-(BOOL) setFullscreenState:(BOOL) state;
-(void) close;

/* Window delegate functionality */
Expand Down
109 changes: 64 additions & 45 deletions src/video/cocoa/SDL_cocoawindow.m
Expand Up @@ -103,6 +103,7 @@ - (void)listen:(SDL_WindowData *)data
wasVisible = [window isVisible];
isFullscreen = NO;
inFullscreenTransition = NO;
pendingFullscreenTransition = PENDING_TRANSITION_NONE;

center = [NSNotificationCenter defaultCenter];

Expand Down Expand Up @@ -183,9 +184,52 @@ -(void) resumeVisibleObservation
}
}

- (BOOL) isToggledFullscreen
-(BOOL) canSetFullscreenState:(BOOL) state;
{
return isFullscreen;
}

-(BOOL) setFullscreenState:(BOOL) state;
{
SDL_Window *window = _data->window;
NSWindow *nswindow = _data->nswindow;
BOOL canSetState = NO;

/* Make sure we can support this fullscreen style */
if (![nswindow respondsToSelector: @selector(toggleFullScreen:)]) {
return NO;
}

pendingFullscreenTransition = PENDING_TRANSITION_NONE;

/* We can enter new style fullscreen mode for "fullscreen desktop" */
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
canSetState = YES;
}

/* We can always leave new style fullscreen mode */
if (!state && isFullscreen) {
canSetState = YES;
}

if (!canSetState) {
return NO;
}

if (state == isFullscreen) {
return YES;
}

if (inFullscreenTransition) {
if (state) {
pendingFullscreenTransition = PENDING_TRANSITION_ENTER_FULLSCREEN;
} else {
pendingFullscreenTransition = PENDING_TRANSITION_LEAVE_FULLSCREEN;
}
return YES;
}

[nswindow performSelector: @selector(toggleFullScreen:) withObject:nswindow];
return YES;
}

- (void)close
Expand Down Expand Up @@ -215,8 +259,7 @@ - (void)close
[window setDelegate:nil];
}

[window removeObserver:self
forKeyPath:@"visible"];
[window removeObserver:self forKeyPath:@"visible"];

if ([window nextResponder] == self) {
[window setNextResponder:nil];
Expand Down Expand Up @@ -385,11 +428,18 @@ - (void)windowWillEnterFullScreen:(NSNotification *)aNotification
- (void)windowDidEnterFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = NO;
[self windowDidResize:aNotification];

if (pendingFullscreenTransition != PENDING_TRANSITION_NONE) {
pendingFullscreenTransition = PENDING_TRANSITION_NONE;
[self setFullscreenState:NO];
} else {
[self windowDidResize:aNotification];
}
}

- (void)windowWillExitFullScreen:(NSNotification *)aNotification
{
isFullscreen = NO;
inFullscreenTransition = YES;
}

Expand All @@ -401,9 +451,14 @@ - (void)windowDidExitFullScreen:(NSNotification *)aNotification
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
[nswindow setStyleMask:GetWindowStyle(window)];
}
isFullscreen = NO;
inFullscreenTransition = NO;
[self windowDidResize:aNotification];

if (pendingFullscreenTransition != PENDING_TRANSITION_NONE) {
pendingFullscreenTransition = PENDING_TRANSITION_NONE;
[self setFullscreenState:YES];
} else {
[self windowDidResize:aNotification];
}
}

/* We'll respond to key events by doing nothing so we don't beep.
Expand Down Expand Up @@ -1094,41 +1149,6 @@ - (void)resetCursorRects
[pool release];
}

static SDL_bool
Cocoa_CanToggleFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = data->nswindow;

if (![nswindow respondsToSelector: @selector(toggleFullScreen:)]) {
return SDL_FALSE;
}

/* We can enter new style fullscreen mode for "fullscreen desktop" */
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
return SDL_TRUE;
}

/* We can always leave new style fullscreen mode */
if (!fullscreen && [data->listener isToggledFullscreen]) {
return SDL_TRUE;
}

/* Requesting a mode switched fullscreen mode */
return SDL_FALSE;
}

static void
Cocoa_SetWindowFullscreen_NewStyle(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = data->nswindow;

if (fullscreen != [data->listener isToggledFullscreen]) {
[nswindow performSelector: @selector(toggleFullScreen:) withObject:nswindow];
}
ScheduleContextUpdates(data);
}

static void
Cocoa_SetWindowFullscreen_OldStyle(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
Expand Down Expand Up @@ -1212,10 +1232,9 @@ - (void)resetCursorRects
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;

if (Cocoa_CanToggleFullscreen(_this, window, display, fullscreen)) {
Cocoa_SetWindowFullscreen_NewStyle(_this, window, display, fullscreen);
} else {
if (![data->listener setFullscreenState:(fullscreen ? YES : NO)]) {
Cocoa_SetWindowFullscreen_OldStyle(_this, window, display, fullscreen);
}

Expand Down

0 comments on commit cb31a80

Please sign in to comment.