src/video/cocoa/SDL_cocoawindow.m
author Jørgen P. Tjernø <jorgen@valvesoftware.com>
Tue, 25 Feb 2014 15:28:12 -0800
changeset 8258 569354dec4e9
parent 8149 681eb46b8ac4
child 8260 028ed8da2524
permissions -rw-r--r--
Mac: Immediately update current OpenGL context's shape.

Previously we were postponing our -[NSOpenGLContext update] call to the next
SDL_GL_SwapWindow, even if the context was current on the current thread. This
changes it so that we will do the update immediately if it's the current
context.

If you're rendering on another thread, you need to call SDL_GL_SwapWindow once
after a resize event to ensure your drawable will produce non-garbage data.

Bug: https://bugzilla.libsdl.org/show_bug.cgi?id=2339
slouken@1933
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@1933
     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@1933
     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@1933
    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@1933
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@1933
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_COCOA
slouken@6044
    24
slouken@8083
    25
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
slouken@8083
    26
# error SDL for Mac OS X must be built with a 10.7 SDK or above.
slouken@8083
    27
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1070 */
slouken@8083
    28
slouken@1933
    29
#include "SDL_syswm.h"
slouken@5398
    30
#include "SDL_timer.h"  /* For SDL_GetTicks() */
slouken@7915
    31
#include "SDL_hints.h"
slouken@1933
    32
#include "../SDL_sysvideo.h"
slouken@1933
    33
#include "../../events/SDL_keyboard_c.h"
slouken@1933
    34
#include "../../events/SDL_mouse_c.h"
slouken@4673
    35
#include "../../events/SDL_touch_c.h"
slouken@1933
    36
#include "../../events/SDL_windowevents_c.h"
slouken@1933
    37
#include "SDL_cocoavideo.h"
eligottlieb@4811
    38
#include "SDL_cocoashape.h"
gzjjgod@5057
    39
#include "SDL_cocoamouse.h"
jorgen@7594
    40
#include "SDL_cocoaopengl.h"
slouken@1933
    41
slouken@5398
    42
static Uint32 s_moveHack;
slouken@5398
    43
slouken@7771
    44
static void ConvertNSRect(NSRect *r)
slouken@1933
    45
{
slouken@1933
    46
    r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
slouken@1933
    47
}
slouken@1933
    48
slouken@7952
    49
static void
slouken@7952
    50
ScheduleContextUpdates(SDL_WindowData *data)
jorgen@7595
    51
{
jorgen@8258
    52
    NSOpenGLContext *currentContext = [NSOpenGLContext currentContext];
jorgen@7595
    53
    NSMutableArray *contexts = data->nscontexts;
jorgen@7595
    54
    @synchronized (contexts) {
jorgen@7595
    55
        for (SDLOpenGLContext *context in contexts) {
jorgen@8258
    56
            if (context == currentContext) {
jorgen@8258
    57
                [context update];
jorgen@8258
    58
            } else {
jorgen@8258
    59
                [context scheduleUpdate];
jorgen@8258
    60
            }
jorgen@7595
    61
        }
jorgen@7595
    62
    }
jorgen@7595
    63
}
jorgen@7595
    64
slouken@7952
    65
static int
slouken@7952
    66
GetHintCtrlClickEmulateRightClick()
slouken@7915
    67
{
slouken@7915
    68
	const char *hint = SDL_GetHint( SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK );
slouken@7915
    69
	return hint != NULL && *hint != '0';
slouken@7915
    70
}
slouken@7915
    71
slouken@7952
    72
static unsigned int
slouken@7952
    73
GetWindowStyle(SDL_Window * window)
slouken@7952
    74
{
slouken@7952
    75
    unsigned int style;
slouken@7952
    76
slouken@7952
    77
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@7952
    78
        style = NSBorderlessWindowMask;
slouken@7952
    79
    } else {
slouken@7952
    80
        if (window->flags & SDL_WINDOW_BORDERLESS) {
slouken@7952
    81
            style = NSBorderlessWindowMask;
slouken@7952
    82
        } else {
slouken@7952
    83
            style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
slouken@7952
    84
        }
slouken@7952
    85
        if (window->flags & SDL_WINDOW_RESIZABLE) {
slouken@7952
    86
            style |= NSResizableWindowMask;
slouken@7952
    87
        }
slouken@7952
    88
    }
slouken@7952
    89
    return style;
slouken@7952
    90
}
slouken@7952
    91
slouken@7990
    92
static SDL_bool
slouken@7990
    93
SetWindowStyle(SDL_Window * window, unsigned int style)
slouken@7990
    94
{
slouken@7990
    95
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@7990
    96
    NSWindow *nswindow = data->nswindow;
slouken@7990
    97
slouken@7990
    98
    if (![nswindow respondsToSelector: @selector(setStyleMask:)]) {
slouken@7990
    99
        return SDL_FALSE;
slouken@7990
   100
    }
slouken@7990
   101
slouken@7990
   102
    /* The view responder chain gets messed with during setStyleMask */
slouken@7990
   103
    if ([[nswindow contentView] nextResponder] == data->listener) {
slouken@7990
   104
        [[nswindow contentView] setNextResponder:nil];
slouken@7990
   105
    }
slouken@7990
   106
slouken@7990
   107
    [nswindow performSelector: @selector(setStyleMask:) withObject: (id)(uintptr_t)style];
slouken@7990
   108
slouken@7990
   109
    /* The view responder chain gets messed with during setStyleMask */
slouken@7990
   110
    if ([[nswindow contentView] nextResponder] != data->listener) {
slouken@7990
   111
        [[nswindow contentView] setNextResponder:data->listener];
slouken@7990
   112
    }
slouken@7990
   113
slouken@7990
   114
    return SDL_TRUE;
slouken@7990
   115
}
slouken@7990
   116
slouken@7952
   117
slouken@1933
   118
@implementation Cocoa_WindowListener
slouken@1933
   119
slouken@1933
   120
- (void)listen:(SDL_WindowData *)data
slouken@1933
   121
{
slouken@1933
   122
    NSNotificationCenter *center;
slouken@5371
   123
    NSWindow *window = data->nswindow;
slouken@5371
   124
    NSView *view = [window contentView];
slouken@1933
   125
slouken@1933
   126
    _data = data;
jorgen@7087
   127
    observingVisible = YES;
slouken@7740
   128
    wasCtrlLeft = NO;
jorgen@7087
   129
    wasVisible = [window isVisible];
slouken@7967
   130
    isFullscreenSpace = NO;
slouken@7952
   131
    inFullscreenTransition = NO;
slouken@7963
   132
    pendingWindowOperation = PENDING_OPERATION_NONE;
slouken@1933
   133
slouken@1933
   134
    center = [NSNotificationCenter defaultCenter];
slouken@1933
   135
slouken@5374
   136
    if ([window delegate] != nil) {
slouken@5374
   137
        [center addObserver:self selector:@selector(windowDidExpose:) name:NSWindowDidExposeNotification object:window];
slouken@5374
   138
        [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:window];
slouken@5374
   139
        [center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:window];
slouken@5374
   140
        [center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:window];
slouken@5374
   141
        [center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:window];
slouken@5374
   142
        [center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:window];
slouken@5374
   143
        [center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:window];
slouken@7952
   144
        [center addObserver:self selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:window];
slouken@7952
   145
        [center addObserver:self selector:@selector(windowDidEnterFullScreen:) name:NSWindowDidEnterFullScreenNotification object:window];
slouken@7952
   146
        [center addObserver:self selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:window];
slouken@7952
   147
        [center addObserver:self selector:@selector(windowDidExitFullScreen:) name:NSWindowDidExitFullScreenNotification object:window];
slouken@5374
   148
    } else {
slouken@5374
   149
        [window setDelegate:self];
slouken@5374
   150
    }
slouken@1933
   151
slouken@7191
   152
    /* Haven't found a delegate / notification that triggers when the window is
slouken@7191
   153
     * ordered out (is not visible any more). You can be ordered out without
slouken@7191
   154
     * minimizing, so DidMiniaturize doesn't work. (e.g. -[NSWindow orderOut:])
slouken@7191
   155
     */
jorgen@7084
   156
    [window addObserver:self
jorgen@7084
   157
             forKeyPath:@"visible"
jorgen@7084
   158
                options:NSKeyValueObservingOptionNew
jorgen@7084
   159
                context:NULL];
jorgen@7084
   160
slouken@5371
   161
    [window setNextResponder:self];
slouken@5371
   162
    [window setAcceptsMouseMovedEvents:YES];
slouken@5371
   163
slouken@5371
   164
    [view setNextResponder:self];
icculus@6108
   165
icculus@6108
   166
    if ([view respondsToSelector:@selector(setAcceptsTouchEvents:)]) {
icculus@6108
   167
        [view setAcceptsTouchEvents:YES];
icculus@6108
   168
    }
slouken@1933
   169
}
slouken@1933
   170
jorgen@7084
   171
- (void)observeValueForKeyPath:(NSString *)keyPath
jorgen@7084
   172
                      ofObject:(id)object
jorgen@7084
   173
                        change:(NSDictionary *)change
jorgen@7084
   174
                       context:(void *)context
jorgen@7084
   175
{
jorgen@7087
   176
    if (!observingVisible) {
jorgen@7087
   177
        return;
jorgen@7087
   178
    }
jorgen@7087
   179
jorgen@7084
   180
    if (object == _data->nswindow && [keyPath isEqualToString:@"visible"]) {
jorgen@7084
   181
        int newVisibility = [[change objectForKey:@"new"] intValue];
jorgen@7084
   182
        if (newVisibility) {
jorgen@7084
   183
            SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
jorgen@7084
   184
        } else {
jorgen@7084
   185
            SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
jorgen@7084
   186
        }
jorgen@7084
   187
    }
jorgen@7084
   188
}
jorgen@7084
   189
jorgen@7087
   190
-(void) pauseVisibleObservation
jorgen@7087
   191
{
jorgen@7087
   192
    observingVisible = NO;
jorgen@7087
   193
    wasVisible = [_data->nswindow isVisible];
jorgen@7087
   194
}
jorgen@7087
   195
jorgen@7087
   196
-(void) resumeVisibleObservation
jorgen@7087
   197
{
jorgen@7087
   198
    BOOL isVisible = [_data->nswindow isVisible];
jorgen@7087
   199
    observingVisible = YES;
jorgen@7087
   200
    if (wasVisible != isVisible) {
jorgen@7087
   201
        if (isVisible) {
jorgen@7087
   202
            SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
jorgen@7087
   203
        } else {
jorgen@7087
   204
            SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
jorgen@7087
   205
        }
jorgen@7087
   206
jorgen@7087
   207
        wasVisible = isVisible;
jorgen@7087
   208
    }
jorgen@7087
   209
}
jorgen@7087
   210
slouken@7967
   211
-(BOOL) setFullscreenSpace:(BOOL) state;
slouken@7961
   212
{
slouken@7961
   213
    SDL_Window *window = _data->window;
slouken@7961
   214
    NSWindow *nswindow = _data->nswindow;
slouken@7961
   215
slouken@7967
   216
    if (![nswindow respondsToSelector: @selector(collectionBehavior)]) {
slouken@7967
   217
        return NO;
slouken@7967
   218
    }
slouken@7967
   219
    if ([nswindow collectionBehavior] != NSWindowCollectionBehaviorFullScreenPrimary) {
slouken@7961
   220
        return NO;
slouken@7961
   221
    }
slouken@7961
   222
slouken@7967
   223
    if (state == isFullscreenSpace) {
slouken@7961
   224
        return YES;
slouken@7961
   225
    }
slouken@7961
   226
slouken@7961
   227
    if (inFullscreenTransition) {
slouken@7961
   228
        if (state) {
slouken@7963
   229
            [self addPendingWindowOperation:PENDING_OPERATION_ENTER_FULLSCREEN];
slouken@7961
   230
        } else {
slouken@7963
   231
            [self addPendingWindowOperation:PENDING_OPERATION_LEAVE_FULLSCREEN];
slouken@7961
   232
        }
slouken@7961
   233
        return YES;
slouken@7961
   234
    }
slouken@7968
   235
    inFullscreenTransition = YES;
slouken@7968
   236
slouken@7968
   237
    /* Update the flags here so the state change is available immediately */
slouken@7968
   238
    if (state) {
slouken@7968
   239
        window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
slouken@7968
   240
    } else {
slouken@7968
   241
        window->flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP;
slouken@7968
   242
    }
slouken@7961
   243
slouken@7965
   244
    [nswindow performSelectorOnMainThread: @selector(toggleFullScreen:) withObject:nswindow waitUntilDone:NO];
slouken@7961
   245
    return YES;
slouken@7952
   246
}
slouken@7952
   247
slouken@7968
   248
-(BOOL) isInFullscreenSpace
slouken@7968
   249
{
slouken@7968
   250
    return isFullscreenSpace;
slouken@7968
   251
}
slouken@7968
   252
slouken@7968
   253
-(BOOL) isInFullscreenSpaceTransition
slouken@7963
   254
{
slouken@7963
   255
    return inFullscreenTransition;
slouken@7963
   256
}
slouken@7963
   257
slouken@7963
   258
-(void) addPendingWindowOperation:(PendingWindowOperation) operation
slouken@7963
   259
{
slouken@7963
   260
    pendingWindowOperation = operation;
slouken@7963
   261
}
slouken@7963
   262
slouken@1933
   263
- (void)close
slouken@1933
   264
{
slouken@1933
   265
    NSNotificationCenter *center;
slouken@5371
   266
    NSWindow *window = _data->nswindow;
slouken@5371
   267
    NSView *view = [window contentView];
icculus@7534
   268
    NSArray *windows = nil;
slouken@1933
   269
slouken@1933
   270
    center = [NSNotificationCenter defaultCenter];
slouken@1933
   271
slouken@5374
   272
    if ([window delegate] != self) {
slouken@5374
   273
        [center removeObserver:self name:NSWindowDidExposeNotification object:window];
slouken@5374
   274
        [center removeObserver:self name:NSWindowDidMoveNotification object:window];
slouken@5374
   275
        [center removeObserver:self name:NSWindowDidResizeNotification object:window];
slouken@5374
   276
        [center removeObserver:self name:NSWindowDidMiniaturizeNotification object:window];
slouken@5374
   277
        [center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:window];
slouken@5374
   278
        [center removeObserver:self name:NSWindowDidBecomeKeyNotification object:window];
slouken@5374
   279
        [center removeObserver:self name:NSWindowDidResignKeyNotification object:window];
slouken@7952
   280
        [center removeObserver:self name:NSWindowWillEnterFullScreenNotification object:window];
slouken@7952
   281
        [center removeObserver:self name:NSWindowDidEnterFullScreenNotification object:window];
slouken@7952
   282
        [center removeObserver:self name:NSWindowWillExitFullScreenNotification object:window];
slouken@7952
   283
        [center removeObserver:self name:NSWindowDidExitFullScreenNotification object:window];
slouken@5374
   284
    } else {
slouken@5374
   285
        [window setDelegate:nil];
slouken@5374
   286
    }
slouken@5371
   287
slouken@7961
   288
    [window removeObserver:self forKeyPath:@"visible"];
jorgen@7084
   289
slouken@5374
   290
    if ([window nextResponder] == self) {
slouken@5374
   291
        [window setNextResponder:nil];
slouken@5374
   292
    }
slouken@5374
   293
    if ([view nextResponder] == self) {
slouken@5374
   294
        [view setNextResponder:nil];
slouken@5374
   295
    }
icculus@7534
   296
icculus@7534
   297
    /* Make the next window in the z-order Key. If we weren't the foreground
icculus@7535
   298
       when closed, this is a no-op.
icculus@7535
   299
       !!! FIXME: Note that this is a hack, and there are corner cases where
icculus@7535
   300
       !!! FIXME:  this fails (such as the About box). The typical nib+RunLoop
icculus@7535
   301
       !!! FIXME:  handles this for Cocoa apps, but we bypass all that in SDL.
icculus@7535
   302
       !!! FIXME:  We should remove this code when we find a better way to
icculus@7535
   303
       !!! FIXME:  have the system do this for us. See discussion in
icculus@7535
   304
       !!! FIXME:   http://bugzilla.libsdl.org/show_bug.cgi?id=1825
icculus@7535
   305
    */
icculus@7534
   306
    windows = [NSApp orderedWindows];
jorgen@8111
   307
    for (NSWindow *win in windows)
jorgen@8111
   308
    {
jorgen@8111
   309
        if (win == window) {
jorgen@8111
   310
            continue;
jorgen@8111
   311
        }
jorgen@8111
   312
icculus@7534
   313
        [win makeKeyAndOrderFront:self];
jorgen@8111
   314
        break;
icculus@7534
   315
    }
slouken@1933
   316
}
slouken@1933
   317
slouken@1933
   318
- (BOOL)windowShouldClose:(id)sender
slouken@1933
   319
{
slouken@3685
   320
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1933
   321
    return NO;
slouken@1933
   322
}
slouken@1933
   323
slouken@1933
   324
- (void)windowDidExpose:(NSNotification *)aNotification
slouken@1933
   325
{
slouken@3685
   326
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
slouken@1933
   327
}
slouken@1933
   328
slouken@1933
   329
- (void)windowDidMove:(NSNotification *)aNotification
slouken@1933
   330
{
slouken@1933
   331
    int x, y;
slouken@5398
   332
    SDL_Window *window = _data->window;
slouken@5398
   333
    NSWindow *nswindow = _data->nswindow;
slouken@5398
   334
    NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
slouken@1933
   335
    ConvertNSRect(&rect);
slouken@5398
   336
slouken@5398
   337
    if (s_moveHack) {
slouken@5398
   338
        SDL_bool blockMove = ((SDL_GetTicks() - s_moveHack) < 500);
slouken@5398
   339
slouken@5398
   340
        s_moveHack = 0;
slouken@5398
   341
slouken@5398
   342
        if (blockMove) {
slouken@5398
   343
            /* Cocoa is adjusting the window in response to a mode change */
slouken@5398
   344
            rect.origin.x = window->x;
slouken@5398
   345
            rect.origin.y = window->y;
slouken@5398
   346
            ConvertNSRect(&rect);
slouken@5398
   347
            [nswindow setFrameOrigin:rect.origin];
slouken@5398
   348
            return;
slouken@5398
   349
        }
slouken@5398
   350
    }
slouken@5398
   351
slouken@3507
   352
    x = (int)rect.origin.x;
slouken@3507
   353
    y = (int)rect.origin.y;
icculus@5564
   354
jorgen@7595
   355
    ScheduleContextUpdates(_data);
icculus@5564
   356
slouken@5398
   357
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1933
   358
}
slouken@1933
   359
slouken@1933
   360
- (void)windowDidResize:(NSNotification *)aNotification
slouken@1933
   361
{
slouken@7963
   362
    SDL_Window *window = _data->window;
slouken@7963
   363
    NSWindow *nswindow = _data->nswindow;
slouken@6231
   364
    int x, y, w, h;
slouken@7963
   365
    NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
slouken@6231
   366
    ConvertNSRect(&rect);
slouken@6231
   367
    x = (int)rect.origin.x;
slouken@6231
   368
    y = (int)rect.origin.y;
slouken@1933
   369
    w = (int)rect.size.width;
slouken@1933
   370
    h = (int)rect.size.height;
slouken@7952
   371
slouken@7952
   372
    if (inFullscreenTransition) {
slouken@7952
   373
        /* We'll take care of this at the end of the transition */
slouken@7952
   374
        return;
slouken@7952
   375
    }
slouken@7952
   376
slouken@7963
   377
    if (SDL_IsShapedWindow(window)) {
slouken@7963
   378
        Cocoa_ResizeWindowShape(window);
slouken@7952
   379
    }
icculus@5564
   380
jorgen@7595
   381
    ScheduleContextUpdates(_data);
icculus@5564
   382
slouken@6231
   383
    /* The window can move during a resize event, such as when maximizing
slouken@6231
   384
       or resizing from a corner */
slouken@7963
   385
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@7963
   386
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
icculus@7566
   387
slouken@7963
   388
    const BOOL zoomed = [nswindow isZoomed];
icculus@7566
   389
    if (!zoomed) {
slouken@7963
   390
        SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
icculus@7566
   391
    } else if (zoomed) {
slouken@7963
   392
        SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
icculus@7566
   393
    }
slouken@1933
   394
}
slouken@1933
   395
slouken@1933
   396
- (void)windowDidMiniaturize:(NSNotification *)aNotification
slouken@1933
   397
{
slouken@3685
   398
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@1933
   399
}
slouken@1933
   400
slouken@1933
   401
- (void)windowDidDeminiaturize:(NSNotification *)aNotification
slouken@1933
   402
{
slouken@3685
   403
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@1933
   404
}
slouken@1933
   405
slouken@1933
   406
- (void)windowDidBecomeKey:(NSNotification *)aNotification
slouken@1933
   407
{
slouken@5367
   408
    SDL_Window *window = _data->window;
jorgen@7271
   409
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@5367
   410
slouken@3688
   411
    /* We're going to get keyboard events, since we're key. */
slouken@5367
   412
    SDL_SetKeyboardFocus(window);
slouken@5367
   413
slouken@5367
   414
    /* If we just gained focus we need the updated mouse position */
jorgen@7271
   415
    if (!mouse->relative_mode) {
slouken@5367
   416
        NSPoint point;
slouken@5396
   417
        int x, y;
slouken@5396
   418
slouken@5396
   419
        point = [_data->nswindow mouseLocationOutsideOfEventStream];
slouken@5396
   420
        x = (int)point.x;
slouken@5396
   421
        y = (int)(window->h - point.y);
slouken@5396
   422
slouken@5396
   423
        if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
slouken@6950
   424
            SDL_SendMouseMotion(window, 0, 0, x, y);
slouken@5396
   425
        }
slouken@5367
   426
    }
slouken@1962
   427
slouken@4503
   428
    /* Check to see if someone updated the clipboard */
slouken@4503
   429
    Cocoa_CheckClipboardUpdate(_data->videodata);
slouken@1933
   430
}
slouken@1933
   431
slouken@1933
   432
- (void)windowDidResignKey:(NSNotification *)aNotification
slouken@1933
   433
{
slouken@2059
   434
    /* Some other window will get mouse events, since we're not key. */
slouken@4465
   435
    if (SDL_GetMouseFocus() == _data->window) {
slouken@4465
   436
        SDL_SetMouseFocus(NULL);
slouken@2059
   437
    }
slouken@2059
   438
slouken@2059
   439
    /* Some other window will get keyboard events, since we're not key. */
slouken@4465
   440
    if (SDL_GetKeyboardFocus() == _data->window) {
slouken@4465
   441
        SDL_SetKeyboardFocus(NULL);
slouken@4465
   442
    }
slouken@1933
   443
}
slouken@1933
   444
slouken@7952
   445
- (void)windowWillEnterFullScreen:(NSNotification *)aNotification
slouken@7952
   446
{
slouken@7952
   447
    SDL_Window *window = _data->window;
slouken@7952
   448
slouken@7968
   449
    window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
slouken@7990
   450
    SetWindowStyle(window, (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask));
slouken@7965
   451
slouken@7967
   452
    isFullscreenSpace = YES;
slouken@7952
   453
    inFullscreenTransition = YES;
slouken@7952
   454
}
slouken@7952
   455
slouken@7952
   456
- (void)windowDidEnterFullScreen:(NSNotification *)aNotification
slouken@7952
   457
{
slouken@7965
   458
    SDL_Window *window = _data->window;
slouken@7965
   459
slouken@7952
   460
    inFullscreenTransition = NO;
slouken@7961
   461
slouken@7963
   462
    if (pendingWindowOperation == PENDING_OPERATION_LEAVE_FULLSCREEN) {
slouken@7963
   463
        pendingWindowOperation = PENDING_OPERATION_NONE;
slouken@7967
   464
        [self setFullscreenSpace:NO];
slouken@7961
   465
    } else {
slouken@7963
   466
        pendingWindowOperation = PENDING_OPERATION_NONE;
slouken@7965
   467
        /* Force the size change event in case it was delivered earlier
slouken@7965
   468
           while the window was still animating into place.
slouken@7965
   469
         */
slouken@7965
   470
        window->w = 0;
slouken@7965
   471
        window->h = 0;
slouken@7961
   472
        [self windowDidResize:aNotification];
slouken@7961
   473
    }
slouken@7952
   474
}
slouken@7952
   475
slouken@7952
   476
- (void)windowWillExitFullScreen:(NSNotification *)aNotification
slouken@7952
   477
{
slouken@7964
   478
    SDL_Window *window = _data->window;
slouken@7964
   479
slouken@7968
   480
    window->flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP;
slouken@7990
   481
    SetWindowStyle(window, GetWindowStyle(window));
slouken@7964
   482
slouken@7967
   483
    isFullscreenSpace = NO;
slouken@7952
   484
    inFullscreenTransition = YES;
slouken@7952
   485
}
slouken@7952
   486
slouken@7952
   487
- (void)windowDidExitFullScreen:(NSNotification *)aNotification
slouken@7952
   488
{
slouken@7965
   489
    SDL_Window *window = _data->window;
slouken@7952
   490
    NSWindow *nswindow = _data->nswindow;
slouken@7952
   491
slouken@7952
   492
    inFullscreenTransition = NO;
slouken@7961
   493
slouken@7963
   494
    if (pendingWindowOperation == PENDING_OPERATION_ENTER_FULLSCREEN) {
slouken@7963
   495
        pendingWindowOperation = PENDING_OPERATION_NONE;
slouken@7967
   496
        [self setFullscreenSpace:YES];
slouken@7963
   497
    } else if (pendingWindowOperation == PENDING_OPERATION_MINIMIZE) {
slouken@7963
   498
        pendingWindowOperation = PENDING_OPERATION_NONE;
slouken@7963
   499
        [nswindow miniaturize:nil];
slouken@7961
   500
    } else {
slouken@7963
   501
        pendingWindowOperation = PENDING_OPERATION_NONE;
slouken@7965
   502
        /* Force the size change event in case it was delivered earlier
slouken@7965
   503
           while the window was still animating into place.
slouken@7965
   504
         */
slouken@7965
   505
        window->w = 0;
slouken@7965
   506
        window->h = 0;
slouken@7961
   507
        [self windowDidResize:aNotification];
slouken@7961
   508
    }
slouken@7952
   509
}
slouken@7952
   510
slouken@7191
   511
/* We'll respond to key events by doing nothing so we don't beep.
slouken@7191
   512
 * We could handle key messages here, but we lose some in the NSApp dispatch,
slouken@7191
   513
 * where they get converted to action messages, etc.
slouken@7191
   514
 */
slouken@6514
   515
- (void)flagsChanged:(NSEvent *)theEvent
slouken@6514
   516
{
slouken@7191
   517
    /*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
slouken@6514
   518
}
slouken@6514
   519
- (void)keyDown:(NSEvent *)theEvent
slouken@6514
   520
{
slouken@7191
   521
    /*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
slouken@6514
   522
}
slouken@6514
   523
- (void)keyUp:(NSEvent *)theEvent
slouken@6514
   524
{
slouken@7191
   525
    /*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
slouken@6514
   526
}
slouken@6514
   527
slouken@7191
   528
/* We'll respond to selectors by doing nothing so we don't beep.
slouken@7191
   529
 * The escape key gets converted to a "cancel" selector, etc.
slouken@7191
   530
 */
slouken@6514
   531
- (void)doCommandBySelector:(SEL)aSelector
slouken@6514
   532
{
slouken@7191
   533
    /*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/
slouken@6514
   534
}
slouken@6514
   535
slouken@1933
   536
- (void)mouseDown:(NSEvent *)theEvent
slouken@1933
   537
{
slouken@1959
   538
    int button;
slouken@1933
   539
slouken@1959
   540
    switch ([theEvent buttonNumber]) {
slouken@1959
   541
    case 0:
slouken@7915
   542
        if (([theEvent modifierFlags] & NSControlKeyMask) &&
slouken@7915
   543
		    GetHintCtrlClickEmulateRightClick()) {
slouken@7740
   544
            wasCtrlLeft = YES;
slouken@7740
   545
            button = SDL_BUTTON_RIGHT;
slouken@7740
   546
        } else {
slouken@7740
   547
            wasCtrlLeft = NO;
slouken@7740
   548
            button = SDL_BUTTON_LEFT;
slouken@7740
   549
        }
slouken@1959
   550
        break;
slouken@1959
   551
    case 1:
slouken@1959
   552
        button = SDL_BUTTON_RIGHT;
slouken@1959
   553
        break;
slouken@1959
   554
    case 2:
slouken@1959
   555
        button = SDL_BUTTON_MIDDLE;
slouken@1959
   556
        break;
slouken@1959
   557
    default:
slouken@5061
   558
        button = [theEvent buttonNumber] + 1;
slouken@1959
   559
        break;
slouken@1959
   560
    }
slouken@6950
   561
    SDL_SendMouseButton(_data->window, 0, SDL_PRESSED, button);
slouken@1933
   562
}
slouken@1933
   563
slouken@1933
   564
- (void)rightMouseDown:(NSEvent *)theEvent
slouken@1933
   565
{
slouken@1959
   566
    [self mouseDown:theEvent];
slouken@1933
   567
}
slouken@1933
   568
slouken@1933
   569
- (void)otherMouseDown:(NSEvent *)theEvent
slouken@1933
   570
{
slouken@1959
   571
    [self mouseDown:theEvent];
slouken@1933
   572
}
slouken@1933
   573
slouken@1933
   574
- (void)mouseUp:(NSEvent *)theEvent
slouken@1933
   575
{
slouken@1959
   576
    int button;
slouken@1933
   577
slouken@1959
   578
    switch ([theEvent buttonNumber]) {
slouken@1959
   579
    case 0:
slouken@7740
   580
        if (wasCtrlLeft) {
slouken@7740
   581
            button = SDL_BUTTON_RIGHT;
slouken@7740
   582
            wasCtrlLeft = NO;
slouken@7740
   583
        } else {
slouken@7740
   584
            button = SDL_BUTTON_LEFT;
slouken@7740
   585
        }
slouken@1959
   586
        break;
slouken@1959
   587
    case 1:
slouken@1959
   588
        button = SDL_BUTTON_RIGHT;
slouken@1959
   589
        break;
slouken@1959
   590
    case 2:
slouken@1959
   591
        button = SDL_BUTTON_MIDDLE;
slouken@1959
   592
        break;
slouken@1959
   593
    default:
slouken@5061
   594
        button = [theEvent buttonNumber] + 1;
slouken@1959
   595
        break;
slouken@1959
   596
    }
slouken@6950
   597
    SDL_SendMouseButton(_data->window, 0, SDL_RELEASED, button);
slouken@1933
   598
}
slouken@1933
   599
slouken@1933
   600
- (void)rightMouseUp:(NSEvent *)theEvent
slouken@1933
   601
{
slouken@1959
   602
    [self mouseUp:theEvent];
slouken@1933
   603
}
slouken@1933
   604
slouken@1933
   605
- (void)otherMouseUp:(NSEvent *)theEvent
slouken@1933
   606
{
slouken@1959
   607
    [self mouseUp:theEvent];
slouken@1933
   608
}
slouken@1933
   609
slouken@1933
   610
- (void)mouseMoved:(NSEvent *)theEvent
slouken@1933
   611
{
slouken@5406
   612
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@3685
   613
    SDL_Window *window = _data->window;
slouken@5396
   614
    NSPoint point;
slouken@5396
   615
    int x, y;
slouken@1933
   616
slouken@5406
   617
    if (mouse->relative_mode) {
gzjjgod@5059
   618
        return;
slouken@5371
   619
    }
gzjjgod@5059
   620
slouken@5396
   621
    point = [theEvent locationInWindow];
slouken@5396
   622
    x = (int)point.x;
slouken@5396
   623
    y = (int)(window->h - point.y);
slouken@5371
   624
slouken@5396
   625
    if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
slouken@6666
   626
        if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@6666
   627
            CGPoint cgpoint;
slouken@6666
   628
slouken@6666
   629
            if (x < 0) {
slouken@6666
   630
                x = 0;
slouken@6666
   631
            } else if (x >= window->w) {
slouken@6666
   632
                x = window->w - 1;
slouken@6666
   633
            }
slouken@6666
   634
            if (y < 0) {
slouken@6666
   635
                y = 0;
slouken@6666
   636
            } else if (y >= window->h) {
slouken@6666
   637
                y = window->h - 1;
slouken@6666
   638
            }
slouken@6666
   639
jorgen@7593
   640
#if !SDL_MAC_NO_SANDBOX
jorgen@7593
   641
            /* When SDL_MAC_NO_SANDBOX is set, this is handled by
jorgen@7593
   642
             * SDL_cocoamousetap.m.
jorgen@7593
   643
             */
jorgen@7593
   644
slouken@6666
   645
            cgpoint.x = window->x + x;
slouken@6666
   646
            cgpoint.y = window->y + y;
jorgen@7098
   647
jorgen@7113
   648
            /* According to the docs, this was deprecated in 10.6, but it's still
jorgen@7113
   649
             * around. The substitute requires a CGEventSource, but I'm not entirely
jorgen@7113
   650
             * sure how we'd procure the right one for this event.
jorgen@7098
   651
             */
jorgen@7113
   652
            CGSetLocalEventsSuppressionInterval(0.0);
slouken@6666
   653
            CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
jorgen@7113
   654
            CGSetLocalEventsSuppressionInterval(0.25);
jorgen@7593
   655
#endif
slouken@5396
   656
        }
slouken@2059
   657
    }
slouken@6950
   658
    SDL_SendMouseMotion(window, 0, 0, x, y);
slouken@1933
   659
}
slouken@1933
   660
slouken@1957
   661
- (void)mouseDragged:(NSEvent *)theEvent
slouken@1957
   662
{
slouken@1957
   663
    [self mouseMoved:theEvent];
slouken@1957
   664
}
slouken@1957
   665
slouken@1958
   666
- (void)rightMouseDragged:(NSEvent *)theEvent
slouken@1958
   667
{
slouken@1958
   668
    [self mouseMoved:theEvent];
slouken@1958
   669
}
slouken@1958
   670
slouken@1958
   671
- (void)otherMouseDragged:(NSEvent *)theEvent
slouken@1958
   672
{
slouken@1958
   673
    [self mouseMoved:theEvent];
slouken@1958
   674
}
slouken@1958
   675
slouken@1933
   676
- (void)scrollWheel:(NSEvent *)theEvent
slouken@1933
   677
{
gzjjgod@5057
   678
    Cocoa_HandleMouseWheel(_data->window, theEvent);
slouken@3688
   679
}
slouken@3688
   680
slouken@4673
   681
- (void)touchesBeganWithEvent:(NSEvent *) theEvent
slouken@4673
   682
{
slouken@4673
   683
    [self handleTouches:COCOA_TOUCH_DOWN withEvent:theEvent];
slouken@4673
   684
}
slouken@4673
   685
slouken@4673
   686
- (void)touchesMovedWithEvent:(NSEvent *) theEvent
slouken@4673
   687
{
slouken@4673
   688
    [self handleTouches:COCOA_TOUCH_MOVE withEvent:theEvent];
slouken@4673
   689
}
slouken@4673
   690
slouken@4673
   691
- (void)touchesEndedWithEvent:(NSEvent *) theEvent
slouken@4673
   692
{
slouken@4673
   693
    [self handleTouches:COCOA_TOUCH_UP withEvent:theEvent];
slouken@4673
   694
}
slouken@4673
   695
slouken@4673
   696
- (void)touchesCancelledWithEvent:(NSEvent *) theEvent
slouken@4673
   697
{
slouken@4673
   698
    [self handleTouches:COCOA_TOUCH_CANCELLED withEvent:theEvent];
slouken@4673
   699
}
slouken@4673
   700
slouken@4673
   701
- (void)handleTouches:(cocoaTouchType)type withEvent:(NSEvent *)event
slouken@4673
   702
{
slouken@4680
   703
    NSSet *touches = 0;
slouken@4680
   704
    NSEnumerator *enumerator;
slouken@4680
   705
    NSTouch *touch;
slouken@4673
   706
slouken@4680
   707
    switch (type) {
slouken@4680
   708
        case COCOA_TOUCH_DOWN:
slouken@4680
   709
            touches = [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil];
slouken@4680
   710
            break;
slouken@4680
   711
        case COCOA_TOUCH_UP:
jorgen@8106
   712
            touches = [event touchesMatchingPhase:NSTouchPhaseEnded inView:nil];
jorgen@8106
   713
            break;
slouken@4680
   714
        case COCOA_TOUCH_CANCELLED:
jorgen@8106
   715
            touches = [event touchesMatchingPhase:NSTouchPhaseCancelled inView:nil];
slouken@4680
   716
            break;
slouken@4680
   717
        case COCOA_TOUCH_MOVE:
slouken@4680
   718
            touches = [event touchesMatchingPhase:NSTouchPhaseMoved inView:nil];
slouken@4680
   719
            break;
slouken@4680
   720
    }
slouken@4680
   721
slouken@4680
   722
    enumerator = [touches objectEnumerator];
slouken@4680
   723
    touch = (NSTouch*)[enumerator nextObject];
slouken@4673
   724
    while (touch) {
slouken@6953
   725
        const SDL_TouchID touchId = (SDL_TouchID)(intptr_t)[touch device];
slouken@4673
   726
        if (!SDL_GetTouch(touchId)) {
slouken@6951
   727
            if (SDL_AddTouch(touchId, "") < 0) {
slouken@4680
   728
                return;
slouken@4673
   729
            }
slouken@7191
   730
        }
slouken@4687
   731
slouken@6953
   732
        const SDL_FingerID fingerId = (SDL_FingerID)(intptr_t)[touch identity];
slouken@4673
   733
        float x = [touch normalizedPosition].x;
slouken@4673
   734
        float y = [touch normalizedPosition].y;
slouken@5261
   735
        /* Make the origin the upper left instead of the lower left */
slouken@5261
   736
        y = 1.0f - y;
slouken@4687
   737
slouken@4673
   738
        switch (type) {
slouken@4673
   739
        case COCOA_TOUCH_DOWN:
slouken@6951
   740
            SDL_SendTouch(touchId, fingerId, SDL_TRUE, x, y, 1.0f);
slouken@4673
   741
            break;
slouken@4673
   742
        case COCOA_TOUCH_UP:
slouken@4673
   743
        case COCOA_TOUCH_CANCELLED:
slouken@6951
   744
            SDL_SendTouch(touchId, fingerId, SDL_FALSE, x, y, 1.0f);
slouken@4673
   745
            break;
slouken@4673
   746
        case COCOA_TOUCH_MOVE:
slouken@6951
   747
            SDL_SendTouchMotion(touchId, fingerId, x, y, 1.0f);
slouken@4673
   748
            break;
slouken@4673
   749
        }
slouken@6951
   750
slouken@4673
   751
        touch = (NSTouch*)[enumerator nextObject];
slouken@4673
   752
    }
slouken@1933
   753
}
slouken@1933
   754
slouken@1933
   755
@end
slouken@1933
   756
slouken@1973
   757
@interface SDLWindow : NSWindow
slouken@1973
   758
/* These are needed for borderless/fullscreen windows */
slouken@1973
   759
- (BOOL)canBecomeKeyWindow;
slouken@1973
   760
- (BOOL)canBecomeMainWindow;
slouken@1973
   761
@end
slouken@1973
   762
slouken@1973
   763
@implementation SDLWindow
slouken@1973
   764
- (BOOL)canBecomeKeyWindow
slouken@1973
   765
{
slouken@1973
   766
    return YES;
slouken@1973
   767
}
slouken@1973
   768
slouken@1973
   769
- (BOOL)canBecomeMainWindow
slouken@1973
   770
{
slouken@1973
   771
    return YES;
slouken@1973
   772
}
slouken@1973
   773
@end
slouken@1973
   774
slouken@5379
   775
@interface SDLView : NSView
jorgen@7158
   776
slouken@5379
   777
/* The default implementation doesn't pass rightMouseDown to responder chain */
slouken@5379
   778
- (void)rightMouseDown:(NSEvent *)theEvent;
gzjjgod@4915
   779
@end
gzjjgod@4915
   780
gzjjgod@4915
   781
@implementation SDLView
gzjjgod@4915
   782
- (void)rightMouseDown:(NSEvent *)theEvent
gzjjgod@4915
   783
{
slouken@5371
   784
    [[self nextResponder] rightMouseDown:theEvent];
gzjjgod@4915
   785
}
jorgen@7158
   786
jorgen@7158
   787
- (void)resetCursorRects
jorgen@7158
   788
{
jorgen@7158
   789
    [super resetCursorRects];
jorgen@7158
   790
    SDL_Mouse *mouse = SDL_GetMouse();
jorgen@7158
   791
jorgen@7270
   792
    if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
jorgen@7158
   793
        [self addCursorRect:[self bounds]
jorgen@7158
   794
                     cursor:mouse->cur_cursor->driverdata];
jorgen@7158
   795
    } else {
jorgen@7158
   796
        [self addCursorRect:[self bounds]
jorgen@7158
   797
                     cursor:[NSCursor invisibleCursor]];
jorgen@7158
   798
    }
jorgen@7158
   799
}
gzjjgod@4915
   800
@end
gzjjgod@4915
   801
slouken@1933
   802
static int
slouken@1951
   803
SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
slouken@1933
   804
{
slouken@6848
   805
    NSAutoreleasePool *pool;
slouken@1951
   806
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@1933
   807
    SDL_WindowData *data;
slouken@1933
   808
slouken@1933
   809
    /* Allocate the window data */
slouken@5249
   810
    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
slouken@1933
   811
    if (!data) {
icculus@7037
   812
        return SDL_OutOfMemory();
slouken@1933
   813
    }
slouken@3685
   814
    data->window = window;
slouken@3688
   815
    data->nswindow = nswindow;
slouken@1933
   816
    data->created = created;
slouken@1951
   817
    data->videodata = videodata;
jorgen@7595
   818
    data->nscontexts = [[NSMutableArray alloc] init];
slouken@1933
   819
slouken@6848
   820
    pool = [[NSAutoreleasePool alloc] init];
slouken@1933
   821
slouken@6848
   822
    /* Create an event listener for the window */
slouken@6848
   823
    data->listener = [[Cocoa_WindowListener alloc] init];
slouken@6848
   824
slouken@6848
   825
    /* Fill in the SDL window with the window data */
slouken@6848
   826
    {
slouken@6848
   827
        NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
slouken@6848
   828
        ConvertNSRect(&rect);
slouken@6848
   829
        window->x = (int)rect.origin.x;
slouken@6848
   830
        window->y = (int)rect.origin.y;
slouken@6848
   831
        window->w = (int)rect.size.width;
slouken@6848
   832
        window->h = (int)rect.size.height;
slouken@6848
   833
    }
slouken@6848
   834
slouken@6848
   835
    /* Set up the listener after we create the view */
slouken@6848
   836
    [data->listener listen:data];
slouken@6848
   837
slouken@6848
   838
    if ([nswindow isVisible]) {
slouken@6848
   839
        window->flags |= SDL_WINDOW_SHOWN;
slouken@6848
   840
    } else {
slouken@6848
   841
        window->flags &= ~SDL_WINDOW_SHOWN;
slouken@6848
   842
    }
jorgen@7084
   843
slouken@6848
   844
    {
slouken@6848
   845
        unsigned int style = [nswindow styleMask];
slouken@6848
   846
slouken@6848
   847
        if (style == NSBorderlessWindowMask) {
slouken@6848
   848
            window->flags |= SDL_WINDOW_BORDERLESS;
slouken@6848
   849
        } else {
slouken@6848
   850
            window->flags &= ~SDL_WINDOW_BORDERLESS;
alexey@6832
   851
        }
slouken@6848
   852
        if (style & NSResizableWindowMask) {
slouken@6848
   853
            window->flags |= SDL_WINDOW_RESIZABLE;
slouken@6848
   854
        } else {
slouken@6848
   855
            window->flags &= ~SDL_WINDOW_RESIZABLE;
slouken@6848
   856
        }
slouken@6848
   857
    }
jorgen@7084
   858
slouken@6848
   859
    /* isZoomed always returns true if the window is not resizable */
slouken@6848
   860
    if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
slouken@6848
   861
        window->flags |= SDL_WINDOW_MAXIMIZED;
slouken@6848
   862
    } else {
slouken@6848
   863
        window->flags &= ~SDL_WINDOW_MAXIMIZED;
slouken@6848
   864
    }
jorgen@7084
   865
slouken@6848
   866
    if ([nswindow isMiniaturized]) {
slouken@6848
   867
        window->flags |= SDL_WINDOW_MINIMIZED;
slouken@6848
   868
    } else {
slouken@6848
   869
        window->flags &= ~SDL_WINDOW_MINIMIZED;
slouken@6848
   870
    }
jorgen@7084
   871
slouken@6848
   872
    if ([nswindow isKeyWindow]) {
slouken@6848
   873
        window->flags |= SDL_WINDOW_INPUT_FOCUS;
slouken@6848
   874
        SDL_SetKeyboardFocus(data->window);
slouken@6848
   875
    }
slouken@1933
   876
jorgen@7085
   877
    /* Prevents the window's "window device" from being destroyed when it is
jorgen@7085
   878
     * hidden. See http://www.mikeash.com/pyblog/nsopenglcontext-and-one-shot.html
jorgen@7085
   879
     */
jorgen@7085
   880
    [nswindow setOneShot:NO];
jorgen@7085
   881
slouken@6848
   882
    /* All done! */
slouken@6848
   883
    [pool release];
slouken@6848
   884
    window->driverdata = data;
slouken@6848
   885
    return 0;
slouken@1933
   886
}
slouken@1933
   887
slouken@1933
   888
int
slouken@1933
   889
Cocoa_CreateWindow(_THIS, SDL_Window * window)
slouken@1933
   890
{
slouken@6848
   891
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   892
    NSWindow *nswindow;
slouken@6848
   893
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@6848
   894
    NSRect rect;
slouken@6848
   895
    SDL_Rect bounds;
slouken@6848
   896
    unsigned int style;
slouken@1933
   897
slouken@6848
   898
    Cocoa_GetDisplayBounds(_this, display, &bounds);
slouken@6848
   899
    rect.origin.x = window->x;
slouken@6848
   900
    rect.origin.y = window->y;
slouken@6848
   901
    rect.size.width = window->w;
slouken@6848
   902
    rect.size.height = window->h;
slouken@6848
   903
    ConvertNSRect(&rect);
slouken@1933
   904
slouken@6848
   905
    style = GetWindowStyle(window);
slouken@1933
   906
slouken@6848
   907
    /* Figure out which screen to place this window */
slouken@6848
   908
    NSArray *screens = [NSScreen screens];
slouken@6848
   909
    NSScreen *screen = nil;
slouken@6848
   910
    NSScreen *candidate;
slouken@6848
   911
    int i, count = [screens count];
slouken@6848
   912
    for (i = 0; i < count; ++i) {
slouken@6848
   913
        candidate = [screens objectAtIndex:i];
slouken@6848
   914
        NSRect screenRect = [candidate frame];
slouken@6848
   915
        if (rect.origin.x >= screenRect.origin.x &&
slouken@6848
   916
            rect.origin.x < screenRect.origin.x + screenRect.size.width &&
slouken@6848
   917
            rect.origin.y >= screenRect.origin.y &&
slouken@6848
   918
            rect.origin.y < screenRect.origin.y + screenRect.size.height) {
slouken@6848
   919
            screen = candidate;
slouken@6848
   920
            rect.origin.x -= screenRect.origin.x;
slouken@6848
   921
            rect.origin.y -= screenRect.origin.y;
slouken@3506
   922
        }
slouken@6848
   923
    }
slouken@7946
   924
slouken@7946
   925
    @try {
slouken@7946
   926
        nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:NO screen:screen];
slouken@7946
   927
    }
slouken@7946
   928
    @catch (NSException *e) {
slouken@7946
   929
        SDL_SetError("%s", [[e reason] UTF8String]);
slouken@7948
   930
        [pool release];
slouken@7946
   931
        return -1;
slouken@7946
   932
    }
icculus@7205
   933
    [nswindow setBackgroundColor:[NSColor blackColor]];
slouken@7955
   934
    if ([nswindow respondsToSelector:@selector(setCollectionBehavior:)]) {
slouken@7968
   935
        const char *hint = SDL_GetHint(SDL_HINT_VIDEO_FULLSCREEN_SPACES);
slouken@7968
   936
        if (hint && SDL_atoi(hint) > 0) {
slouken@7968
   937
            [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
slouken@7968
   938
        }
slouken@7955
   939
    }
alexey@6832
   940
slouken@7191
   941
    /* Create a default view for this window */
slouken@6848
   942
    rect = [nswindow contentRectForFrameRect:[nswindow frame]];
slouken@6848
   943
    NSView *contentView = [[SDLView alloc] initWithFrame:rect];
urkle@7746
   944
slouken@7955
   945
    if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
urkle@7746
   946
        if ([contentView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
urkle@7746
   947
            [contentView setWantsBestResolutionOpenGLSurface:YES];
urkle@7746
   948
        }
urkle@7746
   949
    }
urkle@7746
   950
slouken@6848
   951
    [nswindow setContentView: contentView];
slouken@6848
   952
    [contentView release];
alexey@6832
   953
slouken@6848
   954
    [pool release];
slouken@6848
   955
slouken@6848
   956
    if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
slouken@6848
   957
        [nswindow release];
slouken@6848
   958
        return -1;
slouken@3506
   959
    }
slouken@6848
   960
    return 0;
slouken@1933
   961
}
slouken@1933
   962
slouken@1933
   963
int
slouken@1933
   964
Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@1933
   965
{
slouken@6848
   966
    NSAutoreleasePool *pool;
slouken@1933
   967
    NSWindow *nswindow = (NSWindow *) data;
slouken@1933
   968
    NSString *title;
slouken@1933
   969
slouken@6848
   970
    pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   971
slouken@6848
   972
    /* Query the title from the existing window */
slouken@6848
   973
    title = [nswindow title];
slouken@6848
   974
    if (title) {
slouken@6848
   975
        window->title = SDL_strdup([title UTF8String]);
slouken@1933
   976
    }
slouken@1933
   977
slouken@6848
   978
    [pool release];
slouken@6848
   979
slouken@1951
   980
    return SetupWindowData(_this, window, nswindow, SDL_FALSE);
slouken@1933
   981
}
slouken@1933
   982
slouken@1933
   983
void
slouken@1933
   984
Cocoa_SetWindowTitle(_THIS, SDL_Window * window)
slouken@1933
   985
{
slouken@6848
   986
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   987
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@6848
   988
    NSString *string;
slouken@1933
   989
slouken@6848
   990
    if(window->title) {
slouken@6848
   991
        string = [[NSString alloc] initWithUTF8String:window->title];
slouken@6848
   992
    } else {
slouken@6848
   993
        string = [[NSString alloc] init];
slouken@1956
   994
    }
slouken@6848
   995
    [nswindow setTitle:string];
slouken@6848
   996
    [string release];
slouken@6848
   997
slouken@6848
   998
    [pool release];
slouken@1933
   999
}
slouken@1933
  1000
slouken@1933
  1001
void
slouken@5375
  1002
Cocoa_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
slouken@5375
  1003
{
slouken@6848
  1004
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
  1005
    NSImage *nsimage = Cocoa_CreateImage(icon);
slouken@5375
  1006
slouken@6848
  1007
    if (nsimage) {
slouken@6848
  1008
        [NSApp setApplicationIconImage:nsimage];
slouken@5375
  1009
    }
slouken@6848
  1010
slouken@6848
  1011
    [pool release];
slouken@5375
  1012
}
slouken@5375
  1013
slouken@5375
  1014
void
slouken@1933
  1015
Cocoa_SetWindowPosition(_THIS, SDL_Window * window)
slouken@1933
  1016
{
slouken@6848
  1017
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
jorgen@7594
  1018
    SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
jorgen@7594
  1019
    NSWindow *nswindow = windata->nswindow;
slouken@6848
  1020
    NSRect rect;
slouken@6848
  1021
    Uint32 moveHack;
slouken@1933
  1022
slouken@6848
  1023
    rect.origin.x = window->x;
slouken@6848
  1024
    rect.origin.y = window->y;
slouken@6848
  1025
    rect.size.width = window->w;
slouken@6848
  1026
    rect.size.height = window->h;
slouken@6848
  1027
    ConvertNSRect(&rect);
slouken@5478
  1028
slouken@6848
  1029
    moveHack = s_moveHack;
slouken@6848
  1030
    s_moveHack = 0;
slouken@6848
  1031
    [nswindow setFrameOrigin:rect.origin];
slouken@6848
  1032
    s_moveHack = moveHack;
slouken@5478
  1033
jorgen@7595
  1034
    ScheduleContextUpdates(windata);
slouken@6848
  1035
slouken@6848
  1036
    [pool release];
slouken@1933
  1037
}
slouken@1933
  1038
slouken@1933
  1039
void
slouken@1933
  1040
Cocoa_SetWindowSize(_THIS, SDL_Window * window)
slouken@1933
  1041
{
slouken@6848
  1042
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
  1043
    SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
slouken@6848
  1044
    NSWindow *nswindow = windata->nswindow;
slouken@6848
  1045
    NSSize size;
slouken@1933
  1046
slouken@6848
  1047
    size.width = window->w;
slouken@6848
  1048
    size.height = window->h;
slouken@6848
  1049
    [nswindow setContentSize:size];
icculus@5564
  1050
jorgen@7595
  1051
    ScheduleContextUpdates(windata);
slouken@6848
  1052
slouken@6848
  1053
    [pool release];
slouken@1933
  1054
}
slouken@1933
  1055
slouken@1933
  1056
void
stopiccot@6681
  1057
Cocoa_SetWindowMinimumSize(_THIS, SDL_Window * window)
stopiccot@6681
  1058
{
slouken@6848
  1059
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
  1060
    SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
slouken@7191
  1061
slouken@6848
  1062
    NSSize minSize;
slouken@6848
  1063
    minSize.width = window->min_w;
slouken@6848
  1064
    minSize.height = window->min_h;
slouken@7191
  1065
slouken@6848
  1066
    [windata->nswindow setContentMinSize:minSize];
slouken@7191
  1067
slouken@6848
  1068
    [pool release];
slouken@6788
  1069
}
slouken@6788
  1070
slouken@6788
  1071
void
slouken@6788
  1072
Cocoa_SetWindowMaximumSize(_THIS, SDL_Window * window)
slouken@6788
  1073
{
slouken@6848
  1074
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
  1075
    SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
slouken@7191
  1076
slouken@6848
  1077
    NSSize maxSize;
slouken@6848
  1078
    maxSize.width = window->max_w;
slouken@6848
  1079
    maxSize.height = window->max_h;
slouken@7191
  1080
slouken@6848
  1081
    [windata->nswindow setContentMaxSize:maxSize];
slouken@7191
  1082
slouken@6848
  1083
    [pool release];
stopiccot@6681
  1084
}
stopiccot@6681
  1085
stopiccot@6681
  1086
void
slouken@1933
  1087
Cocoa_ShowWindow(_THIS, SDL_Window * window)
slouken@1933
  1088
{
slouken@6848
  1089
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
jorgen@7087
  1090
    SDL_WindowData *windowData = ((SDL_WindowData *) window->driverdata);
jorgen@7087
  1091
    NSWindow *nswindow = windowData->nswindow;
slouken@1933
  1092
slouken@6848
  1093
    if (![nswindow isMiniaturized]) {
jorgen@7087
  1094
        [windowData->listener pauseVisibleObservation];
slouken@6848
  1095
        [nswindow makeKeyAndOrderFront:nil];
jorgen@7087
  1096
        [windowData->listener resumeVisibleObservation];
slouken@1956
  1097
    }
slouken@6848
  1098
    [pool release];
slouken@1933
  1099
}
slouken@1933
  1100
slouken@1933
  1101
void
slouken@1933
  1102
Cocoa_HideWindow(_THIS, SDL_Window * window)
slouken@1933
  1103
{
slouken@6848
  1104
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
  1105
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@6848
  1106
slouken@6848
  1107
    [nswindow orderOut:nil];
slouken@6848
  1108
    [pool release];
slouken@1933
  1109
}
slouken@1933
  1110
slouken@1933
  1111
void
slouken@1933
  1112
Cocoa_RaiseWindow(_THIS, SDL_Window * window)
slouken@1933
  1113
{
slouken@6848
  1114
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
jorgen@7087
  1115
    SDL_WindowData *windowData = ((SDL_WindowData *) window->driverdata);
jorgen@7087
  1116
    NSWindow *nswindow = windowData->nswindow;
slouken@6848
  1117
slouken@7771
  1118
    /* makeKeyAndOrderFront: has the side-effect of deminiaturizing and showing
slouken@7771
  1119
       a minimized or hidden window, so check for that before showing it.
slouken@7771
  1120
     */
jorgen@7087
  1121
    [windowData->listener pauseVisibleObservation];
jorgen@7469
  1122
    if (![nswindow isMiniaturized] && [nswindow isVisible]) {
jorgen@7469
  1123
        [nswindow makeKeyAndOrderFront:nil];
jorgen@7469
  1124
    }
jorgen@7087
  1125
    [windowData->listener resumeVisibleObservation];
jorgen@7087
  1126
slouken@6848
  1127
    [pool release];
slouken@1933
  1128
}
slouken@1933
  1129
slouken@1933
  1130
void
slouken@1933
  1131
Cocoa_MaximizeWindow(_THIS, SDL_Window * window)
slouken@1933
  1132
{
slouken@6848
  1133
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
jorgen@7594
  1134
    SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
jorgen@7594
  1135
    NSWindow *nswindow = windata->nswindow;
slouken@1933
  1136
slouken@6848
  1137
    [nswindow zoom:nil];
slouken@6848
  1138
jorgen@7595
  1139
    ScheduleContextUpdates(windata);
slouken@6848
  1140
slouken@6848
  1141
    [pool release];
slouken@1933
  1142
}
slouken@1933
  1143
slouken@1933
  1144
void
slouken@1933
  1145
Cocoa_MinimizeWindow(_THIS, SDL_Window * window)
slouken@1933
  1146
{
slouken@6848
  1147
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@7963
  1148
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@7963
  1149
    NSWindow *nswindow = data->nswindow;
slouken@6848
  1150
slouken@7968
  1151
    if ([data->listener isInFullscreenSpaceTransition]) {
slouken@7963
  1152
        [data->listener addPendingWindowOperation:PENDING_OPERATION_MINIMIZE];
slouken@7963
  1153
    } else {
slouken@7963
  1154
        [nswindow miniaturize:nil];
slouken@7963
  1155
    }
slouken@6848
  1156
    [pool release];
slouken@1933
  1157
}
slouken@1933
  1158
slouken@1933
  1159
void
slouken@1933
  1160
Cocoa_RestoreWindow(_THIS, SDL_Window * window)
slouken@1933
  1161
{
slouken@6848
  1162
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
  1163
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
  1164
slouken@6848
  1165
    if ([nswindow isMiniaturized]) {
slouken@6848
  1166
        [nswindow deminiaturize:nil];
slouken@6848
  1167
    } else if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
slouken@6848
  1168
        [nswindow zoom:nil];
slouken@1956
  1169
    }
slouken@6848
  1170
    [pool release];
slouken@1933
  1171
}
slouken@1933
  1172
slouken@5400
  1173
static NSWindow *
slouken@5400
  1174
Cocoa_RebuildWindow(SDL_WindowData * data, NSWindow * nswindow, unsigned style)
slouken@5400
  1175
{
slouken@5400
  1176
    if (!data->created) {
slouken@5400
  1177
        /* Don't mess with other people's windows... */
slouken@5400
  1178
        return nswindow;
slouken@5400
  1179
    }
slouken@5400
  1180
slouken@5400
  1181
    [data->listener close];
jorgen@7085
  1182
    data->nswindow = [[SDLWindow alloc] initWithContentRect:[[nswindow contentView] frame] styleMask:style backing:NSBackingStoreBuffered defer:NO screen:[nswindow screen]];
slouken@5400
  1183
    [data->nswindow setContentView:[nswindow contentView]];
jorgen@7085
  1184
    /* See comment in SetupWindowData. */
jorgen@7085
  1185
    [data->nswindow setOneShot:NO];
slouken@5400
  1186
    [data->listener listen:data];
slouken@5400
  1187
slouken@5400
  1188
    [nswindow close];
slouken@5400
  1189
slouken@5400
  1190
    return data->nswindow;
slouken@5400
  1191
}
slouken@5400
  1192
slouken@1933
  1193
void
icculus@6422
  1194
Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
icculus@6422
  1195
{
slouken@6848
  1196
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@7990
  1197
    if (SetWindowStyle(window, GetWindowStyle(window))) {
slouken@6848
  1198
        if (bordered) {
slouken@7191
  1199
            Cocoa_SetWindowTitle(_this, window);  /* this got blanked out. */
icculus@6426
  1200
        }
icculus@6422
  1201
    }
slouken@6848
  1202
    [pool release];
icculus@6422
  1203
}
icculus@6422
  1204
slouken@7952
  1205
slouken@7968
  1206
void
slouken@7968
  1207
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
slouken@7952
  1208
{
slouken@7968
  1209
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
  1210
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@6848
  1211
    NSWindow *nswindow = data->nswindow;
slouken@6848
  1212
    NSRect rect;
slouken@5249
  1213
slouken@6848
  1214
    /* The view responder chain gets messed with during setStyleMask */
slouken@6848
  1215
    if ([[nswindow contentView] nextResponder] == data->listener) {
slouken@6848
  1216
        [[nswindow contentView] setNextResponder:nil];
slouken@6848
  1217
    }
slouken@6848
  1218
slouken@6848
  1219
    if (fullscreen) {
slouken@6848
  1220
        SDL_Rect bounds;
slouken@6848
  1221
slouken@6848
  1222
        Cocoa_GetDisplayBounds(_this, display, &bounds);
slouken@6848
  1223
        rect.origin.x = bounds.x;
slouken@6848
  1224
        rect.origin.y = bounds.y;
slouken@6848
  1225
        rect.size.width = bounds.w;
slouken@6848
  1226
        rect.size.height = bounds.h;
slouken@6848
  1227
        ConvertNSRect(&rect);
slouken@6848
  1228
slouken@6848
  1229
        /* Hack to fix origin on Mac OS X 10.4 */
slouken@6848
  1230
        NSRect screenRect = [[nswindow screen] frame];
slouken@6848
  1231
        if (screenRect.size.height >= 1.0f) {
slouken@6848
  1232
            rect.origin.y += (screenRect.size.height - rect.size.height);
slouken@5401
  1233
        }
slouken@5401
  1234
slouken@6848
  1235
        if ([nswindow respondsToSelector: @selector(setStyleMask:)]) {
slouken@6848
  1236
            [nswindow performSelector: @selector(setStyleMask:) withObject: (id)NSBorderlessWindowMask];
slouken@6848
  1237
        } else {
slouken@6848
  1238
            nswindow = Cocoa_RebuildWindow(data, nswindow, NSBorderlessWindowMask);
slouken@6848
  1239
        }
slouken@6848
  1240
    } else {
slouken@6848
  1241
        rect.origin.x = window->windowed.x;
slouken@6848
  1242
        rect.origin.y = window->windowed.y;
slouken@6848
  1243
        rect.size.width = window->windowed.w;
slouken@6848
  1244
        rect.size.height = window->windowed.h;
slouken@6848
  1245
        ConvertNSRect(&rect);
alexey@6832
  1246
slouken@6848
  1247
        if ([nswindow respondsToSelector: @selector(setStyleMask:)]) {
slouken@6848
  1248
            [nswindow performSelector: @selector(setStyleMask:) withObject: (id)(uintptr_t)GetWindowStyle(window)];
slouken@5400
  1249
        } else {
slouken@6848
  1250
            nswindow = Cocoa_RebuildWindow(data, nswindow, GetWindowStyle(window));
slouken@5361
  1251
        }
slouken@5398
  1252
    }
slouken@6848
  1253
slouken@6848
  1254
    /* The view responder chain gets messed with during setStyleMask */
slouken@6848
  1255
    if ([[nswindow contentView] nextResponder] != data->listener) {
slouken@6848
  1256
        [[nswindow contentView] setNextResponder:data->listener];
slouken@6848
  1257
    }
slouken@6848
  1258
slouken@6848
  1259
    s_moveHack = 0;
slouken@7873
  1260
    [nswindow setContentSize:rect.size];
slouken@6848
  1261
    [nswindow setFrameOrigin:rect.origin];
slouken@6848
  1262
    s_moveHack = SDL_GetTicks();
slouken@6848
  1263
slouken@6848
  1264
    /* When the window style changes the title is cleared */
slouken@6848
  1265
    if (!fullscreen) {
slouken@6848
  1266
        Cocoa_SetWindowTitle(_this, window);
slouken@6848
  1267
    }
slouken@6848
  1268
slouken@6848
  1269
    if (SDL_ShouldAllowTopmost() && fullscreen) {
slouken@6848
  1270
        /* OpenGL is rendering to the window, so make it visible! */
slouken@6848
  1271
        [nswindow setLevel:CGShieldingWindowLevel()];
slouken@6848
  1272
    } else {
slouken@6848
  1273
        [nswindow setLevel:kCGNormalWindowLevel];
slouken@6848
  1274
    }
jorgen@7087
  1275
jorgen@7636
  1276
    if ([nswindow isVisible] || fullscreen) {
jorgen@7636
  1277
        [data->listener pauseVisibleObservation];
jorgen@7636
  1278
        [nswindow makeKeyAndOrderFront:nil];
jorgen@7636
  1279
        [data->listener resumeVisibleObservation];
jorgen@7636
  1280
    }
slouken@6848
  1281
jorgen@7595
  1282
    ScheduleContextUpdates(data);
slouken@6848
  1283
slouken@6848
  1284
    [pool release];
slouken@5249
  1285
}
slouken@5249
  1286
slouken@5466
  1287
int
slouken@5466
  1288
Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
slouken@5466
  1289
{
slouken@5466
  1290
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5466
  1291
    CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
slouken@5466
  1292
    const uint32_t tableSize = 256;
slouken@5466
  1293
    CGGammaValue redTable[tableSize];
slouken@5466
  1294
    CGGammaValue greenTable[tableSize];
slouken@5466
  1295
    CGGammaValue blueTable[tableSize];
slouken@5466
  1296
    uint32_t i;
slouken@5466
  1297
    float inv65535 = 1.0f / 65535.0f;
slouken@5466
  1298
slouken@5466
  1299
    /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
slouken@5466
  1300
    for (i = 0; i < 256; i++) {
slouken@5466
  1301
        redTable[i] = ramp[0*256+i] * inv65535;
slouken@5466
  1302
        greenTable[i] = ramp[1*256+i] * inv65535;
slouken@5466
  1303
        blueTable[i] = ramp[2*256+i] * inv65535;
slouken@5466
  1304
    }
slouken@5466
  1305
slouken@5466
  1306
    if (CGSetDisplayTransferByTable(display_id, tableSize,
slouken@5466
  1307
                                    redTable, greenTable, blueTable) != CGDisplayNoErr) {
icculus@7037
  1308
        return SDL_SetError("CGSetDisplayTransferByTable()");
slouken@5466
  1309
    }
slouken@5466
  1310
    return 0;
slouken@5466
  1311
}
slouken@5466
  1312
slouken@5466
  1313
int
slouken@5466
  1314
Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
slouken@5466
  1315
{
slouken@5466
  1316
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5466
  1317
    CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
slouken@5466
  1318
    const uint32_t tableSize = 256;
slouken@5466
  1319
    CGGammaValue redTable[tableSize];
slouken@5466
  1320
    CGGammaValue greenTable[tableSize];
slouken@5466
  1321
    CGGammaValue blueTable[tableSize];
slouken@5466
  1322
    uint32_t i, tableCopied;
slouken@5466
  1323
slouken@5466
  1324
    if (CGGetDisplayTransferByTable(display_id, tableSize,
slouken@5466
  1325
                                    redTable, greenTable, blueTable, &tableCopied) != CGDisplayNoErr) {
icculus@7037
  1326
        return SDL_SetError("CGGetDisplayTransferByTable()");
slouken@5466
  1327
    }
slouken@5466
  1328
slouken@5466
  1329
    for (i = 0; i < tableCopied; i++) {
slouken@5466
  1330
        ramp[0*256+i] = (Uint16)(redTable[i] * 65535.0f);
slouken@5466
  1331
        ramp[1*256+i] = (Uint16)(greenTable[i] * 65535.0f);
slouken@5466
  1332
        ramp[2*256+i] = (Uint16)(blueTable[i] * 65535.0f);
slouken@5466
  1333
    }
slouken@5466
  1334
    return 0;
slouken@5466
  1335
}
slouken@5466
  1336
slouken@5249
  1337
void
slouken@6662
  1338
Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
slouken@1933
  1339
{
slouken@5371
  1340
    /* Move the cursor to the nearest point in the window */
slouken@6662
  1341
    if (grabbed) {
slouken@5371
  1342
        int x, y;
slouken@5371
  1343
        CGPoint cgpoint;
slouken@5371
  1344
slouken@5371
  1345
        SDL_GetMouseState(&x, &y);
slouken@5371
  1346
        cgpoint.x = window->x + x;
slouken@5371
  1347
        cgpoint.y = window->y + y;
slouken@5371
  1348
        CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
slouken@5371
  1349
    }
slouken@7191
  1350
slouken@6784
  1351
    if ( window->flags & SDL_WINDOW_FULLSCREEN ) {
slouken@7191
  1352
        SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@6755
  1353
slouken@7191
  1354
        if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@7191
  1355
            /* OpenGL is rendering to the window, so make it visible! */
slouken@7191
  1356
            [data->nswindow setLevel:CGShieldingWindowLevel()];
slouken@7191
  1357
        } else {
slouken@7191
  1358
            [data->nswindow setLevel:kCGNormalWindowLevel];
slouken@7191
  1359
        }
slouken@7191
  1360
    }
slouken@1933
  1361
}
slouken@1933
  1362
slouken@1933
  1363
void
slouken@1933
  1364
Cocoa_DestroyWindow(_THIS, SDL_Window * window)
slouken@1933
  1365
{
slouken@6848
  1366
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
  1367
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1933
  1368
slouken@6848
  1369
    if (data) {
slouken@6848
  1370
        [data->listener close];
slouken@6848
  1371
        [data->listener release];
slouken@6848
  1372
        if (data->created) {
slouken@6848
  1373
            [data->nswindow close];
slouken@1933
  1374
        }
jorgen@7595
  1375
jorgen@7595
  1376
        NSArray *contexts = [[data->nscontexts copy] autorelease];
jorgen@7595
  1377
        for (SDLOpenGLContext *context in contexts) {
jorgen@7595
  1378
            /* Calling setWindow:NULL causes the context to remove itself from the context list. */            
jorgen@7595
  1379
            [context setWindow:NULL];
jorgen@7595
  1380
        }
jorgen@7595
  1381
        [data->nscontexts release];
jorgen@7595
  1382
slouken@6848
  1383
        SDL_free(data);
slouken@1933
  1384
    }
slouken@6848
  1385
    [pool release];
slouken@1933
  1386
}
slouken@1933
  1387
slouken@1933
  1388
SDL_bool
slouken@1933
  1389
Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
slouken@1933
  1390
{
slouken@4900
  1391
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
  1392
slouken@1933
  1393
    if (info->version.major <= SDL_MAJOR_VERSION) {
slouken@4900
  1394
        info->subsystem = SDL_SYSWM_COCOA;
slouken@5056
  1395
        info->info.cocoa.window = nswindow;
slouken@1933
  1396
        return SDL_TRUE;
slouken@1933
  1397
    } else {
slouken@1933
  1398
        SDL_SetError("Application not compiled with SDL %d.%d\n",
slouken@1933
  1399
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@1933
  1400
        return SDL_FALSE;
slouken@1933
  1401
    }
slouken@1933
  1402
}
slouken@1933
  1403
slouken@7968
  1404
SDL_bool
slouken@7969
  1405
Cocoa_IsWindowInFullscreenSpace(SDL_Window * window)
slouken@7969
  1406
{
slouken@7969
  1407
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@7969
  1408
slouken@7969
  1409
    if ([data->listener isInFullscreenSpace]) {
slouken@7969
  1410
        return SDL_TRUE;
slouken@7969
  1411
    } else {
slouken@7969
  1412
        return SDL_FALSE;
slouken@7969
  1413
    }
slouken@7969
  1414
}
slouken@7969
  1415
slouken@7969
  1416
SDL_bool
slouken@7968
  1417
Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
slouken@7968
  1418
{
slouken@7968
  1419
    SDL_bool succeeded = SDL_FALSE;
slouken@7968
  1420
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@7968
  1421
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@7968
  1422
slouken@7968
  1423
    if ([data->listener setFullscreenSpace:(state ? YES : NO)]) {
slouken@7968
  1424
        succeeded = SDL_TRUE;
slouken@7968
  1425
    }
slouken@7968
  1426
slouken@7968
  1427
    [pool release];
slouken@7968
  1428
slouken@7968
  1429
    return succeeded;
slouken@7968
  1430
}
slouken@7968
  1431
slouken@6044
  1432
#endif /* SDL_VIDEO_DRIVER_COCOA */
slouken@6044
  1433
slouken@1933
  1434
/* vi: set ts=4 sw=4 expandtab: */