src/video/cocoa/SDL_cocoamodes.m
author Sam Lantinga
Fri, 27 Jan 2017 06:05:50 -0800
changeset 10856 486aa38c6a88
parent 10737 3406a0f8b041
child 11142 1e26564c7288
permissions -rw-r--r--
Added Thrustmaster Wheel FFB entry to the list of wheels
slouken@1931
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 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
*/
icculus@8093
    21
#include "../../SDL_internal.h"
icculus@10019
    22
#include "SDL_assert.h"
slouken@1931
    23
slouken@6044
    24
#if SDL_VIDEO_DRIVER_COCOA
slouken@6044
    25
slouken@1931
    26
#include "SDL_cocoavideo.h"
slouken@1931
    27
slouken@6787
    28
/* We need this for IODisplayCreateInfoDictionary and kIODisplayOnlyPreferredName */
slouken@6787
    29
#include <IOKit/graphics/IOGraphicsLib.h>
slouken@6787
    30
slouken@9112
    31
/* We need this for CVDisplayLinkGetNominalOutputVideoRefreshPeriod */
slouken@9112
    32
#include <CoreVideo/CVBase.h>
slouken@9112
    33
#include <CoreVideo/CVDisplayLink.h>
slouken@9112
    34
icculus@6104
    35
/* we need this for ShowMenuBar() and HideMenuBar(). */
icculus@6104
    36
#include <Carbon/Carbon.h>
aschiffler@6101
    37
jorgen@7507
    38
/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */
jorgen@7507
    39
#include <AvailabilityMacros.h>
jorgen@7507
    40
slouken@7771
    41
slouken@7771
    42
static void
slouken@7771
    43
Cocoa_ToggleMenuBar(const BOOL show)
icculus@6105
    44
{
icculus@6105
    45
    /* !!! FIXME: keep an eye on this.
icculus@6105
    46
     * ShowMenuBar/HideMenuBar is officially unavailable for 64-bit binaries.
icculus@6105
    47
     *  It happens to work, as of 10.7, but we're going to see if
icculus@6105
    48
     *  we can just simply do without it on newer OSes...
icculus@6105
    49
     */
icculus@6105
    50
#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
slouken@8986
    51
    if (show) {
icculus@6105
    52
        ShowMenuBar();
slouken@8986
    53
    } else {
icculus@6105
    54
        HideMenuBar();
slouken@8986
    55
    }
icculus@6105
    56
#endif
icculus@6105
    57
}
icculus@6105
    58
icculus@7037
    59
static int
slouken@1934
    60
CG_SetError(const char *prefix, CGDisplayErr result)
slouken@1934
    61
{
slouken@1934
    62
    const char *error;
slouken@1934
    63
slouken@1934
    64
    switch (result) {
slouken@1934
    65
    case kCGErrorFailure:
slouken@1934
    66
        error = "kCGErrorFailure";
slouken@1934
    67
        break;
slouken@1934
    68
    case kCGErrorIllegalArgument:
slouken@1934
    69
        error = "kCGErrorIllegalArgument";
slouken@1934
    70
        break;
slouken@1934
    71
    case kCGErrorInvalidConnection:
slouken@1934
    72
        error = "kCGErrorInvalidConnection";
slouken@1934
    73
        break;
slouken@1934
    74
    case kCGErrorInvalidContext:
slouken@1934
    75
        error = "kCGErrorInvalidContext";
slouken@1934
    76
        break;
slouken@1934
    77
    case kCGErrorCannotComplete:
slouken@1934
    78
        error = "kCGErrorCannotComplete";
slouken@1934
    79
        break;
slouken@1934
    80
    case kCGErrorNotImplemented:
slouken@1934
    81
        error = "kCGErrorNotImplemented";
slouken@1934
    82
        break;
slouken@1934
    83
    case kCGErrorRangeCheck:
slouken@1934
    84
        error = "kCGErrorRangeCheck";
slouken@1934
    85
        break;
slouken@1934
    86
    case kCGErrorTypeCheck:
slouken@1934
    87
        error = "kCGErrorTypeCheck";
slouken@1934
    88
        break;
slouken@1934
    89
    case kCGErrorInvalidOperation:
slouken@1934
    90
        error = "kCGErrorInvalidOperation";
slouken@1934
    91
        break;
slouken@1934
    92
    case kCGErrorNoneAvailable:
slouken@1934
    93
        error = "kCGErrorNoneAvailable";
slouken@1934
    94
        break;
slouken@1934
    95
    default:
slouken@1934
    96
        error = "Unknown Error";
slouken@1934
    97
        break;
slouken@1934
    98
    }
icculus@7037
    99
    return SDL_SetError("%s: %s", prefix, error);
slouken@1934
   100
}
slouken@1934
   101
slouken@1934
   102
static SDL_bool
slime73@10176
   103
GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CVDisplayLinkRef link, SDL_DisplayMode *mode)
slouken@1934
   104
{
slouken@1934
   105
    SDL_DisplayModeData *data;
slime73@10339
   106
    int width = 0;
slime73@10339
   107
    int height = 0;
slime73@10339
   108
    int bpp = 0;
slime73@10339
   109
    int refreshRate = 0;
slime73@10176
   110
    CFStringRef fmt;
slouken@1934
   111
slouken@1934
   112
    data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
slouken@1934
   113
    if (!data) {
slouken@1934
   114
        return SDL_FALSE;
slouken@1934
   115
    }
slime73@10176
   116
    data->moderef = vidmode;
slouken@1934
   117
slime73@10176
   118
    fmt = CGDisplayModeCopyPixelEncoding(vidmode);
slime73@10339
   119
    width = (int) CGDisplayModeGetWidth(vidmode);
slime73@10339
   120
    height = (int) CGDisplayModeGetHeight(vidmode);
slime73@10339
   121
    refreshRate = (int) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
icculus@5643
   122
slime73@10176
   123
    if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
slime73@10176
   124
                        kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
slime73@10176
   125
        bpp = 32;
slime73@10176
   126
    } else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
slime73@10176
   127
                        kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
slime73@10176
   128
        bpp = 16;
slime73@10176
   129
    } else if (CFStringCompare(fmt, CFSTR(kIO30BitDirectPixels),
slime73@10176
   130
                        kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
slime73@10176
   131
        bpp = 30;
slime73@10176
   132
    } else {
slime73@10176
   133
        bpp = 0;  /* ignore 8-bit and such for now. */
icculus@5643
   134
    }
icculus@5643
   135
slime73@10176
   136
    CFRelease(fmt);
slouken@1934
   137
slouken@9112
   138
    /* CGDisplayModeGetRefreshRate returns 0 for many non-CRT displays. */
slouken@9112
   139
    if (refreshRate == 0 && link != NULL) {
slouken@9112
   140
        CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
slouken@9112
   141
        if ((time.flags & kCVTimeIsIndefinite) == 0 && time.timeValue != 0) {
slime73@10339
   142
            refreshRate = (int) ((time.timeScale / (double) time.timeValue) + 0.5);
slouken@9112
   143
        }
slouken@9112
   144
    }
slouken@9112
   145
slouken@1969
   146
    mode->format = SDL_PIXELFORMAT_UNKNOWN;
slouken@1934
   147
    switch (bpp) {
slouken@1934
   148
    case 16:
slouken@2237
   149
        mode->format = SDL_PIXELFORMAT_ARGB1555;
slouken@1934
   150
        break;
slouken@9112
   151
    case 30:
slouken@9112
   152
        mode->format = SDL_PIXELFORMAT_ARGB2101010;
slouken@9112
   153
        break;
slouken@1934
   154
    case 32:
slouken@2237
   155
        mode->format = SDL_PIXELFORMAT_ARGB8888;
slouken@1934
   156
        break;
icculus@5643
   157
    case 8: /* We don't support palettized modes now */
icculus@9701
   158
    default: /* Totally unrecognizable bit depth. */
icculus@9545
   159
        SDL_free(data);
icculus@5643
   160
        return SDL_FALSE;
slouken@1934
   161
    }
slouken@1934
   162
    mode->w = width;
slouken@1934
   163
    mode->h = height;
slouken@1934
   164
    mode->refresh_rate = refreshRate;
slouken@1934
   165
    mode->driverdata = data;
slouken@1934
   166
    return SDL_TRUE;
slouken@1934
   167
}
slouken@1931
   168
slouken@6788
   169
static const char *
slouken@6787
   170
Cocoa_GetDisplayName(CGDirectDisplayID displayID)
slouken@6787
   171
{
slouken@8866
   172
    CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName);
slouken@8866
   173
    NSDictionary *localizedNames = [(NSDictionary *)deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
slouken@6836
   174
    const char* displayName = NULL;
slouken@7191
   175
slouken@6787
   176
    if ([localizedNames count] > 0) {
slouken@6836
   177
        displayName = SDL_strdup([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
slouken@6787
   178
    }
slouken@8866
   179
    CFRelease(deviceInfo);
slouken@6836
   180
    return displayName;
slouken@6787
   181
}
slouken@6787
   182
slouken@1931
   183
void
slouken@1931
   184
Cocoa_InitModes(_THIS)
slouken@9087
   185
{ @autoreleasepool
slouken@1931
   186
{
slouken@1934
   187
    CGDisplayErr result;
slouken@1934
   188
    CGDirectDisplayID *displays;
slouken@1934
   189
    CGDisplayCount numDisplays;
slouken@3505
   190
    int pass, i;
slouken@1934
   191
slouken@1934
   192
    result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
slouken@1934
   193
    if (result != kCGErrorSuccess) {
slouken@1934
   194
        CG_SetError("CGGetOnlineDisplayList()", result);
slouken@1934
   195
        return;
slouken@1934
   196
    }
slouken@1934
   197
    displays = SDL_stack_alloc(CGDirectDisplayID, numDisplays);
slouken@1934
   198
    result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
slouken@1934
   199
    if (result != kCGErrorSuccess) {
slouken@1934
   200
        CG_SetError("CGGetOnlineDisplayList()", result);
slouken@1934
   201
        SDL_stack_free(displays);
slouken@1934
   202
        return;
slouken@1934
   203
    }
slouken@1934
   204
slouken@3505
   205
    /* Pick up the primary display in the first pass, then get the rest */
slouken@3505
   206
    for (pass = 0; pass < 2; ++pass) {
slouken@3505
   207
        for (i = 0; i < numDisplays; ++i) {
slouken@3505
   208
            SDL_VideoDisplay display;
slouken@3505
   209
            SDL_DisplayData *displaydata;
slouken@3505
   210
            SDL_DisplayMode mode;
slime73@10176
   211
            CGDisplayModeRef moderef = NULL;
slouken@9112
   212
            CVDisplayLinkRef link = NULL;
slouken@1934
   213
slouken@3505
   214
            if (pass == 0) {
slouken@3505
   215
                if (!CGDisplayIsMain(displays[i])) {
slouken@3505
   216
                    continue;
slouken@3505
   217
                }
slouken@3505
   218
            } else {
slouken@3505
   219
                if (CGDisplayIsMain(displays[i])) {
slouken@3505
   220
                    continue;
slouken@3505
   221
                }
slouken@3505
   222
            }
slouken@1934
   223
slouken@3505
   224
            if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay) {
slouken@3505
   225
                continue;
slouken@3505
   226
            }
icculus@5643
   227
slime73@10176
   228
            moderef = CGDisplayCopyDisplayMode(displays[i]);
icculus@5643
   229
slouken@3505
   230
            if (!moderef) {
slouken@3505
   231
                continue;
slouken@3505
   232
            }
slouken@1934
   233
slouken@3505
   234
            displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
slouken@3505
   235
            if (!displaydata) {
slime73@10176
   236
                CGDisplayModeRelease(moderef);
slouken@3505
   237
                continue;
slouken@3505
   238
            }
slouken@3505
   239
            displaydata->display = displays[i];
slouken@3505
   240
slouken@9112
   241
            CVDisplayLinkCreateWithCGDisplay(displays[i], &link);
slouken@9112
   242
slouken@3505
   243
            SDL_zero(display);
slouken@7191
   244
            /* this returns a stddup'ed string */
slouken@6788
   245
            display.name = (char *)Cocoa_GetDisplayName(displays[i]);
slouken@9112
   246
            if (!GetDisplayMode(_this, moderef, link, &mode)) {
slouken@9112
   247
                CVDisplayLinkRelease(link);
slime73@10176
   248
                CGDisplayModeRelease(moderef);
slouken@7719
   249
                SDL_free(display.name);
slouken@3505
   250
                SDL_free(displaydata);
slouken@3505
   251
                continue;
slouken@3505
   252
            }
icculus@5643
   253
slouken@9112
   254
            CVDisplayLinkRelease(link);
slouken@9112
   255
slouken@3505
   256
            display.desktop_mode = mode;
slouken@3505
   257
            display.current_mode = mode;
slouken@3505
   258
            display.driverdata = displaydata;
slouken@3505
   259
            SDL_AddVideoDisplay(&display);
slouken@7719
   260
            SDL_free(display.name);
slouken@1934
   261
        }
slouken@1934
   262
    }
slouken@1973
   263
    SDL_stack_free(displays);
slouken@9087
   264
}}
slouken@1934
   265
slouken@3528
   266
int
slouken@3528
   267
Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
slouken@3525
   268
{
slouken@3528
   269
    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
slouken@3525
   270
    CGRect cgrect;
slouken@3525
   271
slouken@3528
   272
    cgrect = CGDisplayBounds(displaydata->display);
slouken@3528
   273
    rect->x = (int)cgrect.origin.x;
slouken@3528
   274
    rect->y = (int)cgrect.origin.y;
slouken@3528
   275
    rect->w = (int)cgrect.size.width;
slouken@3528
   276
    rect->h = (int)cgrect.size.height;
slouken@3528
   277
    return 0;
slouken@3525
   278
}
slouken@3525
   279
icculus@10019
   280
int
icculus@10019
   281
Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
icculus@10019
   282
{
icculus@10019
   283
    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
icculus@10019
   284
    const CGDirectDisplayID cgdisplay = displaydata->display;
icculus@10019
   285
    NSArray *screens = [NSScreen screens];
icculus@10019
   286
    NSScreen *screen = nil;
icculus@10019
   287
icculus@10019
   288
    /* !!! FIXME: maybe track the NSScreen in SDL_DisplayData? */
icculus@10019
   289
    for (NSScreen *i in screens) {
icculus@10019
   290
        const CGDirectDisplayID thisDisplay = (CGDirectDisplayID) [[[i deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
icculus@10019
   291
        if (thisDisplay == cgdisplay) {
icculus@10019
   292
            screen = i;
icculus@10019
   293
            break;
icculus@10019
   294
        }
icculus@10019
   295
    }
icculus@10019
   296
icculus@10019
   297
    SDL_assert(screen != nil);  /* didn't find it?! */
icculus@10019
   298
    if (screen == nil) {
icculus@10019
   299
        return -1;
icculus@10019
   300
    }
icculus@10019
   301
icculus@10019
   302
    const CGRect cgrect = CGDisplayBounds(cgdisplay);
icculus@10019
   303
    const NSRect frame = [screen visibleFrame];
icculus@10019
   304
icculus@10019
   305
    // !!! FIXME: I assume -[NSScreen visibleFrame] is relative to the origin of the screen in question and not the whole desktop.
icculus@10019
   306
    // !!! FIXME: The math vs CGDisplayBounds might be incorrect if that's not the case, though. Check this.
icculus@10019
   307
    rect->x = (int)(cgrect.origin.x + frame.origin.x);
icculus@10019
   308
    rect->y = (int)(cgrect.origin.y + frame.origin.y);
icculus@10019
   309
    rect->w = (int)frame.size.width;
icculus@10019
   310
    rect->h = (int)frame.size.height;
icculus@10019
   311
icculus@10019
   312
    return 0;
icculus@10019
   313
}
icculus@10019
   314
icculus@10038
   315
int
icculus@10038
   316
Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi)
icculus@10038
   317
{
icculus@10038
   318
    const float MM_IN_INCH = 25.4f;
icculus@10038
   319
icculus@10038
   320
    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
icculus@10038
   321
icculus@10038
   322
    CGSize displaySize = CGDisplayScreenSize(data->display);
slime73@10339
   323
    int pixelWidth =  (int) CGDisplayPixelsWide(data->display);
slime73@10339
   324
    int pixelHeight = (int) CGDisplayPixelsHigh(data->display);
icculus@10038
   325
philipp@10186
   326
    if (ddpi) {
philipp@10186
   327
        *ddpi = SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH);
philipp@10186
   328
    }
philipp@10186
   329
    if (hdpi) {
philipp@10186
   330
        *hdpi = pixelWidth * MM_IN_INCH / displaySize.width;
philipp@10186
   331
    }
philipp@10186
   332
    if (vdpi) {
philipp@10186
   333
        *vdpi = pixelHeight * MM_IN_INCH / displaySize.height;
philipp@10186
   334
    }
icculus@10038
   335
icculus@10038
   336
    return 0;
icculus@10038
   337
}
icculus@10038
   338
slouken@1931
   339
void
slouken@3500
   340
Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
slouken@1931
   341
{
slouken@3500
   342
    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
slime73@10176
   343
    CFArrayRef modes = CGDisplayCopyAllDisplayModes(data->display, NULL);
icculus@5643
   344
icculus@5643
   345
    if (modes) {
slouken@9112
   346
        CVDisplayLinkRef link = NULL;
icculus@5643
   347
        const CFIndex count = CFArrayGetCount(modes);
icculus@5643
   348
        CFIndex i;
slouken@1934
   349
slouken@9112
   350
        CVDisplayLinkCreateWithCGDisplay(data->display, &link);
slouken@9112
   351
icculus@5643
   352
        for (i = 0; i < count; i++) {
slime73@10176
   353
            CGDisplayModeRef moderef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
icculus@5643
   354
            SDL_DisplayMode mode;
slouken@9112
   355
            if (GetDisplayMode(_this, moderef, link, &mode)) {
slime73@10176
   356
                CGDisplayModeRetain(moderef);
icculus@5643
   357
                SDL_AddDisplayMode(display, &mode);
icculus@5643
   358
            }
icculus@5643
   359
        }
icculus@5643
   360
slouken@9112
   361
        CVDisplayLinkRelease(link);
slime73@10176
   362
        CFRelease(modes);
slouken@1934
   363
    }
icculus@5643
   364
}
icculus@5643
   365
slouken@1931
   366
int
slouken@3500
   367
Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
slouken@1931
   368
{
slouken@3500
   369
    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
slouken@1934
   370
    SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
slouken@1934
   371
    CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
slouken@1934
   372
    CGError result;
slouken@4939
   373
slouken@1934
   374
    /* Fade to black to hide resolution-switching flicker */
slouken@1934
   375
    if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
slouken@1934
   376
        CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
slouken@1934
   377
    }
slouken@1934
   378
slouken@3513
   379
    if (data == display->desktop_mode.driverdata) {
slouken@3513
   380
        /* Restoring desktop mode */
slime73@10176
   381
        CGDisplaySetDisplayMode(displaydata->display, data->moderef, NULL);
slouken@4939
   382
slouken@5248
   383
        if (CGDisplayIsMain(displaydata->display)) {
slouken@5248
   384
            CGReleaseAllDisplays();
slouken@5248
   385
        } else {
slouken@5248
   386
            CGDisplayRelease(displaydata->display);
slouken@5248
   387
        }
slouken@1934
   388
slouken@3513
   389
        if (CGDisplayIsMain(displaydata->display)) {
icculus@6105
   390
            Cocoa_ToggleMenuBar(YES);
slouken@3513
   391
        }
slouken@3513
   392
    } else {
slouken@4939
   393
        /* Put up the blanking window (a window above all other windows) */
slouken@5248
   394
        if (CGDisplayIsMain(displaydata->display)) {
slouken@5248
   395
            /* If we don't capture all displays, Cocoa tries to rearrange windows... *sigh* */
slouken@5248
   396
            result = CGCaptureAllDisplays();
slouken@5248
   397
        } else {
slouken@5248
   398
            result = CGDisplayCapture(displaydata->display);
slouken@5248
   399
        }
slouken@4939
   400
        if (result != kCGErrorSuccess) {
slouken@4939
   401
            CG_SetError("CGDisplayCapture()", result);
slouken@4939
   402
            goto ERR_NO_CAPTURE;
slouken@4939
   403
        }
slouken@4939
   404
slouken@3513
   405
        /* Do the physical switch */
slime73@10176
   406
        result = CGDisplaySetDisplayMode(displaydata->display, data->moderef, NULL);
slouken@3513
   407
        if (result != kCGErrorSuccess) {
slouken@3513
   408
            CG_SetError("CGDisplaySwitchToMode()", result);
slouken@3513
   409
            goto ERR_NO_SWITCH;
slouken@3513
   410
        }
slouken@3513
   411
slouken@3513
   412
        /* Hide the menu bar so it doesn't intercept events */
slouken@3513
   413
        if (CGDisplayIsMain(displaydata->display)) {
icculus@6105
   414
            Cocoa_ToggleMenuBar(NO);
slouken@3513
   415
        }
slouken@3510
   416
    }
slouken@1973
   417
slouken@1934
   418
    /* Fade in again (asynchronously) */
slouken@1934
   419
    if (fade_token != kCGDisplayFadeReservationInvalidToken) {
slouken@1934
   420
        CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
slouken@1934
   421
        CGReleaseDisplayFadeReservation(fade_token);
slouken@1934
   422
    }
slouken@1973
   423
slouken@1934
   424
    return 0;
slouken@1934
   425
slouken@1934
   426
    /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
slouken@1934
   427
ERR_NO_SWITCH:
slouken@1934
   428
    CGDisplayRelease(displaydata->display);
slouken@1934
   429
ERR_NO_CAPTURE:
slouken@1934
   430
    if (fade_token != kCGDisplayFadeReservationInvalidToken) {
slouken@1934
   431
        CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
slouken@1934
   432
        CGReleaseDisplayFadeReservation(fade_token);
slouken@1934
   433
    }
slouken@1931
   434
    return -1;
slouken@1931
   435
}
slouken@1931
   436
slouken@1931
   437
void
slouken@1931
   438
Cocoa_QuitModes(_THIS)
slouken@1931
   439
{
icculus@5643
   440
    int i, j;
slouken@1934
   441
slouken@1934
   442
    for (i = 0; i < _this->num_displays; ++i) {
slouken@1934
   443
        SDL_VideoDisplay *display = &_this->displays[i];
icculus@5643
   444
        SDL_DisplayModeData *mode;
slouken@1934
   445
slouken@1934
   446
        if (display->current_mode.driverdata != display->desktop_mode.driverdata) {
slouken@3500
   447
            Cocoa_SetDisplayMode(_this, display, &display->desktop_mode);
slouken@1934
   448
        }
icculus@5643
   449
icculus@5643
   450
        mode = (SDL_DisplayModeData *) display->desktop_mode.driverdata;
slime73@10176
   451
        CGDisplayModeRelease(mode->moderef);
icculus@5643
   452
icculus@5643
   453
        for (j = 0; j < display->num_display_modes; j++) {
icculus@5643
   454
            mode = (SDL_DisplayModeData*) display->display_modes[j].driverdata;
slime73@10176
   455
            CGDisplayModeRelease(mode->moderef);
icculus@5643
   456
        }
icculus@5643
   457
slouken@1934
   458
    }
icculus@6105
   459
    Cocoa_ToggleMenuBar(YES);
slouken@1931
   460
}
slouken@1931
   461
slouken@6044
   462
#endif /* SDL_VIDEO_DRIVER_COCOA */
slouken@6044
   463
slouken@1931
   464
/* vi: set ts=4 sw=4 expandtab: */