src/video/cocoa/SDL_cocoawindow.m
author Jørgen P. Tjernø <jorgen@valvesoftware.com>
Mon, 22 Apr 2013 12:07:16 -0700
changeset 7085 152cc7ddfa57
parent 7084 9d43403e9fc5
child 7087 5639ac726076
permissions -rw-r--r--
Mac no longer loses OpenGL context when window is hidden.

This fixes an issue that would arise when you minimize / order out an
OpenGL window on Mac, where the window would lose it's window device.
Without a window device, you cannot render to the window.

It does so by making two changes:
- Windows are no longer "oneShot" (which caused their window device to
get destroyed when they're minified or ordered out)
- Windows are no longer "deferred" (which caused the OS to defer
window device creation until the window is shown, which meant that
we couldn't properly makeCurrent to it)

Thanks to http://www.mikeash.com/pyblog/nsopenglcontext-and-one-shot.html
slouken@1933
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 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
*/
slouken@1933
    21
#include "SDL_config.h"
slouken@1933
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_COCOA
slouken@6044
    24
slouken@1933
    25
#include "SDL_syswm.h"
slouken@5398
    26
#include "SDL_timer.h"  /* For SDL_GetTicks() */
slouken@1933
    27
#include "../SDL_sysvideo.h"
slouken@1933
    28
#include "../../events/SDL_keyboard_c.h"
slouken@1933
    29
#include "../../events/SDL_mouse_c.h"
slouken@4673
    30
#include "../../events/SDL_touch_c.h"
slouken@1933
    31
#include "../../events/SDL_windowevents_c.h"
slouken@1933
    32
#include "SDL_cocoavideo.h"
eligottlieb@4811
    33
#include "SDL_cocoashape.h"
gzjjgod@5057
    34
#include "SDL_cocoamouse.h"
slouken@1933
    35
slouken@5398
    36
slouken@5398
    37
static Uint32 s_moveHack;
slouken@5398
    38
slouken@1933
    39
static __inline__ void ConvertNSRect(NSRect *r)
slouken@1933
    40
{
slouken@1933
    41
    r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
slouken@1933
    42
}
slouken@1933
    43
slouken@1933
    44
@implementation Cocoa_WindowListener
slouken@1933
    45
slouken@1933
    46
- (void)listen:(SDL_WindowData *)data
slouken@1933
    47
{
slouken@1933
    48
    NSNotificationCenter *center;
slouken@5371
    49
    NSWindow *window = data->nswindow;
slouken@5371
    50
    NSView *view = [window contentView];
slouken@1933
    51
slouken@1933
    52
    _data = data;
slouken@1933
    53
slouken@1933
    54
    center = [NSNotificationCenter defaultCenter];
slouken@1933
    55
slouken@5374
    56
    if ([window delegate] != nil) {
slouken@5374
    57
        [center addObserver:self selector:@selector(windowDidExpose:) name:NSWindowDidExposeNotification object:window];
slouken@5374
    58
        [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:window];
slouken@5374
    59
        [center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:window];
slouken@5374
    60
        [center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:window];
slouken@5374
    61
        [center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:window];
slouken@5374
    62
        [center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:window];
slouken@5374
    63
        [center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:window];
slouken@5374
    64
    } else {
slouken@5374
    65
        [window setDelegate:self];
slouken@5374
    66
    }
slouken@1933
    67
jorgen@7084
    68
    // Haven't found a delegate / notification that triggers when the window is
jorgen@7084
    69
    // ordered out (is not visible any more). You can be ordered out without
jorgen@7084
    70
    // minimizing, so DidMiniaturize doesn't work. (e.g. -[NSWindow orderOut:])
jorgen@7084
    71
    [window addObserver:self
jorgen@7084
    72
             forKeyPath:@"visible"
jorgen@7084
    73
                options:NSKeyValueObservingOptionNew
jorgen@7084
    74
                context:NULL];
jorgen@7084
    75
slouken@5371
    76
    [window setNextResponder:self];
slouken@5371
    77
    [window setAcceptsMouseMovedEvents:YES];
slouken@5371
    78
slouken@5371
    79
    [view setNextResponder:self];
icculus@6108
    80
icculus@5646
    81
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
icculus@6108
    82
    if ([view respondsToSelector:@selector(setAcceptsTouchEvents:)]) {
icculus@6108
    83
        [view setAcceptsTouchEvents:YES];
icculus@6108
    84
    }
slouken@4925
    85
#endif
slouken@1933
    86
}
slouken@1933
    87
jorgen@7084
    88
- (void)observeValueForKeyPath:(NSString *)keyPath
jorgen@7084
    89
                      ofObject:(id)object
jorgen@7084
    90
                        change:(NSDictionary *)change
jorgen@7084
    91
                       context:(void *)context
jorgen@7084
    92
{
jorgen@7084
    93
    if (object == _data->nswindow && [keyPath isEqualToString:@"visible"]) {
jorgen@7084
    94
        int newVisibility = [[change objectForKey:@"new"] intValue];
jorgen@7084
    95
        if (newVisibility) {
jorgen@7084
    96
            SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
jorgen@7084
    97
        } else {
jorgen@7084
    98
            SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
jorgen@7084
    99
        }
jorgen@7084
   100
    }
jorgen@7084
   101
}
jorgen@7084
   102
slouken@1933
   103
- (void)close
slouken@1933
   104
{
slouken@1933
   105
    NSNotificationCenter *center;
slouken@5371
   106
    NSWindow *window = _data->nswindow;
slouken@5371
   107
    NSView *view = [window contentView];
slouken@1933
   108
slouken@1933
   109
    center = [NSNotificationCenter defaultCenter];
slouken@1933
   110
slouken@5374
   111
    if ([window delegate] != self) {
slouken@5374
   112
        [center removeObserver:self name:NSWindowDidExposeNotification object:window];
slouken@5374
   113
        [center removeObserver:self name:NSWindowDidMoveNotification object:window];
slouken@5374
   114
        [center removeObserver:self name:NSWindowDidResizeNotification object:window];
slouken@5374
   115
        [center removeObserver:self name:NSWindowDidMiniaturizeNotification object:window];
slouken@5374
   116
        [center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:window];
slouken@5374
   117
        [center removeObserver:self name:NSWindowDidBecomeKeyNotification object:window];
slouken@5374
   118
        [center removeObserver:self name:NSWindowDidResignKeyNotification object:window];
slouken@5374
   119
    } else {
slouken@5374
   120
        [window setDelegate:nil];
slouken@5374
   121
    }
slouken@5371
   122
jorgen@7084
   123
    [window removeObserver:self
jorgen@7084
   124
                forKeyPath:@"visible"];
jorgen@7084
   125
slouken@5374
   126
    if ([window nextResponder] == self) {
slouken@5374
   127
        [window setNextResponder:nil];
slouken@5374
   128
    }
slouken@5374
   129
    if ([view nextResponder] == self) {
slouken@5374
   130
        [view setNextResponder:nil];
slouken@5374
   131
    }
slouken@1933
   132
}
slouken@1933
   133
slouken@1933
   134
- (BOOL)windowShouldClose:(id)sender
slouken@1933
   135
{
slouken@3685
   136
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1933
   137
    return NO;
slouken@1933
   138
}
slouken@1933
   139
slouken@1933
   140
- (void)windowDidExpose:(NSNotification *)aNotification
slouken@1933
   141
{
slouken@3685
   142
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
slouken@1933
   143
}
slouken@1933
   144
slouken@1933
   145
- (void)windowDidMove:(NSNotification *)aNotification
slouken@1933
   146
{
slouken@1933
   147
    int x, y;
icculus@5564
   148
    SDL_VideoDevice *device = SDL_GetVideoDevice();
slouken@5398
   149
    SDL_Window *window = _data->window;
slouken@5398
   150
    NSWindow *nswindow = _data->nswindow;
slouken@5398
   151
    NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
slouken@1933
   152
    ConvertNSRect(&rect);
slouken@5398
   153
slouken@5398
   154
    if (s_moveHack) {
slouken@5398
   155
        SDL_bool blockMove = ((SDL_GetTicks() - s_moveHack) < 500);
slouken@5398
   156
slouken@5398
   157
        s_moveHack = 0;
slouken@5398
   158
slouken@5398
   159
        if (blockMove) {
slouken@5398
   160
            /* Cocoa is adjusting the window in response to a mode change */
slouken@5398
   161
            rect.origin.x = window->x;
slouken@5398
   162
            rect.origin.y = window->y;
slouken@5398
   163
            ConvertNSRect(&rect);
slouken@5398
   164
            [nswindow setFrameOrigin:rect.origin];
slouken@5398
   165
            return;
slouken@5398
   166
        }
slouken@5398
   167
    }
slouken@5398
   168
slouken@3507
   169
    x = (int)rect.origin.x;
slouken@3507
   170
    y = (int)rect.origin.y;
icculus@5564
   171
icculus@5564
   172
    if (window == device->current_glwin) {
icculus@5564
   173
        [((NSOpenGLContext *) device->current_glctx) update];
icculus@5564
   174
    }
icculus@5564
   175
slouken@5398
   176
    SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1933
   177
}
slouken@1933
   178
slouken@1933
   179
- (void)windowDidResize:(NSNotification *)aNotification
slouken@1933
   180
{
icculus@5564
   181
    SDL_VideoDevice *device = SDL_GetVideoDevice();
slouken@6231
   182
    int x, y, w, h;
slouken@3688
   183
    NSRect rect = [_data->nswindow contentRectForFrameRect:[_data->nswindow frame]];
slouken@6231
   184
    ConvertNSRect(&rect);
slouken@6231
   185
    x = (int)rect.origin.x;
slouken@6231
   186
    y = (int)rect.origin.y;
slouken@1933
   187
    w = (int)rect.size.width;
slouken@1933
   188
    h = (int)rect.size.height;
slouken@4937
   189
    if (SDL_IsShapedWindow(_data->window))
slouken@4937
   190
        Cocoa_ResizeWindowShape(_data->window);
icculus@5564
   191
icculus@5564
   192
    if (_data->window == device->current_glwin) {
icculus@5564
   193
        [((NSOpenGLContext *) device->current_glctx) update];
icculus@5564
   194
    }
icculus@5564
   195
slouken@6231
   196
    /* The window can move during a resize event, such as when maximizing
slouken@6231
   197
       or resizing from a corner */
slouken@6231
   198
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@3685
   199
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESIZED, w, h);
slouken@1933
   200
}
slouken@1933
   201
slouken@1933
   202
- (void)windowDidMiniaturize:(NSNotification *)aNotification
slouken@1933
   203
{
slouken@3685
   204
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@1933
   205
}
slouken@1933
   206
slouken@1933
   207
- (void)windowDidDeminiaturize:(NSNotification *)aNotification
slouken@1933
   208
{
slouken@3685
   209
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@1933
   210
}
slouken@1933
   211
slouken@1933
   212
- (void)windowDidBecomeKey:(NSNotification *)aNotification
slouken@1933
   213
{
slouken@5367
   214
    SDL_Window *window = _data->window;
slouken@5367
   215
slouken@3688
   216
    /* We're going to get keyboard events, since we're key. */
slouken@5367
   217
    SDL_SetKeyboardFocus(window);
slouken@5367
   218
slouken@5367
   219
    /* If we just gained focus we need the updated mouse position */
slouken@5396
   220
    {
slouken@5367
   221
        NSPoint point;
slouken@5396
   222
        int x, y;
slouken@5396
   223
slouken@5396
   224
        point = [_data->nswindow mouseLocationOutsideOfEventStream];
slouken@5396
   225
        x = (int)point.x;
slouken@5396
   226
        y = (int)(window->h - point.y);
slouken@5396
   227
slouken@5396
   228
        if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
slouken@6950
   229
            SDL_SendMouseMotion(window, 0, 0, x, y);
slouken@6666
   230
            SDL_SetCursor(NULL);
slouken@5396
   231
        }
slouken@5367
   232
    }
slouken@1962
   233
slouken@4503
   234
    /* Check to see if someone updated the clipboard */
slouken@4503
   235
    Cocoa_CheckClipboardUpdate(_data->videodata);
slouken@1933
   236
}
slouken@1933
   237
slouken@1933
   238
- (void)windowDidResignKey:(NSNotification *)aNotification
slouken@1933
   239
{
slouken@2059
   240
    /* Some other window will get mouse events, since we're not key. */
slouken@4465
   241
    if (SDL_GetMouseFocus() == _data->window) {
slouken@4465
   242
        SDL_SetMouseFocus(NULL);
slouken@2059
   243
    }
slouken@2059
   244
slouken@2059
   245
    /* Some other window will get keyboard events, since we're not key. */
slouken@4465
   246
    if (SDL_GetKeyboardFocus() == _data->window) {
slouken@4465
   247
        SDL_SetKeyboardFocus(NULL);
slouken@4465
   248
    }
slouken@1933
   249
}
slouken@1933
   250
slouken@6514
   251
// We'll respond to key events by doing nothing so we don't beep.
slouken@6514
   252
// We could handle key messages here, but we lose some in the NSApp dispatch,
slouken@6514
   253
// where they get converted to action messages, etc.
slouken@6514
   254
- (void)flagsChanged:(NSEvent *)theEvent
slouken@6514
   255
{
slouken@6514
   256
    //Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);
slouken@6514
   257
}
slouken@6514
   258
- (void)keyDown:(NSEvent *)theEvent
slouken@6514
   259
{
slouken@6514
   260
    //Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);
slouken@6514
   261
}
slouken@6514
   262
- (void)keyUp:(NSEvent *)theEvent
slouken@6514
   263
{
slouken@6514
   264
    //Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);
slouken@6514
   265
}
slouken@6514
   266
slouken@6514
   267
// We'll respond to selectors by doing nothing so we don't beep.
slouken@6514
   268
// The escape key gets converted to a "cancel" selector, etc.
slouken@6514
   269
- (void)doCommandBySelector:(SEL)aSelector
slouken@6514
   270
{
slouken@6514
   271
    //NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));
slouken@6514
   272
}
slouken@6514
   273
slouken@1933
   274
- (void)mouseDown:(NSEvent *)theEvent
slouken@1933
   275
{
slouken@1959
   276
    int button;
slouken@1933
   277
slouken@1959
   278
    switch ([theEvent buttonNumber]) {
slouken@1959
   279
    case 0:
slouken@1959
   280
        button = SDL_BUTTON_LEFT;
slouken@1959
   281
        break;
slouken@1959
   282
    case 1:
slouken@1959
   283
        button = SDL_BUTTON_RIGHT;
slouken@1959
   284
        break;
slouken@1959
   285
    case 2:
slouken@1959
   286
        button = SDL_BUTTON_MIDDLE;
slouken@1959
   287
        break;
slouken@1959
   288
    default:
slouken@5061
   289
        button = [theEvent buttonNumber] + 1;
slouken@1959
   290
        break;
slouken@1959
   291
    }
slouken@6950
   292
    SDL_SendMouseButton(_data->window, 0, SDL_PRESSED, button);
slouken@1933
   293
}
slouken@1933
   294
slouken@1933
   295
- (void)rightMouseDown:(NSEvent *)theEvent
slouken@1933
   296
{
slouken@1959
   297
    [self mouseDown:theEvent];
slouken@1933
   298
}
slouken@1933
   299
slouken@1933
   300
- (void)otherMouseDown:(NSEvent *)theEvent
slouken@1933
   301
{
slouken@1959
   302
    [self mouseDown:theEvent];
slouken@1933
   303
}
slouken@1933
   304
slouken@1933
   305
- (void)mouseUp:(NSEvent *)theEvent
slouken@1933
   306
{
slouken@1959
   307
    int button;
slouken@1933
   308
slouken@1959
   309
    switch ([theEvent buttonNumber]) {
slouken@1959
   310
    case 0:
slouken@1959
   311
        button = SDL_BUTTON_LEFT;
slouken@1959
   312
        break;
slouken@1959
   313
    case 1:
slouken@1959
   314
        button = SDL_BUTTON_RIGHT;
slouken@1959
   315
        break;
slouken@1959
   316
    case 2:
slouken@1959
   317
        button = SDL_BUTTON_MIDDLE;
slouken@1959
   318
        break;
slouken@1959
   319
    default:
slouken@5061
   320
        button = [theEvent buttonNumber] + 1;
slouken@1959
   321
        break;
slouken@1959
   322
    }
slouken@6950
   323
    SDL_SendMouseButton(_data->window, 0, SDL_RELEASED, button);
slouken@1933
   324
}
slouken@1933
   325
slouken@1933
   326
- (void)rightMouseUp:(NSEvent *)theEvent
slouken@1933
   327
{
slouken@1959
   328
    [self mouseUp:theEvent];
slouken@1933
   329
}
slouken@1933
   330
slouken@1933
   331
- (void)otherMouseUp:(NSEvent *)theEvent
slouken@1933
   332
{
slouken@1959
   333
    [self mouseUp:theEvent];
slouken@1933
   334
}
slouken@1933
   335
slouken@1933
   336
- (void)mouseMoved:(NSEvent *)theEvent
slouken@1933
   337
{
slouken@5406
   338
    SDL_Mouse *mouse = SDL_GetMouse();
slouken@3685
   339
    SDL_Window *window = _data->window;
slouken@5396
   340
    NSPoint point;
slouken@5396
   341
    int x, y;
slouken@1933
   342
slouken@5406
   343
    if (mouse->relative_mode) {
gzjjgod@5059
   344
        return;
slouken@5371
   345
    }
gzjjgod@5059
   346
slouken@5396
   347
    point = [theEvent locationInWindow];
slouken@5396
   348
    x = (int)point.x;
slouken@5396
   349
    y = (int)(window->h - point.y);
slouken@5371
   350
slouken@5396
   351
    if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
slouken@6666
   352
        if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@6666
   353
            CGPoint cgpoint;
slouken@6666
   354
slouken@6666
   355
            if (x < 0) {
slouken@6666
   356
                x = 0;
slouken@6666
   357
            } else if (x >= window->w) {
slouken@6666
   358
                x = window->w - 1;
slouken@6666
   359
            }
slouken@6666
   360
            if (y < 0) {
slouken@6666
   361
                y = 0;
slouken@6666
   362
            } else if (y >= window->h) {
slouken@6666
   363
                y = window->h - 1;
slouken@6666
   364
            }
slouken@6666
   365
slouken@6666
   366
            cgpoint.x = window->x + x;
slouken@6666
   367
            cgpoint.y = window->y + y;
slouken@6666
   368
            CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
slouken@5396
   369
        }
slouken@2059
   370
    }
slouken@6950
   371
    SDL_SendMouseMotion(window, 0, 0, x, y);
slouken@1933
   372
}
slouken@1933
   373
slouken@1957
   374
- (void)mouseDragged:(NSEvent *)theEvent
slouken@1957
   375
{
slouken@1957
   376
    [self mouseMoved:theEvent];
slouken@1957
   377
}
slouken@1957
   378
slouken@1958
   379
- (void)rightMouseDragged:(NSEvent *)theEvent
slouken@1958
   380
{
slouken@1958
   381
    [self mouseMoved:theEvent];
slouken@1958
   382
}
slouken@1958
   383
slouken@1958
   384
- (void)otherMouseDragged:(NSEvent *)theEvent
slouken@1958
   385
{
slouken@1958
   386
    [self mouseMoved:theEvent];
slouken@1958
   387
}
slouken@1958
   388
slouken@1933
   389
- (void)scrollWheel:(NSEvent *)theEvent
slouken@1933
   390
{
gzjjgod@5057
   391
    Cocoa_HandleMouseWheel(_data->window, theEvent);
slouken@3688
   392
}
slouken@3688
   393
slouken@4673
   394
- (void)touchesBeganWithEvent:(NSEvent *) theEvent
slouken@4673
   395
{
slouken@4673
   396
    [self handleTouches:COCOA_TOUCH_DOWN withEvent:theEvent];
slouken@4673
   397
}
slouken@4673
   398
slouken@4673
   399
- (void)touchesMovedWithEvent:(NSEvent *) theEvent
slouken@4673
   400
{
slouken@4673
   401
    [self handleTouches:COCOA_TOUCH_MOVE withEvent:theEvent];
slouken@4673
   402
}
slouken@4673
   403
slouken@4673
   404
- (void)touchesEndedWithEvent:(NSEvent *) theEvent
slouken@4673
   405
{
slouken@4673
   406
    [self handleTouches:COCOA_TOUCH_UP withEvent:theEvent];
slouken@4673
   407
}
slouken@4673
   408
slouken@4673
   409
- (void)touchesCancelledWithEvent:(NSEvent *) theEvent
slouken@4673
   410
{
slouken@4673
   411
    [self handleTouches:COCOA_TOUCH_CANCELLED withEvent:theEvent];
slouken@4673
   412
}
slouken@4673
   413
slouken@4673
   414
- (void)handleTouches:(cocoaTouchType)type withEvent:(NSEvent *)event
slouken@4673
   415
{
icculus@5646
   416
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
slouken@4680
   417
    NSSet *touches = 0;
slouken@4680
   418
    NSEnumerator *enumerator;
slouken@4680
   419
    NSTouch *touch;
slouken@4673
   420
slouken@4680
   421
    switch (type) {
slouken@4680
   422
        case COCOA_TOUCH_DOWN:
slouken@4680
   423
            touches = [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil];
slouken@4680
   424
            break;
slouken@4680
   425
        case COCOA_TOUCH_UP:
slouken@4680
   426
        case COCOA_TOUCH_CANCELLED:
slouken@4680
   427
            touches = [event touchesMatchingPhase:NSTouchPhaseEnded inView:nil];
slouken@4680
   428
            break;
slouken@4680
   429
        case COCOA_TOUCH_MOVE:
slouken@4680
   430
            touches = [event touchesMatchingPhase:NSTouchPhaseMoved inView:nil];
slouken@4680
   431
            break;
slouken@4680
   432
    }
slouken@4680
   433
slouken@4680
   434
    enumerator = [touches objectEnumerator];
slouken@4680
   435
    touch = (NSTouch*)[enumerator nextObject];
slouken@4673
   436
    while (touch) {
slouken@6953
   437
        const SDL_TouchID touchId = (SDL_TouchID)(intptr_t)[touch device];
slouken@4673
   438
        if (!SDL_GetTouch(touchId)) {
slouken@6951
   439
            if (SDL_AddTouch(touchId, "") < 0) {
slouken@4680
   440
                return;
slouken@4673
   441
            }
slouken@4673
   442
        } 
slouken@4687
   443
slouken@6953
   444
        const SDL_FingerID fingerId = (SDL_FingerID)(intptr_t)[touch identity];
slouken@4673
   445
        float x = [touch normalizedPosition].x;
slouken@4673
   446
        float y = [touch normalizedPosition].y;
slouken@5261
   447
        /* Make the origin the upper left instead of the lower left */
slouken@5261
   448
        y = 1.0f - y;
slouken@4687
   449
slouken@4673
   450
        switch (type) {
slouken@4673
   451
        case COCOA_TOUCH_DOWN:
slouken@6951
   452
            SDL_SendTouch(touchId, fingerId, SDL_TRUE, x, y, 1.0f);
slouken@4673
   453
            break;
slouken@4673
   454
        case COCOA_TOUCH_UP:
slouken@4673
   455
        case COCOA_TOUCH_CANCELLED:
slouken@6951
   456
            SDL_SendTouch(touchId, fingerId, SDL_FALSE, x, y, 1.0f);
slouken@4673
   457
            break;
slouken@4673
   458
        case COCOA_TOUCH_MOVE:
slouken@6951
   459
            SDL_SendTouchMotion(touchId, fingerId, x, y, 1.0f);
slouken@4673
   460
            break;
slouken@4673
   461
        }
slouken@6951
   462
slouken@4673
   463
        touch = (NSTouch*)[enumerator nextObject];
slouken@4673
   464
    }
icculus@5646
   465
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 */
slouken@1933
   466
}
slouken@1933
   467
slouken@1933
   468
@end
slouken@1933
   469
slouken@1973
   470
@interface SDLWindow : NSWindow
slouken@1973
   471
/* These are needed for borderless/fullscreen windows */
slouken@1973
   472
- (BOOL)canBecomeKeyWindow;
slouken@1973
   473
- (BOOL)canBecomeMainWindow;
slouken@1973
   474
@end
slouken@1973
   475
slouken@1973
   476
@implementation SDLWindow
slouken@1973
   477
- (BOOL)canBecomeKeyWindow
slouken@1973
   478
{
slouken@1973
   479
    return YES;
slouken@1973
   480
}
slouken@1973
   481
slouken@1973
   482
- (BOOL)canBecomeMainWindow
slouken@1973
   483
{
slouken@1973
   484
    return YES;
slouken@1973
   485
}
slouken@1973
   486
@end
slouken@1973
   487
slouken@5379
   488
@interface SDLView : NSView
slouken@5379
   489
/* The default implementation doesn't pass rightMouseDown to responder chain */
slouken@5379
   490
- (void)rightMouseDown:(NSEvent *)theEvent;
gzjjgod@4915
   491
@end
gzjjgod@4915
   492
gzjjgod@4915
   493
@implementation SDLView
gzjjgod@4915
   494
- (void)rightMouseDown:(NSEvent *)theEvent
gzjjgod@4915
   495
{
slouken@5371
   496
    [[self nextResponder] rightMouseDown:theEvent];
gzjjgod@4915
   497
}
gzjjgod@4915
   498
@end
gzjjgod@4915
   499
slouken@5249
   500
static unsigned int
slouken@5305
   501
GetWindowStyle(SDL_Window * window)
slouken@5249
   502
{
slouken@5249
   503
    unsigned int style;
slouken@5249
   504
slouken@5305
   505
	if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@5249
   506
        style = NSBorderlessWindowMask;
slouken@5305
   507
	} else {
slouken@5305
   508
		if (window->flags & SDL_WINDOW_BORDERLESS) {
slouken@5305
   509
			style = NSBorderlessWindowMask;
slouken@5305
   510
		} else {
slouken@5305
   511
			style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
slouken@5305
   512
		}
slouken@5305
   513
		if (window->flags & SDL_WINDOW_RESIZABLE) {
slouken@5305
   514
			style |= NSResizableWindowMask;
slouken@5305
   515
		}
slouken@5305
   516
	}
slouken@5249
   517
    return style;
slouken@5249
   518
}
slouken@5249
   519
slouken@1933
   520
static int
slouken@1951
   521
SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
slouken@1933
   522
{
slouken@6848
   523
    NSAutoreleasePool *pool;
slouken@1951
   524
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@1933
   525
    SDL_WindowData *data;
slouken@1933
   526
slouken@1933
   527
    /* Allocate the window data */
slouken@5249
   528
    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
slouken@1933
   529
    if (!data) {
icculus@7037
   530
        return SDL_OutOfMemory();
slouken@1933
   531
    }
slouken@3685
   532
    data->window = window;
slouken@3688
   533
    data->nswindow = nswindow;
slouken@1933
   534
    data->created = created;
slouken@1951
   535
    data->videodata = videodata;
slouken@1933
   536
slouken@6848
   537
    pool = [[NSAutoreleasePool alloc] init];
slouken@1933
   538
slouken@6848
   539
    /* Create an event listener for the window */
slouken@6848
   540
    data->listener = [[Cocoa_WindowListener alloc] init];
slouken@6848
   541
slouken@6848
   542
    /* Fill in the SDL window with the window data */
slouken@6848
   543
    {
slouken@6848
   544
        NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
slouken@6848
   545
        ConvertNSRect(&rect);
slouken@6848
   546
        window->x = (int)rect.origin.x;
slouken@6848
   547
        window->y = (int)rect.origin.y;
slouken@6848
   548
        window->w = (int)rect.size.width;
slouken@6848
   549
        window->h = (int)rect.size.height;
slouken@6848
   550
    }
slouken@6848
   551
slouken@6848
   552
    /* Set up the listener after we create the view */
slouken@6848
   553
    [data->listener listen:data];
slouken@6848
   554
slouken@6848
   555
    if ([nswindow isVisible]) {
slouken@6848
   556
        window->flags |= SDL_WINDOW_SHOWN;
slouken@6848
   557
    } else {
slouken@6848
   558
        window->flags &= ~SDL_WINDOW_SHOWN;
slouken@6848
   559
    }
jorgen@7084
   560
slouken@6848
   561
    {
slouken@6848
   562
        unsigned int style = [nswindow styleMask];
slouken@6848
   563
slouken@6848
   564
        if (style == NSBorderlessWindowMask) {
slouken@6848
   565
            window->flags |= SDL_WINDOW_BORDERLESS;
slouken@6848
   566
        } else {
slouken@6848
   567
            window->flags &= ~SDL_WINDOW_BORDERLESS;
alexey@6832
   568
        }
slouken@6848
   569
        if (style & NSResizableWindowMask) {
slouken@6848
   570
            window->flags |= SDL_WINDOW_RESIZABLE;
slouken@6848
   571
        } else {
slouken@6848
   572
            window->flags &= ~SDL_WINDOW_RESIZABLE;
slouken@6848
   573
        }
slouken@6848
   574
    }
jorgen@7084
   575
slouken@6848
   576
    /* isZoomed always returns true if the window is not resizable */
slouken@6848
   577
    if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
slouken@6848
   578
        window->flags |= SDL_WINDOW_MAXIMIZED;
slouken@6848
   579
    } else {
slouken@6848
   580
        window->flags &= ~SDL_WINDOW_MAXIMIZED;
slouken@6848
   581
    }
jorgen@7084
   582
slouken@6848
   583
    if ([nswindow isMiniaturized]) {
slouken@6848
   584
        window->flags |= SDL_WINDOW_MINIMIZED;
slouken@6848
   585
    } else {
slouken@6848
   586
        window->flags &= ~SDL_WINDOW_MINIMIZED;
slouken@6848
   587
    }
jorgen@7084
   588
slouken@6848
   589
    if ([nswindow isKeyWindow]) {
slouken@6848
   590
        window->flags |= SDL_WINDOW_INPUT_FOCUS;
slouken@6848
   591
        SDL_SetKeyboardFocus(data->window);
slouken@6848
   592
    }
slouken@1933
   593
jorgen@7085
   594
    /* Prevents the window's "window device" from being destroyed when it is
jorgen@7085
   595
     * hidden. See http://www.mikeash.com/pyblog/nsopenglcontext-and-one-shot.html
jorgen@7085
   596
     */
jorgen@7085
   597
    [nswindow setOneShot:NO];
jorgen@7085
   598
slouken@6848
   599
    /* All done! */
slouken@6848
   600
    [pool release];
slouken@6848
   601
    window->driverdata = data;
slouken@6848
   602
    return 0;
slouken@1933
   603
}
slouken@1933
   604
slouken@1933
   605
int
slouken@1933
   606
Cocoa_CreateWindow(_THIS, SDL_Window * window)
slouken@1933
   607
{
slouken@6848
   608
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   609
    NSWindow *nswindow;
slouken@6848
   610
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@6848
   611
    NSRect rect;
slouken@6848
   612
    SDL_Rect bounds;
slouken@6848
   613
    unsigned int style;
slouken@1933
   614
slouken@6848
   615
    Cocoa_GetDisplayBounds(_this, display, &bounds);
slouken@6848
   616
    rect.origin.x = window->x;
slouken@6848
   617
    rect.origin.y = window->y;
slouken@6848
   618
    rect.size.width = window->w;
slouken@6848
   619
    rect.size.height = window->h;
slouken@6848
   620
    ConvertNSRect(&rect);
slouken@1933
   621
slouken@6848
   622
    style = GetWindowStyle(window);
slouken@1933
   623
slouken@6848
   624
    /* Figure out which screen to place this window */
slouken@6848
   625
    NSArray *screens = [NSScreen screens];
slouken@6848
   626
    NSScreen *screen = nil;
slouken@6848
   627
    NSScreen *candidate;
slouken@6848
   628
    int i, count = [screens count];
slouken@6848
   629
    for (i = 0; i < count; ++i) {
slouken@6848
   630
        candidate = [screens objectAtIndex:i];
slouken@6848
   631
        NSRect screenRect = [candidate frame];
slouken@6848
   632
        if (rect.origin.x >= screenRect.origin.x &&
slouken@6848
   633
            rect.origin.x < screenRect.origin.x + screenRect.size.width &&
slouken@6848
   634
            rect.origin.y >= screenRect.origin.y &&
slouken@6848
   635
            rect.origin.y < screenRect.origin.y + screenRect.size.height) {
slouken@6848
   636
            screen = candidate;
slouken@6848
   637
            rect.origin.x -= screenRect.origin.x;
slouken@6848
   638
            rect.origin.y -= screenRect.origin.y;
slouken@3506
   639
        }
slouken@6848
   640
    }
jorgen@7085
   641
    nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:NO screen:screen];
alexey@6832
   642
slouken@6848
   643
    // Create a default view for this window
slouken@6848
   644
    rect = [nswindow contentRectForFrameRect:[nswindow frame]];
slouken@6848
   645
    NSView *contentView = [[SDLView alloc] initWithFrame:rect];
slouken@6848
   646
    [nswindow setContentView: contentView];
slouken@6848
   647
    [contentView release];
alexey@6832
   648
slouken@6848
   649
    [pool release];
slouken@6848
   650
slouken@6848
   651
    if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
slouken@6848
   652
        [nswindow release];
slouken@6848
   653
        return -1;
slouken@3506
   654
    }
slouken@6848
   655
    return 0;
slouken@1933
   656
}
slouken@1933
   657
slouken@1933
   658
int
slouken@1933
   659
Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@1933
   660
{
slouken@6848
   661
    NSAutoreleasePool *pool;
slouken@1933
   662
    NSWindow *nswindow = (NSWindow *) data;
slouken@1933
   663
    NSString *title;
slouken@1933
   664
slouken@6848
   665
    pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   666
slouken@6848
   667
    /* Query the title from the existing window */
slouken@6848
   668
    title = [nswindow title];
slouken@6848
   669
    if (title) {
slouken@6848
   670
        window->title = SDL_strdup([title UTF8String]);
slouken@1933
   671
    }
slouken@1933
   672
slouken@6848
   673
    [pool release];
slouken@6848
   674
slouken@1951
   675
    return SetupWindowData(_this, window, nswindow, SDL_FALSE);
slouken@1933
   676
}
slouken@1933
   677
slouken@1933
   678
void
slouken@1933
   679
Cocoa_SetWindowTitle(_THIS, SDL_Window * window)
slouken@1933
   680
{
slouken@6848
   681
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   682
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@6848
   683
    NSString *string;
slouken@1933
   684
slouken@6848
   685
    if(window->title) {
slouken@6848
   686
        string = [[NSString alloc] initWithUTF8String:window->title];
slouken@6848
   687
    } else {
slouken@6848
   688
        string = [[NSString alloc] init];
slouken@1956
   689
    }
slouken@6848
   690
    [nswindow setTitle:string];
slouken@6848
   691
    [string release];
slouken@6848
   692
slouken@6848
   693
    [pool release];
slouken@1933
   694
}
slouken@1933
   695
slouken@1933
   696
void
slouken@5375
   697
Cocoa_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
slouken@5375
   698
{
slouken@6848
   699
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   700
    NSImage *nsimage = Cocoa_CreateImage(icon);
slouken@5375
   701
slouken@6848
   702
    if (nsimage) {
slouken@6848
   703
        [NSApp setApplicationIconImage:nsimage];
slouken@5375
   704
    }
slouken@6848
   705
slouken@6848
   706
    [pool release];
slouken@5375
   707
}
slouken@5375
   708
slouken@5375
   709
void
slouken@1933
   710
Cocoa_SetWindowPosition(_THIS, SDL_Window * window)
slouken@1933
   711
{
slouken@6848
   712
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   713
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@6848
   714
    NSRect rect;
slouken@6848
   715
    Uint32 moveHack;
slouken@1933
   716
slouken@6848
   717
    rect.origin.x = window->x;
slouken@6848
   718
    rect.origin.y = window->y;
slouken@6848
   719
    rect.size.width = window->w;
slouken@6848
   720
    rect.size.height = window->h;
slouken@6848
   721
    ConvertNSRect(&rect);
slouken@5478
   722
slouken@6848
   723
    moveHack = s_moveHack;
slouken@6848
   724
    s_moveHack = 0;
slouken@6848
   725
    [nswindow setFrameOrigin:rect.origin];
slouken@6848
   726
    s_moveHack = moveHack;
slouken@5478
   727
slouken@6848
   728
    if (window == _this->current_glwin) {
slouken@6848
   729
        [((NSOpenGLContext *) _this->current_glctx) update];
icculus@5564
   730
    }
slouken@6848
   731
slouken@6848
   732
    [pool release];
slouken@1933
   733
}
slouken@1933
   734
slouken@1933
   735
void
slouken@1933
   736
Cocoa_SetWindowSize(_THIS, SDL_Window * window)
slouken@1933
   737
{
slouken@6848
   738
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   739
    SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
slouken@6848
   740
    NSWindow *nswindow = windata->nswindow;
slouken@6848
   741
    NSSize size;
slouken@1933
   742
slouken@6848
   743
    size.width = window->w;
slouken@6848
   744
    size.height = window->h;
slouken@6848
   745
    [nswindow setContentSize:size];
icculus@5564
   746
slouken@6848
   747
    if (window == _this->current_glwin) {
slouken@6848
   748
        [((NSOpenGLContext *) _this->current_glctx) update];
icculus@5564
   749
    }
slouken@6848
   750
slouken@6848
   751
    [pool release];
slouken@1933
   752
}
slouken@1933
   753
slouken@1933
   754
void
stopiccot@6681
   755
Cocoa_SetWindowMinimumSize(_THIS, SDL_Window * window)
stopiccot@6681
   756
{
slouken@6848
   757
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   758
    SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
slouken@6848
   759
        
slouken@6848
   760
    NSSize minSize;
slouken@6848
   761
    minSize.width = window->min_w;
slouken@6848
   762
    minSize.height = window->min_h;
slouken@6848
   763
        
slouken@6848
   764
    [windata->nswindow setContentMinSize:minSize];
slouken@6848
   765
    
slouken@6848
   766
    [pool release];
slouken@6788
   767
}
slouken@6788
   768
slouken@6788
   769
void
slouken@6788
   770
Cocoa_SetWindowMaximumSize(_THIS, SDL_Window * window)
slouken@6788
   771
{
slouken@6848
   772
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   773
    SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
slouken@6848
   774
        
slouken@6848
   775
    NSSize maxSize;
slouken@6848
   776
    maxSize.width = window->max_w;
slouken@6848
   777
    maxSize.height = window->max_h;
slouken@6848
   778
        
slouken@6848
   779
    [windata->nswindow setContentMaxSize:maxSize];
slouken@6848
   780
    
slouken@6848
   781
    [pool release];
stopiccot@6681
   782
}
stopiccot@6681
   783
stopiccot@6681
   784
void
slouken@1933
   785
Cocoa_ShowWindow(_THIS, SDL_Window * window)
slouken@1933
   786
{
slouken@6848
   787
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   788
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   789
slouken@6848
   790
    if (![nswindow isMiniaturized]) {
slouken@6848
   791
        [nswindow makeKeyAndOrderFront:nil];
slouken@1956
   792
    }
slouken@6848
   793
    [pool release];
slouken@1933
   794
}
slouken@1933
   795
slouken@1933
   796
void
slouken@1933
   797
Cocoa_HideWindow(_THIS, SDL_Window * window)
slouken@1933
   798
{
slouken@6848
   799
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   800
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@6848
   801
slouken@6848
   802
    [nswindow orderOut:nil];
slouken@6848
   803
    [pool release];
slouken@1933
   804
}
slouken@1933
   805
slouken@1933
   806
void
slouken@1933
   807
Cocoa_RaiseWindow(_THIS, SDL_Window * window)
slouken@1933
   808
{
slouken@6848
   809
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   810
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@6848
   811
slouken@6848
   812
    [nswindow makeKeyAndOrderFront:nil];
slouken@6848
   813
    [pool release];
slouken@1933
   814
}
slouken@1933
   815
slouken@1933
   816
void
slouken@1933
   817
Cocoa_MaximizeWindow(_THIS, SDL_Window * window)
slouken@1933
   818
{
slouken@6848
   819
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   820
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   821
slouken@6848
   822
    [nswindow zoom:nil];
slouken@6848
   823
slouken@6848
   824
    if (window == _this->current_glwin) {
slouken@6848
   825
        [((NSOpenGLContext *) _this->current_glctx) update];
icculus@5564
   826
    }
slouken@6848
   827
slouken@6848
   828
    [pool release];
slouken@1933
   829
}
slouken@1933
   830
slouken@1933
   831
void
slouken@1933
   832
Cocoa_MinimizeWindow(_THIS, SDL_Window * window)
slouken@1933
   833
{
slouken@6848
   834
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   835
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@6848
   836
slouken@6848
   837
    [nswindow miniaturize:nil];
slouken@6848
   838
    [pool release];
slouken@1933
   839
}
slouken@1933
   840
slouken@1933
   841
void
slouken@1933
   842
Cocoa_RestoreWindow(_THIS, SDL_Window * window)
slouken@1933
   843
{
slouken@6848
   844
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   845
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   846
slouken@6848
   847
    if ([nswindow isMiniaturized]) {
slouken@6848
   848
        [nswindow deminiaturize:nil];
slouken@6848
   849
    } else if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed]) {
slouken@6848
   850
        [nswindow zoom:nil];
slouken@1956
   851
    }
slouken@6848
   852
    [pool release];
slouken@1933
   853
}
slouken@1933
   854
slouken@5400
   855
static NSWindow *
slouken@5400
   856
Cocoa_RebuildWindow(SDL_WindowData * data, NSWindow * nswindow, unsigned style)
slouken@5400
   857
{
slouken@5400
   858
    if (!data->created) {
slouken@5400
   859
        /* Don't mess with other people's windows... */
slouken@5400
   860
        return nswindow;
slouken@5400
   861
    }
slouken@5400
   862
slouken@5400
   863
    [data->listener close];
jorgen@7085
   864
    data->nswindow = [[SDLWindow alloc] initWithContentRect:[[nswindow contentView] frame] styleMask:style backing:NSBackingStoreBuffered defer:NO screen:[nswindow screen]];
slouken@5400
   865
    [data->nswindow setContentView:[nswindow contentView]];
jorgen@7085
   866
    /* See comment in SetupWindowData. */
jorgen@7085
   867
    [data->nswindow setOneShot:NO];
slouken@5400
   868
    [data->listener listen:data];
slouken@5400
   869
slouken@5400
   870
    [nswindow close];
slouken@5400
   871
slouken@5400
   872
    return data->nswindow;
slouken@5400
   873
}
slouken@5400
   874
slouken@1933
   875
void
icculus@6422
   876
Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
icculus@6422
   877
{
icculus@6422
   878
    /* this message arrived in 10.6. You're out of luck on older OSes. */
icculus@6422
   879
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
slouken@6848
   880
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   881
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@6848
   882
    if ([nswindow respondsToSelector:@selector(setStyleMask:)]) {
slouken@6848
   883
        [nswindow setStyleMask:GetWindowStyle(window)];
slouken@6848
   884
        if (bordered) {
slouken@6848
   885
            Cocoa_SetWindowTitle(_this, window);  // this got blanked out.
icculus@6426
   886
        }
icculus@6422
   887
    }
slouken@6848
   888
    [pool release];
icculus@6422
   889
#endif
icculus@6422
   890
}
icculus@6422
   891
icculus@6422
   892
void
slouken@5305
   893
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
slouken@5249
   894
{
slouken@6848
   895
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   896
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@6848
   897
    NSWindow *nswindow = data->nswindow;
slouken@6848
   898
    NSRect rect;
slouken@5249
   899
slouken@6848
   900
    /* The view responder chain gets messed with during setStyleMask */
slouken@6848
   901
    if ([[nswindow contentView] nextResponder] == data->listener) {
slouken@6848
   902
        [[nswindow contentView] setNextResponder:nil];
slouken@6848
   903
    }
slouken@6848
   904
slouken@6848
   905
    if (fullscreen) {
slouken@6848
   906
        SDL_Rect bounds;
slouken@6848
   907
slouken@6848
   908
        Cocoa_GetDisplayBounds(_this, display, &bounds);
slouken@6848
   909
        rect.origin.x = bounds.x;
slouken@6848
   910
        rect.origin.y = bounds.y;
slouken@6848
   911
        rect.size.width = bounds.w;
slouken@6848
   912
        rect.size.height = bounds.h;
slouken@6848
   913
        ConvertNSRect(&rect);
slouken@6848
   914
slouken@6848
   915
        /* Hack to fix origin on Mac OS X 10.4 */
slouken@6848
   916
        NSRect screenRect = [[nswindow screen] frame];
slouken@6848
   917
        if (screenRect.size.height >= 1.0f) {
slouken@6848
   918
            rect.origin.y += (screenRect.size.height - rect.size.height);
slouken@5401
   919
        }
slouken@5401
   920
slouken@6848
   921
        if ([nswindow respondsToSelector: @selector(setStyleMask:)]) {
slouken@6848
   922
            [nswindow performSelector: @selector(setStyleMask:) withObject: (id)NSBorderlessWindowMask];
slouken@6848
   923
        } else {
slouken@6848
   924
            nswindow = Cocoa_RebuildWindow(data, nswindow, NSBorderlessWindowMask);
slouken@6848
   925
        }
slouken@6848
   926
    } else {
slouken@6848
   927
        rect.origin.x = window->windowed.x;
slouken@6848
   928
        rect.origin.y = window->windowed.y;
slouken@6848
   929
        rect.size.width = window->windowed.w;
slouken@6848
   930
        rect.size.height = window->windowed.h;
slouken@6848
   931
        ConvertNSRect(&rect);
alexey@6832
   932
slouken@6848
   933
        if ([nswindow respondsToSelector: @selector(setStyleMask:)]) {
slouken@6848
   934
            [nswindow performSelector: @selector(setStyleMask:) withObject: (id)(uintptr_t)GetWindowStyle(window)];
slouken@5400
   935
        } else {
slouken@6848
   936
            nswindow = Cocoa_RebuildWindow(data, nswindow, GetWindowStyle(window));
slouken@5361
   937
        }
slouken@5398
   938
    }
slouken@6848
   939
slouken@6848
   940
    /* The view responder chain gets messed with during setStyleMask */
slouken@6848
   941
    if ([[nswindow contentView] nextResponder] != data->listener) {
slouken@6848
   942
        [[nswindow contentView] setNextResponder:data->listener];
slouken@6848
   943
    }
slouken@6848
   944
slouken@6848
   945
    s_moveHack = 0;
slouken@6848
   946
    [nswindow setFrameOrigin:rect.origin];
slouken@6848
   947
    [nswindow setContentSize:rect.size];
slouken@6848
   948
    s_moveHack = SDL_GetTicks();
slouken@6848
   949
slouken@6848
   950
    /* When the window style changes the title is cleared */
slouken@6848
   951
    if (!fullscreen) {
slouken@6848
   952
        Cocoa_SetWindowTitle(_this, window);
slouken@6848
   953
    }
slouken@6848
   954
slouken@6848
   955
#ifdef FULLSCREEN_TOGGLEABLE
slouken@6848
   956
    if (SDL_ShouldAllowTopmost() && fullscreen) {
slouken@6848
   957
        /* OpenGL is rendering to the window, so make it visible! */
slouken@6848
   958
        [nswindow setLevel:CGShieldingWindowLevel()];
slouken@6848
   959
    } else {
slouken@6848
   960
        [nswindow setLevel:kCGNormalWindowLevel];
slouken@6848
   961
    }
slouken@6848
   962
#endif
slouken@6848
   963
    [nswindow makeKeyAndOrderFront:nil];
slouken@6848
   964
slouken@6848
   965
    if (window == _this->current_glwin) {
slouken@6848
   966
        [((NSOpenGLContext *) _this->current_glctx) update];
slouken@6848
   967
    }
slouken@6848
   968
slouken@6848
   969
    [pool release];
slouken@5249
   970
}
slouken@5249
   971
slouken@5466
   972
int
slouken@5466
   973
Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
slouken@5466
   974
{
slouken@5466
   975
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5466
   976
    CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
slouken@5466
   977
    const uint32_t tableSize = 256;
slouken@5466
   978
    CGGammaValue redTable[tableSize];
slouken@5466
   979
    CGGammaValue greenTable[tableSize];
slouken@5466
   980
    CGGammaValue blueTable[tableSize];
slouken@5466
   981
    uint32_t i;
slouken@5466
   982
    float inv65535 = 1.0f / 65535.0f;
slouken@5466
   983
slouken@5466
   984
    /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
slouken@5466
   985
    for (i = 0; i < 256; i++) {
slouken@5466
   986
        redTable[i] = ramp[0*256+i] * inv65535;
slouken@5466
   987
        greenTable[i] = ramp[1*256+i] * inv65535;
slouken@5466
   988
        blueTable[i] = ramp[2*256+i] * inv65535;
slouken@5466
   989
    }
slouken@5466
   990
slouken@5466
   991
    if (CGSetDisplayTransferByTable(display_id, tableSize,
slouken@5466
   992
                                    redTable, greenTable, blueTable) != CGDisplayNoErr) {
icculus@7037
   993
        return SDL_SetError("CGSetDisplayTransferByTable()");
slouken@5466
   994
    }
slouken@5466
   995
    return 0;
slouken@5466
   996
}
slouken@5466
   997
slouken@5466
   998
int
slouken@5466
   999
Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
slouken@5466
  1000
{
slouken@5466
  1001
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5466
  1002
    CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
slouken@5466
  1003
    const uint32_t tableSize = 256;
slouken@5466
  1004
    CGGammaValue redTable[tableSize];
slouken@5466
  1005
    CGGammaValue greenTable[tableSize];
slouken@5466
  1006
    CGGammaValue blueTable[tableSize];
slouken@5466
  1007
    uint32_t i, tableCopied;
slouken@5466
  1008
slouken@5466
  1009
    if (CGGetDisplayTransferByTable(display_id, tableSize,
slouken@5466
  1010
                                    redTable, greenTable, blueTable, &tableCopied) != CGDisplayNoErr) {
icculus@7037
  1011
        return SDL_SetError("CGGetDisplayTransferByTable()");
slouken@5466
  1012
    }
slouken@5466
  1013
slouken@5466
  1014
    for (i = 0; i < tableCopied; i++) {
slouken@5466
  1015
        ramp[0*256+i] = (Uint16)(redTable[i] * 65535.0f);
slouken@5466
  1016
        ramp[1*256+i] = (Uint16)(greenTable[i] * 65535.0f);
slouken@5466
  1017
        ramp[2*256+i] = (Uint16)(blueTable[i] * 65535.0f);
slouken@5466
  1018
    }
slouken@5466
  1019
    return 0;
slouken@5466
  1020
}
slouken@5466
  1021
slouken@5249
  1022
void
slouken@6662
  1023
Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
slouken@1933
  1024
{
slouken@5371
  1025
    /* Move the cursor to the nearest point in the window */
slouken@6662
  1026
    if (grabbed) {
slouken@5371
  1027
        int x, y;
slouken@5371
  1028
        CGPoint cgpoint;
slouken@5371
  1029
slouken@5371
  1030
        SDL_GetMouseState(&x, &y);
slouken@5371
  1031
        cgpoint.x = window->x + x;
slouken@5371
  1032
        cgpoint.y = window->y + y;
slouken@5371
  1033
        CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
slouken@5371
  1034
    }
slouken@6755
  1035
	
slouken@6784
  1036
    if ( window->flags & SDL_WINDOW_FULLSCREEN ) {
slouken@6755
  1037
		SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@6755
  1038
slouken@6784
  1039
		if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@6755
  1040
			/* OpenGL is rendering to the window, so make it visible! */
slouken@6755
  1041
			[data->nswindow setLevel:CGShieldingWindowLevel()];
slouken@6784
  1042
		} else {
slouken@6755
  1043
			[data->nswindow setLevel:kCGNormalWindowLevel];
slouken@6755
  1044
		}
slouken@6755
  1045
	}
slouken@1933
  1046
}
slouken@1933
  1047
slouken@1933
  1048
void
slouken@1933
  1049
Cocoa_DestroyWindow(_THIS, SDL_Window * window)
slouken@1933
  1050
{
slouken@6848
  1051
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@6848
  1052
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1933
  1053
slouken@6848
  1054
    if (data) {
slouken@6848
  1055
        [data->listener close];
slouken@6848
  1056
        [data->listener release];
slouken@6848
  1057
        if (data->created) {
slouken@6848
  1058
            [data->nswindow close];
slouken@1933
  1059
        }
slouken@6848
  1060
        SDL_free(data);
slouken@1933
  1061
    }
slouken@6848
  1062
    [pool release];
slouken@1933
  1063
}
slouken@1933
  1064
slouken@1933
  1065
SDL_bool
slouken@1933
  1066
Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
slouken@1933
  1067
{
slouken@4900
  1068
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
  1069
slouken@1933
  1070
    if (info->version.major <= SDL_MAJOR_VERSION) {
slouken@4900
  1071
        info->subsystem = SDL_SYSWM_COCOA;
slouken@5056
  1072
        info->info.cocoa.window = nswindow;
slouken@1933
  1073
        return SDL_TRUE;
slouken@1933
  1074
    } else {
slouken@1933
  1075
        SDL_SetError("Application not compiled with SDL %d.%d\n",
slouken@1933
  1076
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@1933
  1077
        return SDL_FALSE;
slouken@1933
  1078
    }
slouken@1933
  1079
}
slouken@1933
  1080
slouken@6044
  1081
#endif /* SDL_VIDEO_DRIVER_COCOA */
slouken@6044
  1082
slouken@1933
  1083
/* vi: set ts=4 sw=4 expandtab: */