src/video/cocoa/SDL_cocoawindow.m
author Jørgen P. Tjernø <jorgen@valvesoftware.com>
Tue, 09 Jul 2013 12:57:12 -0700
changeset 7389 361d1a0c90f6
parent 7282 df78adc8ba04
child 7469 4310d5aee6fe
permissions -rw-r--r--
Mac: Remove dead FULLSCREEN_TOGGLEABLE code.

This code was written almost 2 years ago, and the flag hasn't been
changed since. Cleaning up the code by removing the conditional blocks,
so that they behave the same way they have for the past two years.

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