Reworked fullscreen policy on Mac OS X.
authorRyan C. Gordon <icculus@icculus.org>
Sun, 02 Mar 2014 12:45:51 -0500
changeset 8284a2910aa6c056
parent 8283 176891c01b3c
child 8285 a6493ee0c9b5
Reworked fullscreen policy on Mac OS X.

- SDL_WINDOW_FULLSCREEN works as always (change resolution, lock to window).
- SDL_WINDOW_FULLSCREEN_DESKTOP now puts the window in its own Space, and
hides the menu bar, but you can slide between Spaces and Command-Tab between
apps without the window minimizing, etc.
- SDL_WINDOW_RESIZABLE windows will get the new 10.7+ "toggle fullscreen"
window decoration and menubar item. As far as the app is concerned, this is
no different than resizing a window, but it gives the end-user more power.
- The hint for putting fullscreen windows into the Spaces system is gone,
since Spaces can't enforce the requested resolution. It's a perfect match
for FULLSCREEN_DESKTOP, though, so this is all automated now.
include/SDL_hints.h
src/video/cocoa/SDL_cocoawindow.m
     1.1 --- a/include/SDL_hints.h	Sun Mar 02 02:00:40 2014 -0500
     1.2 +++ b/include/SDL_hints.h	Sun Mar 02 12:45:51 2014 -0500
     1.3 @@ -201,17 +201,6 @@
     1.4  #define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS   "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"
     1.5  
     1.6  /**
     1.7 - *  \brief Set whether windows go fullscreen in their own spaces on Mac OS X
     1.8 - *
     1.9 - *  This variable can be set to the following values:
    1.10 - *    "0"       - Fullscreen windows will use the classic fullscreen mode
    1.11 - *    "1"       - Fullscreen windows will use fullscreen spaces
    1.12 - *
    1.13 - *  By default SDL will use the classic fullscreen mode.
    1.14 - */
    1.15 -#define SDL_HINT_VIDEO_FULLSCREEN_SPACES   "SDL_VIDEO_FULLSCREEN_SPACES"
    1.16 -
    1.17 -/**
    1.18   *  \brief  A variable controlling whether the idle timer is disabled on iOS.
    1.19   *
    1.20   *  When an iOS app does not receive touches for some time, the screen is
     2.1 --- a/src/video/cocoa/SDL_cocoawindow.m	Sun Mar 02 02:00:40 2014 -0500
     2.2 +++ b/src/video/cocoa/SDL_cocoawindow.m	Sun Mar 02 12:45:51 2014 -0500
     2.3 @@ -121,7 +121,9 @@
     2.4  {
     2.5      unsigned int style;
     2.6  
     2.7 -    if (window->flags & SDL_WINDOW_FULLSCREEN) {
     2.8 +    if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
     2.9 +        style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
    2.10 +    } else if (window->flags & SDL_WINDOW_FULLSCREEN) {
    2.11          style = NSBorderlessWindowMask;
    2.12      } else {
    2.13          if (window->flags & SDL_WINDOW_BORDERLESS) {
    2.14 @@ -256,20 +258,17 @@
    2.15      }
    2.16  }
    2.17  
    2.18 --(BOOL) setFullscreenSpace:(BOOL) state;
    2.19 +-(BOOL) setFullscreenSpace:(BOOL) state
    2.20  {
    2.21      SDL_Window *window = _data->window;
    2.22      NSWindow *nswindow = _data->nswindow;
    2.23  
    2.24 -    if (![nswindow respondsToSelector: @selector(collectionBehavior)]) {
    2.25 -        return NO;
    2.26 -    }
    2.27 -    if ([nswindow collectionBehavior] != NSWindowCollectionBehaviorFullScreenPrimary) {
    2.28 -        return NO;
    2.29 -    }
    2.30 -
    2.31 -    if (state == isFullscreenSpace) {
    2.32 -        return YES;
    2.33 +    if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
    2.34 +        return NO;  /* we only allow this on FULLSCREEN_DESKTOP windows. */
    2.35 +    } else if (![nswindow respondsToSelector: @selector(setCollectionBehavior:)]) {
    2.36 +        return NO;  /* No Spaces support? Older Mac OS X? */
    2.37 +    } else if (state == isFullscreenSpace) {
    2.38 +        return YES;  /* already there. */
    2.39      }
    2.40  
    2.41      if (inFullscreenTransition) {
    2.42 @@ -282,13 +281,8 @@
    2.43      }
    2.44      inFullscreenTransition = YES;
    2.45  
    2.46 -    /* Update the flags here so the state change is available immediately */
    2.47 -    if (state) {
    2.48 -        window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
    2.49 -    } else {
    2.50 -        window->flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP;
    2.51 -    }
    2.52 -
    2.53 +    /* you need to be FullScreenPrimary, or toggleFullScreen doesn't work. Unset it again in windowDid[Enter|Exit]FullScreen. */
    2.54 +    [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
    2.55      [nswindow performSelectorOnMainThread: @selector(toggleFullScreen:) withObject:nswindow waitUntilDone:NO];
    2.56      return YES;
    2.57  }
    2.58 @@ -443,6 +437,11 @@
    2.59  
    2.60  - (void)windowDidResize:(NSNotification *)aNotification
    2.61  {
    2.62 +    if (inFullscreenTransition) {
    2.63 +        /* We'll take care of this at the end of the transition */
    2.64 +        return;
    2.65 +    }
    2.66 +
    2.67      SDL_Window *window = _data->window;
    2.68      NSWindow *nswindow = _data->nswindow;
    2.69      int x, y, w, h;
    2.70 @@ -453,11 +452,6 @@
    2.71      w = (int)rect.size.width;
    2.72      h = (int)rect.size.height;
    2.73  
    2.74 -    if (inFullscreenTransition) {
    2.75 -        /* We'll take care of this at the end of the transition */
    2.76 -        return;
    2.77 -    }
    2.78 -
    2.79      if (SDL_IsShapedWindow(window)) {
    2.80          Cocoa_ResizeWindowShape(window);
    2.81      }
    2.82 @@ -538,7 +532,6 @@
    2.83  {
    2.84      SDL_Window *window = _data->window;
    2.85  
    2.86 -    window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
    2.87      SetWindowStyle(window, (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask));
    2.88  
    2.89      isFullscreenSpace = YES;
    2.90 @@ -548,6 +541,7 @@
    2.91  - (void)windowDidEnterFullScreen:(NSNotification *)aNotification
    2.92  {
    2.93      SDL_Window *window = _data->window;
    2.94 +    NSWindow *nswindow = _data->nswindow;
    2.95  
    2.96      inFullscreenTransition = NO;
    2.97  
    2.98 @@ -555,6 +549,12 @@
    2.99          pendingWindowOperation = PENDING_OPERATION_NONE;
   2.100          [self setFullscreenSpace:NO];
   2.101      } else {
   2.102 +        if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
   2.103 +            /* Remove the fullscreen toggle button and menu now that we're here. */
   2.104 +            [nswindow setCollectionBehavior:NSWindowCollectionBehaviorManaged];
   2.105 +            [NSMenu setMenuBarVisible:NO];
   2.106 +        }
   2.107 +
   2.108          pendingWindowOperation = PENDING_OPERATION_NONE;
   2.109          /* Force the size change event in case it was delivered earlier
   2.110             while the window was still animating into place.
   2.111 @@ -569,7 +569,6 @@
   2.112  {
   2.113      SDL_Window *window = _data->window;
   2.114  
   2.115 -    window->flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP;
   2.116      SetWindowStyle(window, GetWindowStyle(window));
   2.117  
   2.118      isFullscreenSpace = NO;
   2.119 @@ -590,6 +589,12 @@
   2.120          pendingWindowOperation = PENDING_OPERATION_NONE;
   2.121          [nswindow miniaturize:nil];
   2.122      } else {
   2.123 +        if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
   2.124 +            /* Remove the fullscreen toggle button and readd menu now that we're here. */
   2.125 +            [nswindow setCollectionBehavior:NSWindowCollectionBehaviorManaged];
   2.126 +            [NSMenu setMenuBarVisible:YES];
   2.127 +        }
   2.128 +
   2.129          pendingWindowOperation = PENDING_OPERATION_NONE;
   2.130          /* Force the size change event in case it was delivered earlier
   2.131             while the window was still animating into place.
   2.132 @@ -1007,9 +1012,11 @@
   2.133          return -1;
   2.134      }
   2.135      [nswindow setBackgroundColor:[NSColor blackColor]];
   2.136 -    if ([nswindow respondsToSelector:@selector(setCollectionBehavior:)]) {
   2.137 -        const char *hint = SDL_GetHint(SDL_HINT_VIDEO_FULLSCREEN_SPACES);
   2.138 -        if (hint && SDL_atoi(hint) > 0) {
   2.139 +
   2.140 +    if ([nswindow respondsToSelector: @selector(setCollectionBehavior:)]) {
   2.141 +        /* we put FULLSCREEN_DESKTOP windows in their own Space, without a toggle button or menubar, later */
   2.142 +        if (window->flags & SDL_WINDOW_RESIZABLE) {
   2.143 +            /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */
   2.144              [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
   2.145          }
   2.146      }