src/video/cocoa/SDL_cocoamodes.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 08 Feb 2013 00:54:08 -0800
changeset 6836 b0ca1571caf3
parent 6809 54cca01b6006
child 6885 700f1b25f77f
permissions -rw-r--r--
Fixed bug 1689 - Leaks galore in OS X Cocoa code.

Edward Rudd

This is to document the various leaks I'm finding in the Cocoa code in SDL 2.
slouken@1931
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@1931
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1931
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1931
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1931
    20
*/
slouken@1931
    21
#include "SDL_config.h"
slouken@1931
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_COCOA
slouken@6044
    24
slouken@1931
    25
#include "SDL_cocoavideo.h"
slouken@1931
    26
slouken@6787
    27
/* We need this for IODisplayCreateInfoDictionary and kIODisplayOnlyPreferredName */
slouken@6787
    28
#include <IOKit/graphics/IOGraphicsLib.h>
slouken@6787
    29
icculus@6104
    30
/* we need this for ShowMenuBar() and HideMenuBar(). */
icculus@6104
    31
#include <Carbon/Carbon.h>
aschiffler@6101
    32
icculus@6105
    33
static inline void Cocoa_ToggleMenuBar(const BOOL show)
icculus@6105
    34
{
icculus@6105
    35
    /* !!! FIXME: keep an eye on this.
icculus@6105
    36
     * ShowMenuBar/HideMenuBar is officially unavailable for 64-bit binaries.
icculus@6105
    37
     *  It happens to work, as of 10.7, but we're going to see if
icculus@6105
    38
     *  we can just simply do without it on newer OSes...
icculus@6105
    39
     */
icculus@6105
    40
#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
icculus@6105
    41
    if (show)
icculus@6105
    42
        ShowMenuBar();
icculus@6105
    43
    else
icculus@6105
    44
        HideMenuBar();
icculus@6105
    45
#endif
icculus@6105
    46
}
icculus@6105
    47
icculus@6105
    48
icculus@5643
    49
/* !!! FIXME: clean out the pre-10.6 code when it makes sense to do so. */
icculus@5643
    50
#define FORCE_OLD_API 0 || (MAC_OS_X_VERSION_MAX_ALLOWED < 1060)
icculus@5643
    51
icculus@5643
    52
#if FORCE_OLD_API
icculus@5643
    53
#undef MAC_OS_X_VERSION_MIN_REQUIRED
icculus@5646
    54
#define MAC_OS_X_VERSION_MIN_REQUIRED 1050
icculus@5643
    55
#endif
icculus@5643
    56
icculus@5646
    57
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
slouken@1973
    58
/* 
slouken@1973
    59
    Add methods to get at private members of NSScreen. 
slouken@1973
    60
    Since there is a bug in Apple's screen switching code
slouken@1973
    61
    that does not update this variable when switching
slouken@1973
    62
    to fullscreen, we'll set it manually (but only for the
slouken@1973
    63
    main screen).
slouken@1973
    64
*/
slouken@1973
    65
@interface NSScreen (NSScreenAccess)
slouken@1973
    66
- (void) setFrame:(NSRect)frame;
slouken@1973
    67
@end
slouken@1973
    68
slouken@1973
    69
@implementation NSScreen (NSScreenAccess)
slouken@1973
    70
- (void) setFrame:(NSRect)frame;
slouken@1973
    71
{
slouken@1973
    72
    _frame = frame;
slouken@1973
    73
}
slouken@1973
    74
@end
slouken@3246
    75
#endif
slouken@1973
    76
icculus@5643
    77
static inline BOOL
icculus@5643
    78
IS_SNOW_LEOPARD_OR_LATER(_THIS)
icculus@5643
    79
{
icculus@5643
    80
#if FORCE_OLD_API
icculus@5643
    81
    return NO;
icculus@5643
    82
#else
icculus@5643
    83
    return ((((SDL_VideoData *) _this->driverdata))->osversion >= 0x1060);
icculus@5643
    84
#endif
icculus@5643
    85
}
icculus@5643
    86
slouken@1934
    87
static void
slouken@1934
    88
CG_SetError(const char *prefix, CGDisplayErr result)
slouken@1934
    89
{
slouken@1934
    90
    const char *error;
slouken@1934
    91
slouken@1934
    92
    switch (result) {
slouken@1934
    93
    case kCGErrorFailure:
slouken@1934
    94
        error = "kCGErrorFailure";
slouken@1934
    95
        break;
slouken@1934
    96
    case kCGErrorIllegalArgument:
slouken@1934
    97
        error = "kCGErrorIllegalArgument";
slouken@1934
    98
        break;
slouken@1934
    99
    case kCGErrorInvalidConnection:
slouken@1934
   100
        error = "kCGErrorInvalidConnection";
slouken@1934
   101
        break;
slouken@1934
   102
    case kCGErrorInvalidContext:
slouken@1934
   103
        error = "kCGErrorInvalidContext";
slouken@1934
   104
        break;
slouken@1934
   105
    case kCGErrorCannotComplete:
slouken@1934
   106
        error = "kCGErrorCannotComplete";
slouken@1934
   107
        break;
slouken@1934
   108
    case kCGErrorNotImplemented:
slouken@1934
   109
        error = "kCGErrorNotImplemented";
slouken@1934
   110
        break;
slouken@1934
   111
    case kCGErrorRangeCheck:
slouken@1934
   112
        error = "kCGErrorRangeCheck";
slouken@1934
   113
        break;
slouken@1934
   114
    case kCGErrorTypeCheck:
slouken@1934
   115
        error = "kCGErrorTypeCheck";
slouken@1934
   116
        break;
slouken@1934
   117
    case kCGErrorInvalidOperation:
slouken@1934
   118
        error = "kCGErrorInvalidOperation";
slouken@1934
   119
        break;
slouken@1934
   120
    case kCGErrorNoneAvailable:
slouken@1934
   121
        error = "kCGErrorNoneAvailable";
slouken@1934
   122
        break;
slouken@1934
   123
    default:
slouken@1934
   124
        error = "Unknown Error";
slouken@1934
   125
        break;
slouken@1934
   126
    }
slouken@1934
   127
    SDL_SetError("%s: %s", prefix, error);
slouken@1934
   128
}
slouken@1934
   129
slouken@1934
   130
static SDL_bool
icculus@5643
   131
GetDisplayMode(_THIS, const void *moderef, SDL_DisplayMode *mode)
slouken@1934
   132
{
slouken@1934
   133
    SDL_DisplayModeData *data;
icculus@6072
   134
    long width = 0;
icculus@6072
   135
    long height = 0;
icculus@6072
   136
    long bpp = 0;
icculus@6072
   137
    long refreshRate = 0;
slouken@1934
   138
slouken@1934
   139
    data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
slouken@1934
   140
    if (!data) {
slouken@1934
   141
        return SDL_FALSE;
slouken@1934
   142
    }
slouken@1934
   143
    data->moderef = moderef;
slouken@1934
   144
icculus@5646
   145
    #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
icculus@5643
   146
    if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   147
        CGDisplayModeRef vidmode = (CGDisplayModeRef) moderef;
icculus@5643
   148
        CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode);
icculus@5643
   149
        width = (long) CGDisplayModeGetWidth(vidmode);
icculus@5643
   150
        height = (long) CGDisplayModeGetHeight(vidmode);
icculus@5643
   151
        refreshRate = (long) CGDisplayModeGetRefreshRate(vidmode);
icculus@5643
   152
icculus@5643
   153
        if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
icculus@5643
   154
                            kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
icculus@5643
   155
            bpp = 32;
icculus@5643
   156
        } else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
icculus@5643
   157
                            kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
icculus@5643
   158
            bpp = 16;
icculus@5643
   159
        } else {
icculus@5643
   160
            bpp = 0;  /* ignore 8-bit and such for now. */
icculus@5643
   161
        }
icculus@5643
   162
icculus@5643
   163
        CFRelease(fmt);
icculus@5643
   164
    }
icculus@5643
   165
    #endif
icculus@5643
   166
icculus@5646
   167
    #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
icculus@5643
   168
    if (!IS_SNOW_LEOPARD_OR_LATER(_this)) {
slouken@6044
   169
        CFNumberRef number;
icculus@5643
   170
        CFDictionaryRef vidmode = (CFDictionaryRef) moderef;
icculus@5643
   171
        number = CFDictionaryGetValue(vidmode, kCGDisplayWidth);
icculus@5643
   172
        CFNumberGetValue(number, kCFNumberLongType, &width);
icculus@5643
   173
        number = CFDictionaryGetValue(vidmode, kCGDisplayHeight);
icculus@5643
   174
        CFNumberGetValue(number, kCFNumberLongType, &height);
icculus@5643
   175
        number = CFDictionaryGetValue(vidmode, kCGDisplayBitsPerPixel);
icculus@5643
   176
        CFNumberGetValue(number, kCFNumberLongType, &bpp);
icculus@5643
   177
        number = CFDictionaryGetValue(vidmode, kCGDisplayRefreshRate);
icculus@5643
   178
        CFNumberGetValue(number, kCFNumberLongType, &refreshRate);
icculus@5643
   179
    }
icculus@5643
   180
    #endif
slouken@1934
   181
slouken@1969
   182
    mode->format = SDL_PIXELFORMAT_UNKNOWN;
slouken@1934
   183
    switch (bpp) {
slouken@1934
   184
    case 16:
slouken@2237
   185
        mode->format = SDL_PIXELFORMAT_ARGB1555;
slouken@1934
   186
        break;
slouken@1934
   187
    case 32:
slouken@2237
   188
        mode->format = SDL_PIXELFORMAT_ARGB8888;
slouken@1934
   189
        break;
icculus@5643
   190
    case 8: /* We don't support palettized modes now */
icculus@5643
   191
    default: /* Totally unrecognizable bit depth. */
icculus@5643
   192
        return SDL_FALSE;
slouken@1934
   193
    }
slouken@1934
   194
    mode->w = width;
slouken@1934
   195
    mode->h = height;
slouken@1934
   196
    mode->refresh_rate = refreshRate;
slouken@1934
   197
    mode->driverdata = data;
slouken@1934
   198
    return SDL_TRUE;
slouken@1934
   199
}
slouken@1931
   200
icculus@5643
   201
static inline void
icculus@5643
   202
Cocoa_ReleaseDisplayMode(_THIS, const void *moderef)
icculus@5643
   203
{
icculus@5643
   204
    /* We don't own moderef unless we use the 10.6+ APIs. */
icculus@5646
   205
    #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
icculus@5643
   206
    if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   207
        CGDisplayModeRelease((CGDisplayModeRef) moderef);  /* NULL is ok */
icculus@5643
   208
    }
icculus@5643
   209
    #endif
icculus@5643
   210
}
icculus@5643
   211
icculus@5643
   212
static inline void
icculus@5643
   213
Cocoa_ReleaseDisplayModeList(_THIS, CFArrayRef modelist)
icculus@5643
   214
{
icculus@5643
   215
    /* We don't own modelis unless we use the 10.6+ APIs. */
icculus@5646
   216
    #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
icculus@5643
   217
    if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   218
        CFRelease(modelist);  /* NULL is ok */
icculus@5643
   219
    }
icculus@5643
   220
    #endif
icculus@5643
   221
}
icculus@5643
   222
slouken@6788
   223
static const char *
slouken@6787
   224
Cocoa_GetDisplayName(CGDirectDisplayID displayID)
slouken@6787
   225
{
slouken@6787
   226
    NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName);
slouken@6787
   227
    NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
slouken@6836
   228
    const char* displayName = NULL;
slouken@6836
   229
    
slouken@6787
   230
    if ([localizedNames count] > 0) {
slouken@6836
   231
        displayName = SDL_strdup([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
slouken@6787
   232
    }
slouken@6836
   233
    [deviceInfo release];
slouken@6836
   234
    return displayName;
slouken@6787
   235
}
slouken@6787
   236
slouken@1931
   237
void
slouken@1931
   238
Cocoa_InitModes(_THIS)
slouken@1931
   239
{
icculus@6809
   240
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@1934
   241
    CGDisplayErr result;
slouken@1934
   242
    CGDirectDisplayID *displays;
slouken@1934
   243
    CGDisplayCount numDisplays;
slouken@3505
   244
    int pass, i;
slouken@1934
   245
slouken@1934
   246
    result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
slouken@1934
   247
    if (result != kCGErrorSuccess) {
slouken@1934
   248
        CG_SetError("CGGetOnlineDisplayList()", result);
icculus@6809
   249
        [pool release];
slouken@1934
   250
        return;
slouken@1934
   251
    }
slouken@1934
   252
    displays = SDL_stack_alloc(CGDirectDisplayID, numDisplays);
slouken@1934
   253
    result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
slouken@1934
   254
    if (result != kCGErrorSuccess) {
slouken@1934
   255
        CG_SetError("CGGetOnlineDisplayList()", result);
slouken@1934
   256
        SDL_stack_free(displays);
icculus@6809
   257
        [pool release];
slouken@1934
   258
        return;
slouken@1934
   259
    }
slouken@1934
   260
slouken@3505
   261
    /* Pick up the primary display in the first pass, then get the rest */
slouken@3505
   262
    for (pass = 0; pass < 2; ++pass) {
slouken@3505
   263
        for (i = 0; i < numDisplays; ++i) {
slouken@3505
   264
            SDL_VideoDisplay display;
slouken@3505
   265
            SDL_DisplayData *displaydata;
slouken@3505
   266
            SDL_DisplayMode mode;
icculus@5643
   267
            const void *moderef = NULL;
slouken@1934
   268
slouken@3505
   269
            if (pass == 0) {
slouken@3505
   270
                if (!CGDisplayIsMain(displays[i])) {
slouken@3505
   271
                    continue;
slouken@3505
   272
                }
slouken@3505
   273
            } else {
slouken@3505
   274
                if (CGDisplayIsMain(displays[i])) {
slouken@3505
   275
                    continue;
slouken@3505
   276
                }
slouken@3505
   277
            }
slouken@1934
   278
slouken@3505
   279
            if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay) {
slouken@3505
   280
                continue;
slouken@3505
   281
            }
icculus@5643
   282
icculus@5646
   283
            #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
icculus@5643
   284
            if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   285
                moderef = CGDisplayCopyDisplayMode(displays[i]);
icculus@5643
   286
            }
icculus@5643
   287
            #endif
icculus@5643
   288
icculus@5646
   289
            #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
icculus@5643
   290
            if (!IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   291
                moderef = CGDisplayCurrentMode(displays[i]);
icculus@5643
   292
            }
icculus@5643
   293
            #endif
icculus@5643
   294
slouken@3505
   295
            if (!moderef) {
slouken@3505
   296
                continue;
slouken@3505
   297
            }
slouken@1934
   298
slouken@3505
   299
            displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
slouken@3505
   300
            if (!displaydata) {
icculus@5643
   301
                Cocoa_ReleaseDisplayMode(_this, moderef);
slouken@3505
   302
                continue;
slouken@3505
   303
            }
slouken@3505
   304
            displaydata->display = displays[i];
slouken@3505
   305
slouken@3505
   306
            SDL_zero(display);
slouken@6836
   307
            // this returns a stddup'ed string
slouken@6788
   308
            display.name = (char *)Cocoa_GetDisplayName(displays[i]);
icculus@5643
   309
            if (!GetDisplayMode (_this, moderef, &mode)) {
icculus@5643
   310
                Cocoa_ReleaseDisplayMode(_this, moderef);
slouken@6836
   311
                if (display.name) SDL_free(display.name);
slouken@3505
   312
                SDL_free(displaydata);
slouken@3505
   313
                continue;
slouken@3505
   314
            }
icculus@5643
   315
slouken@3505
   316
            display.desktop_mode = mode;
slouken@3505
   317
            display.current_mode = mode;
slouken@3505
   318
            display.driverdata = displaydata;
slouken@3505
   319
            SDL_AddVideoDisplay(&display);
slouken@6836
   320
            if (display.name) SDL_free(display.name);
slouken@1934
   321
        }
slouken@1934
   322
    }
slouken@1973
   323
    SDL_stack_free(displays);
icculus@6809
   324
    [pool release];
slouken@1934
   325
}
slouken@1934
   326
slouken@3528
   327
int
slouken@3528
   328
Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
slouken@3525
   329
{
slouken@3528
   330
    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
slouken@3525
   331
    CGRect cgrect;
slouken@3525
   332
slouken@3528
   333
    cgrect = CGDisplayBounds(displaydata->display);
slouken@3528
   334
    rect->x = (int)cgrect.origin.x;
slouken@3528
   335
    rect->y = (int)cgrect.origin.y;
slouken@3528
   336
    rect->w = (int)cgrect.size.width;
slouken@3528
   337
    rect->h = (int)cgrect.size.height;
slouken@3528
   338
    return 0;
slouken@3525
   339
}
slouken@3525
   340
slouken@1931
   341
void
slouken@3500
   342
Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
slouken@1931
   343
{
slouken@3500
   344
    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
icculus@5643
   345
    CFArrayRef modes = NULL;
icculus@5643
   346
icculus@5646
   347
    #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
icculus@5643
   348
    if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   349
        modes = CGDisplayCopyAllDisplayModes(data->display, NULL);
icculus@5643
   350
    }
icculus@5643
   351
    #endif
icculus@5643
   352
icculus@5646
   353
    #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
icculus@5643
   354
    if (!IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   355
        modes = CGDisplayAvailableModes(data->display);
icculus@5643
   356
    }
icculus@5643
   357
    #endif
icculus@5643
   358
icculus@5643
   359
    if (modes) {
icculus@5643
   360
        const CFIndex count = CFArrayGetCount(modes);
icculus@5643
   361
        CFIndex i;
slouken@1934
   362
icculus@5643
   363
        for (i = 0; i < count; i++) {
icculus@5643
   364
            const void *moderef = CFArrayGetValueAtIndex(modes, i);
icculus@5643
   365
            SDL_DisplayMode mode;
icculus@5643
   366
            if (GetDisplayMode(_this, moderef, &mode)) {
icculus@5646
   367
                #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
icculus@5643
   368
                if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   369
                    CGDisplayModeRetain((CGDisplayModeRef) moderef);
icculus@5643
   370
                }
icculus@5643
   371
                #endif
icculus@5643
   372
                SDL_AddDisplayMode(display, &mode);
icculus@5643
   373
            }
icculus@5643
   374
        }
icculus@5643
   375
icculus@5643
   376
        Cocoa_ReleaseDisplayModeList(_this, modes);
slouken@1934
   377
    }
icculus@5643
   378
}
icculus@5643
   379
icculus@5643
   380
static CGError
icculus@5643
   381
Cocoa_SwitchMode(_THIS, CGDirectDisplayID display, const void *mode)
icculus@5643
   382
{
icculus@5646
   383
    #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
icculus@5643
   384
    if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   385
        return CGDisplaySetDisplayMode(display, (CGDisplayModeRef) mode, NULL);
icculus@5643
   386
    }
icculus@5643
   387
    #endif
icculus@5643
   388
icculus@5646
   389
    #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
icculus@5643
   390
    if (!IS_SNOW_LEOPARD_OR_LATER(_this)) {
icculus@5643
   391
        return CGDisplaySwitchToMode(display, (CFDictionaryRef) mode);
icculus@5643
   392
    }
icculus@5643
   393
    #endif
icculus@5643
   394
icculus@5643
   395
    return kCGErrorFailure;
slouken@1931
   396
}
slouken@1931
   397
slouken@1931
   398
int
slouken@3500
   399
Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
slouken@1931
   400
{
slouken@3500
   401
    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
slouken@1934
   402
    SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
slouken@1934
   403
    CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
slouken@1934
   404
    CGError result;
slouken@4939
   405
slouken@1934
   406
    /* Fade to black to hide resolution-switching flicker */
slouken@1934
   407
    if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
slouken@1934
   408
        CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
slouken@1934
   409
    }
slouken@1934
   410
slouken@3513
   411
    if (data == display->desktop_mode.driverdata) {
slouken@3513
   412
        /* Restoring desktop mode */
icculus@5643
   413
        Cocoa_SwitchMode(_this, displaydata->display, data->moderef);
slouken@4939
   414
slouken@5248
   415
        if (CGDisplayIsMain(displaydata->display)) {
slouken@5248
   416
            CGReleaseAllDisplays();
slouken@5248
   417
        } else {
slouken@5248
   418
            CGDisplayRelease(displaydata->display);
slouken@5248
   419
        }
slouken@1934
   420
slouken@3513
   421
        if (CGDisplayIsMain(displaydata->display)) {
icculus@6105
   422
            Cocoa_ToggleMenuBar(YES);
slouken@3513
   423
        }
slouken@3513
   424
    } else {
slouken@4939
   425
        /* Put up the blanking window (a window above all other windows) */
slouken@5248
   426
        if (CGDisplayIsMain(displaydata->display)) {
slouken@5248
   427
            /* If we don't capture all displays, Cocoa tries to rearrange windows... *sigh* */
slouken@5248
   428
            result = CGCaptureAllDisplays();
slouken@5248
   429
        } else {
slouken@5248
   430
            result = CGDisplayCapture(displaydata->display);
slouken@5248
   431
        }
slouken@4939
   432
        if (result != kCGErrorSuccess) {
slouken@4939
   433
            CG_SetError("CGDisplayCapture()", result);
slouken@4939
   434
            goto ERR_NO_CAPTURE;
slouken@4939
   435
        }
slouken@4939
   436
slouken@3513
   437
        /* Do the physical switch */
icculus@5643
   438
        result = Cocoa_SwitchMode(_this, displaydata->display, data->moderef);
slouken@3513
   439
        if (result != kCGErrorSuccess) {
slouken@3513
   440
            CG_SetError("CGDisplaySwitchToMode()", result);
slouken@3513
   441
            goto ERR_NO_SWITCH;
slouken@3513
   442
        }
slouken@3513
   443
slouken@3513
   444
        /* Hide the menu bar so it doesn't intercept events */
slouken@3513
   445
        if (CGDisplayIsMain(displaydata->display)) {
icculus@6105
   446
            Cocoa_ToggleMenuBar(NO);
slouken@3513
   447
        }
slouken@3510
   448
    }
slouken@1973
   449
slouken@1934
   450
    /* Fade in again (asynchronously) */
slouken@1934
   451
    if (fade_token != kCGDisplayFadeReservationInvalidToken) {
slouken@1934
   452
        CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
slouken@1934
   453
        CGReleaseDisplayFadeReservation(fade_token);
slouken@1934
   454
    }
slouken@1973
   455
slouken@1934
   456
    return 0;
slouken@1934
   457
slouken@1934
   458
    /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
slouken@1934
   459
ERR_NO_SWITCH:
slouken@1934
   460
    CGDisplayRelease(displaydata->display);
slouken@1934
   461
ERR_NO_CAPTURE:
slouken@1934
   462
    if (fade_token != kCGDisplayFadeReservationInvalidToken) {
slouken@1934
   463
        CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
slouken@1934
   464
        CGReleaseDisplayFadeReservation(fade_token);
slouken@1934
   465
    }
slouken@1931
   466
    return -1;
slouken@1931
   467
}
slouken@1931
   468
slouken@1931
   469
void
slouken@1931
   470
Cocoa_QuitModes(_THIS)
slouken@1931
   471
{
icculus@5643
   472
    int i, j;
slouken@1934
   473
slouken@1934
   474
    for (i = 0; i < _this->num_displays; ++i) {
slouken@1934
   475
        SDL_VideoDisplay *display = &_this->displays[i];
icculus@5643
   476
        SDL_DisplayModeData *mode;
slouken@1934
   477
slouken@1934
   478
        if (display->current_mode.driverdata != display->desktop_mode.driverdata) {
slouken@3500
   479
            Cocoa_SetDisplayMode(_this, display, &display->desktop_mode);
slouken@1934
   480
        }
icculus@5643
   481
icculus@5643
   482
        mode = (SDL_DisplayModeData *) display->desktop_mode.driverdata;
icculus@5643
   483
        Cocoa_ReleaseDisplayMode(_this, mode->moderef);
icculus@5643
   484
icculus@5643
   485
        for (j = 0; j < display->num_display_modes; j++) {
icculus@5643
   486
            mode = (SDL_DisplayModeData*) display->display_modes[j].driverdata;
icculus@5643
   487
            Cocoa_ReleaseDisplayMode(_this, mode->moderef);
icculus@5643
   488
        }
icculus@5643
   489
slouken@1934
   490
    }
icculus@6105
   491
    Cocoa_ToggleMenuBar(YES);
slouken@1931
   492
}
slouken@1931
   493
slouken@6044
   494
#endif /* SDL_VIDEO_DRIVER_COCOA */
slouken@6044
   495
slouken@1931
   496
/* vi: set ts=4 sw=4 expandtab: */