Skip to content

Commit

Permalink
Added support for new style fullscreen transitions on Mac OS X
Browse files Browse the repository at this point in the history
  • Loading branch information
slouken committed Nov 11, 2013
1 parent 2b93fa0 commit 4c1322f
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 26 deletions.
20 changes: 20 additions & 0 deletions src/video/cocoa/SDL_cocoaevents.m
Expand Up @@ -147,6 +147,7 @@ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filenam
NSMenu *appleMenu;
NSMenu *serviceMenu;
NSMenu *windowMenu;
NSMenu *viewMenu;
NSMenuItem *menuItem;

if (NSApp == nil) {
Expand Down Expand Up @@ -220,6 +221,25 @@ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filenam
/* Tell the application object that this is now the window menu */
[NSApp setWindowsMenu:windowMenu];
[windowMenu release];


/* Add the fullscreen view toggle menu option, if supported */
if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) {
/* Create the view menu */
viewMenu = [[NSMenu alloc] initWithTitle:@"View"];

/* Add menu items */
menuItem = [viewMenu addItemWithTitle:@"Toggle Full Screen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"];
[menuItem setKeyEquivalentModifierMask:NSControlKeyMask | NSCommandKeyMask];

/* Put menu into the menubar */
menuItem = [[NSMenuItem alloc] initWithTitle:@"View" action:nil keyEquivalent:@""];
[menuItem setSubmenu:viewMenu];
[[NSApp mainMenu] addItem:menuItem];
[menuItem release];

[viewMenu release];
}
}

void
Expand Down
7 changes: 7 additions & 0 deletions src/video/cocoa/SDL_cocoawindow.h
Expand Up @@ -32,11 +32,14 @@ typedef struct SDL_WindowData SDL_WindowData;
BOOL observingVisible;
BOOL wasCtrlLeft;
BOOL wasVisible;
BOOL isFullscreen;
BOOL inFullscreenTransition;
}

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

/* Window delegate functionality */
Expand All @@ -48,6 +51,10 @@ typedef struct SDL_WindowData SDL_WindowData;
-(void) windowDidDeminiaturize:(NSNotification *) aNotification;
-(void) windowDidBecomeKey:(NSNotification *) aNotification;
-(void) windowDidResignKey:(NSNotification *) aNotification;
-(void) windowWillEnterFullScreen:(NSNotification *) aNotification;
-(void) windowDidEnterFullScreen:(NSNotification *) aNotification;
-(void) windowWillExitFullScreen:(NSNotification *) aNotification;
-(void) windowDidExitFullScreen:(NSNotification *) aNotification;

/* Window event handling */
-(void) mouseDown:(NSEvent *) theEvent;
Expand Down
165 changes: 139 additions & 26 deletions src/video/cocoa/SDL_cocoawindow.m
Expand Up @@ -50,7 +50,8 @@ static void ConvertNSRect(NSRect *r)
r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
}

static void ScheduleContextUpdates(SDL_WindowData *data)
static void
ScheduleContextUpdates(SDL_WindowData *data)
{
NSMutableArray *contexts = data->nscontexts;
@synchronized (contexts) {
Expand All @@ -60,12 +61,34 @@ static void ScheduleContextUpdates(SDL_WindowData *data)
}
}

static int GetHintCtrlClickEmulateRightClick()
static int
GetHintCtrlClickEmulateRightClick()
{
const char *hint = SDL_GetHint( SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK );
return hint != NULL && *hint != '0';
}

static unsigned int
GetWindowStyle(SDL_Window * window)
{
unsigned int style;

if (window->flags & SDL_WINDOW_FULLSCREEN) {
style = NSBorderlessWindowMask;
} else {
if (window->flags & SDL_WINDOW_BORDERLESS) {
style = NSBorderlessWindowMask;
} else {
style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
}
if (window->flags & SDL_WINDOW_RESIZABLE) {
style |= NSResizableWindowMask;
}
}
return style;
}


@implementation Cocoa_WindowListener

- (void)listen:(SDL_WindowData *)data
Expand All @@ -78,6 +101,8 @@ - (void)listen:(SDL_WindowData *)data
observingVisible = YES;
wasCtrlLeft = NO;
wasVisible = [window isVisible];
isFullscreen = NO;
inFullscreenTransition = NO;

center = [NSNotificationCenter defaultCenter];

Expand All @@ -89,6 +114,10 @@ - (void)listen:(SDL_WindowData *)data
[center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:window];
[center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:window];
[center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:window];
[center addObserver:self selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:window];
[center addObserver:self selector:@selector(windowDidEnterFullScreen:) name:NSWindowDidEnterFullScreenNotification object:window];
[center addObserver:self selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:window];
[center addObserver:self selector:@selector(windowDidExitFullScreen:) name:NSWindowDidExitFullScreenNotification object:window];
} else {
[window setDelegate:self];
}
Expand Down Expand Up @@ -152,6 +181,11 @@ -(void) resumeVisibleObservation
}
}

- (BOOL) isToggledFullscreen
{
return isFullscreen;
}

- (void)close
{
NSNotificationCenter *center;
Expand All @@ -169,6 +203,10 @@ - (void)close
[center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:window];
[center removeObserver:self name:NSWindowDidBecomeKeyNotification object:window];
[center removeObserver:self name:NSWindowDidResignKeyNotification object:window];
[center removeObserver:self name:NSWindowWillEnterFullScreenNotification object:window];
[center removeObserver:self name:NSWindowDidEnterFullScreenNotification object:window];
[center removeObserver:self name:NSWindowWillExitFullScreenNotification object:window];
[center removeObserver:self name:NSWindowDidExitFullScreenNotification object:window];
} else {
[window setDelegate:nil];
}
Expand Down Expand Up @@ -250,8 +288,15 @@ - (void)windowDidResize:(NSNotification *)aNotification
y = (int)rect.origin.y;
w = (int)rect.size.width;
h = (int)rect.size.height;
if (SDL_IsShapedWindow(_data->window))

if (inFullscreenTransition) {
/* We'll take care of this at the end of the transition */
return;
}

if (SDL_IsShapedWindow(_data->window)) {
Cocoa_ResizeWindowShape(_data->window);
}

ScheduleContextUpdates(_data);

Expand Down Expand Up @@ -317,6 +362,46 @@ - (void)windowDidResignKey:(NSNotification *)aNotification
}
}

- (void)windowWillEnterFullScreen:(NSNotification *)aNotification
{
SDL_Window *window = _data->window;
NSWindow *nswindow = _data->nswindow;

if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
[nswindow setStyleMask:(NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask)];
} else {
[nswindow setStyleMask:NSBorderlessWindowMask];
}
}
isFullscreen = YES;
inFullscreenTransition = YES;
}

- (void)windowDidEnterFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = NO;
[self windowDidResize:aNotification];
}

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

- (void)windowDidExitFullScreen:(NSNotification *)aNotification
{
SDL_Window *window = _data->window;
NSWindow *nswindow = _data->nswindow;

if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
[nswindow setStyleMask:GetWindowStyle(window)];
}
isFullscreen = NO;
inFullscreenTransition = NO;
[self windowDidResize:aNotification];
}

/* 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,
* where they get converted to action messages, etc.
Expand Down Expand Up @@ -606,26 +691,6 @@ - (void)resetCursorRects
}
@end

static unsigned int
GetWindowStyle(SDL_Window * window)
{
unsigned int style;

if (window->flags & SDL_WINDOW_FULLSCREEN) {
style = NSBorderlessWindowMask;
} else {
if (window->flags & SDL_WINDOW_BORDERLESS) {
style = NSBorderlessWindowMask;
} else {
style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
}
if (window->flags & SDL_WINDOW_RESIZABLE) {
style |= NSResizableWindowMask;
}
}
return style;
}

static int
SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
{
Expand Down Expand Up @@ -758,6 +823,7 @@ - (void)resetCursorRects
return -1;
}
[nswindow setBackgroundColor:[NSColor blackColor]];
[nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];

/* Create a default view for this window */
rect = [nswindow contentRectForFrameRect:[nswindow frame]];
Expand Down Expand Up @@ -1020,10 +1086,45 @@ - (void)resetCursorRects
[pool release];
}

void
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
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 toggleFullScreen:nil];
}
ScheduleContextUpdates(data);
}

static void
Cocoa_SetWindowFullscreen_OldStyle(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = data->nswindow;
NSRect rect;
Expand Down Expand Up @@ -1097,6 +1198,18 @@ - (void)resetCursorRects
}

ScheduleContextUpdates(data);
}

void
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

if (Cocoa_CanToggleFullscreen(_this, window, display, fullscreen)) {
Cocoa_SetWindowFullscreen_NewStyle(_this, window, display, fullscreen);
} else {
Cocoa_SetWindowFullscreen_OldStyle(_this, window, display, fullscreen);
}

[pool release];
}
Expand Down

0 comments on commit 4c1322f

Please sign in to comment.