Properly handle toggling fullscreen state when another fullscreen state change is in progress.

This commit is contained in:
Sam Lantinga 2013-11-11 20:42:59 -08:00
parent 819148a844
commit cb31a80d82
2 changed files with 72 additions and 46 deletions

View File

@ -34,12 +34,19 @@ typedef struct SDL_WindowData SDL_WindowData;
BOOL wasVisible; BOOL wasVisible;
BOOL isFullscreen; BOOL isFullscreen;
BOOL inFullscreenTransition; BOOL inFullscreenTransition;
enum
{
PENDING_TRANSITION_NONE,
PENDING_TRANSITION_ENTER_FULLSCREEN,
PENDING_TRANSITION_LEAVE_FULLSCREEN
} pendingFullscreenTransition;
} }
-(void) listen:(SDL_WindowData *) data; -(void) listen:(SDL_WindowData *) data;
-(void) pauseVisibleObservation; -(void) pauseVisibleObservation;
-(void) resumeVisibleObservation; -(void) resumeVisibleObservation;
-(BOOL) isToggledFullscreen; -(BOOL) setFullscreenState:(BOOL) state;
-(void) close; -(void) close;
/* Window delegate functionality */ /* Window delegate functionality */

View File

@ -103,6 +103,7 @@ GetWindowStyle(SDL_Window * window)
wasVisible = [window isVisible]; wasVisible = [window isVisible];
isFullscreen = NO; isFullscreen = NO;
inFullscreenTransition = NO; inFullscreenTransition = NO;
pendingFullscreenTransition = PENDING_TRANSITION_NONE;
center = [NSNotificationCenter defaultCenter]; center = [NSNotificationCenter defaultCenter];
@ -183,9 +184,52 @@ GetWindowStyle(SDL_Window * window)
} }
} }
- (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 - (void)close
@ -215,8 +259,7 @@ GetWindowStyle(SDL_Window * window)
[window setDelegate:nil]; [window setDelegate:nil];
} }
[window removeObserver:self [window removeObserver:self forKeyPath:@"visible"];
forKeyPath:@"visible"];
if ([window nextResponder] == self) { if ([window nextResponder] == self) {
[window setNextResponder:nil]; [window setNextResponder:nil];
@ -385,11 +428,18 @@ GetWindowStyle(SDL_Window * window)
- (void)windowDidEnterFullScreen:(NSNotification *)aNotification - (void)windowDidEnterFullScreen:(NSNotification *)aNotification
{ {
inFullscreenTransition = NO; inFullscreenTransition = NO;
if (pendingFullscreenTransition != PENDING_TRANSITION_NONE) {
pendingFullscreenTransition = PENDING_TRANSITION_NONE;
[self setFullscreenState:NO];
} else {
[self windowDidResize:aNotification]; [self windowDidResize:aNotification];
} }
}
- (void)windowWillExitFullScreen:(NSNotification *)aNotification - (void)windowWillExitFullScreen:(NSNotification *)aNotification
{ {
isFullscreen = NO;
inFullscreenTransition = YES; inFullscreenTransition = YES;
} }
@ -401,10 +451,15 @@ GetWindowStyle(SDL_Window * window)
if (!(window->flags & SDL_WINDOW_RESIZABLE)) { if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
[nswindow setStyleMask:GetWindowStyle(window)]; [nswindow setStyleMask:GetWindowStyle(window)];
} }
isFullscreen = NO;
inFullscreenTransition = NO; inFullscreenTransition = NO;
if (pendingFullscreenTransition != PENDING_TRANSITION_NONE) {
pendingFullscreenTransition = PENDING_TRANSITION_NONE;
[self setFullscreenState:YES];
} else {
[self windowDidResize:aNotification]; [self windowDidResize:aNotification];
} }
}
/* We'll respond to key events by doing nothing so we don't beep. /* We'll respond to key events by doing nothing so we don't beep.
* We could handle key messages here, but we lose some in the NSApp dispatch, * We could handle key messages here, but we lose some in the NSApp dispatch,
@ -1094,41 +1149,6 @@ Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
[pool release]; [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 static void
Cocoa_SetWindowFullscreen_OldStyle(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) Cocoa_SetWindowFullscreen_OldStyle(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
@ -1212,10 +1232,9 @@ void
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{ {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (Cocoa_CanToggleFullscreen(_this, window, display, fullscreen)) { if (![data->listener setFullscreenState:(fullscreen ? YES : NO)]) {
Cocoa_SetWindowFullscreen_NewStyle(_this, window, display, fullscreen);
} else {
Cocoa_SetWindowFullscreen_OldStyle(_this, window, display, fullscreen); Cocoa_SetWindowFullscreen_OldStyle(_this, window, display, fullscreen);
} }