src/video/cocoa/SDL_cocoawindow.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Feb 2011 00:25:44 -0800
changeset 5249 7a963be087ef
parent 5246 58265e606e4e
child 5253 9e70b360f423
permissions -rw-r--r--
Mostly fixed fullscreen mode on Mac OS X, and you can toggle it on and off.

There are still some problems with the ConvertNSRect() calculations when switching video modes, which causes wierd window positioning issues, and the fullscreen window is still minimized on exit.
slouken@1933
     1
/*
slouken@1933
     2
    SDL - Simple DirectMedia Layer
slouken@4498
     3
    Copyright (C) 1997-2010 Sam Lantinga
slouken@1933
     4
slouken@1933
     5
    This library is free software; you can redistribute it and/or
slouken@1933
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1933
     7
    License as published by the Free Software Foundation; either
slouken@1933
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1933
     9
slouken@1933
    10
    This library is distributed in the hope that it will be useful,
slouken@1933
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1933
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1933
    13
    Lesser General Public License for more details.
slouken@1933
    14
slouken@1933
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1933
    16
    License along with this library; if not, write to the Free Software
slouken@1933
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1933
    18
slouken@1933
    19
    Sam Lantinga
slouken@1933
    20
    slouken@libsdl.org
slouken@1933
    21
*/
slouken@1933
    22
#include "SDL_config.h"
slouken@1933
    23
slouken@1933
    24
#include "SDL_syswm.h"
slouken@1933
    25
#include "../SDL_sysvideo.h"
slouken@1933
    26
#include "../../events/SDL_keyboard_c.h"
slouken@1933
    27
#include "../../events/SDL_mouse_c.h"
slouken@4673
    28
#include "../../events/SDL_touch_c.h"
slouken@1933
    29
#include "../../events/SDL_windowevents_c.h"
slouken@1933
    30
#include "SDL_cocoavideo.h"
eligottlieb@4811
    31
#include "SDL_cocoashape.h"
gzjjgod@5057
    32
#include "SDL_cocoamouse.h"
slouken@1933
    33
slouken@1933
    34
static __inline__ void ConvertNSRect(NSRect *r)
slouken@1933
    35
{
slouken@1933
    36
    r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
slouken@1933
    37
}
slouken@1933
    38
slouken@1933
    39
@implementation Cocoa_WindowListener
slouken@1933
    40
slouken@1933
    41
- (void)listen:(SDL_WindowData *)data
slouken@1933
    42
{
slouken@1933
    43
    NSNotificationCenter *center;
slouken@1933
    44
slouken@1933
    45
    _data = data;
slouken@1933
    46
slouken@1933
    47
    center = [NSNotificationCenter defaultCenter];
slouken@1933
    48
slouken@3688
    49
    [_data->nswindow setNextResponder:self];
slouken@3688
    50
    if ([_data->nswindow delegate] != nil) {
slouken@3688
    51
        [center addObserver:self selector:@selector(windowDisExpose:) name:NSWindowDidExposeNotification object:_data->nswindow];
slouken@3688
    52
        [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:_data->nswindow];
slouken@3688
    53
        [center addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:_data->nswindow];
slouken@3688
    54
        [center addObserver:self selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:_data->nswindow];
slouken@3688
    55
        [center addObserver:self selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:_data->nswindow];
slouken@3688
    56
        [center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:_data->nswindow];
slouken@3688
    57
        [center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:_data->nswindow];
slouken@1933
    58
    } else {
slouken@3688
    59
        [_data->nswindow setDelegate:self];
slouken@1933
    60
    }
slouken@4927
    61
// FIXME: Why doesn't this work?
slouken@4927
    62
//    [center addObserver:self selector:@selector(rightMouseDown:) name:[NSString stringWithCString:"rightMouseDown" encoding:NSUTF8StringEncoding] object:[_data->nswindow contentView]];
slouken@1933
    63
    [center addObserver:self selector:@selector(windowDidHide:) name:NSApplicationDidHideNotification object:NSApp];
slouken@1933
    64
    [center addObserver:self selector:@selector(windowDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp];
slouken@1933
    65
slouken@3688
    66
    [_data->nswindow setAcceptsMouseMovedEvents:YES];
slouken@4927
    67
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
slouken@4673
    68
    [[_data->nswindow contentView] setAcceptsTouchEvents:YES];
slouken@4925
    69
#endif
slouken@1933
    70
}
slouken@1933
    71
slouken@1933
    72
- (void)close
slouken@1933
    73
{
slouken@1933
    74
    NSNotificationCenter *center;
slouken@1933
    75
slouken@1933
    76
    center = [NSNotificationCenter defaultCenter];
slouken@1933
    77
slouken@3688
    78
    [_data->nswindow setNextResponder:nil];
slouken@3688
    79
    if ([_data->nswindow delegate] != self) {
slouken@3688
    80
        [center removeObserver:self name:NSWindowDidExposeNotification object:_data->nswindow];
slouken@3688
    81
        [center removeObserver:self name:NSWindowDidMoveNotification object:_data->nswindow];
slouken@3688
    82
        [center removeObserver:self name:NSWindowDidResizeNotification object:_data->nswindow];
slouken@3688
    83
        [center removeObserver:self name:NSWindowDidMiniaturizeNotification object:_data->nswindow];
slouken@3688
    84
        [center removeObserver:self name:NSWindowDidDeminiaturizeNotification object:_data->nswindow];
slouken@3688
    85
        [center removeObserver:self name:NSWindowDidBecomeKeyNotification object:_data->nswindow];
slouken@3688
    86
        [center removeObserver:self name:NSWindowDidResignKeyNotification object:_data->nswindow];
slouken@1933
    87
    } else {
slouken@3688
    88
        [_data->nswindow setDelegate:nil];
slouken@1933
    89
    }
slouken@1933
    90
    [center removeObserver:self name:NSApplicationDidHideNotification object:NSApp];
slouken@1933
    91
    [center removeObserver:self name:NSApplicationDidUnhideNotification object:NSApp];
slouken@1933
    92
}
slouken@1933
    93
slouken@1933
    94
- (BOOL)windowShouldClose:(id)sender
slouken@1933
    95
{
slouken@3685
    96
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
slouken@1933
    97
    return NO;
slouken@1933
    98
}
slouken@1933
    99
slouken@1933
   100
- (void)windowDidExpose:(NSNotification *)aNotification
slouken@1933
   101
{
slouken@3685
   102
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
slouken@1933
   103
}
slouken@1933
   104
slouken@1933
   105
- (void)windowDidMove:(NSNotification *)aNotification
slouken@1933
   106
{
slouken@1933
   107
    int x, y;
slouken@3688
   108
    NSRect rect = [_data->nswindow contentRectForFrameRect:[_data->nswindow frame]];
slouken@1933
   109
    ConvertNSRect(&rect);
slouken@3507
   110
    x = (int)rect.origin.x;
slouken@3507
   111
    y = (int)rect.origin.y;
slouken@3685
   112
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MOVED, x, y);
slouken@1933
   113
}
slouken@1933
   114
slouken@1933
   115
- (void)windowDidResize:(NSNotification *)aNotification
slouken@1933
   116
{
slouken@1933
   117
    int w, h;
slouken@3688
   118
    NSRect rect = [_data->nswindow contentRectForFrameRect:[_data->nswindow frame]];
slouken@1933
   119
    w = (int)rect.size.width;
slouken@1933
   120
    h = (int)rect.size.height;
slouken@4937
   121
    if (SDL_IsShapedWindow(_data->window))
slouken@4937
   122
        Cocoa_ResizeWindowShape(_data->window);
slouken@3685
   123
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESIZED, w, h);
slouken@1933
   124
}
slouken@1933
   125
slouken@1933
   126
- (void)windowDidMiniaturize:(NSNotification *)aNotification
slouken@1933
   127
{
slouken@3685
   128
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
slouken@1933
   129
}
slouken@1933
   130
slouken@1933
   131
- (void)windowDidDeminiaturize:(NSNotification *)aNotification
slouken@1933
   132
{
slouken@3685
   133
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
slouken@1933
   134
}
slouken@1933
   135
slouken@1933
   136
- (void)windowDidBecomeKey:(NSNotification *)aNotification
slouken@1933
   137
{
slouken@3688
   138
    /* We're going to get keyboard events, since we're key. */
slouken@4465
   139
    SDL_SetKeyboardFocus(_data->window);
slouken@1962
   140
slouken@4503
   141
    /* Check to see if someone updated the clipboard */
slouken@4503
   142
    Cocoa_CheckClipboardUpdate(_data->videodata);
slouken@1933
   143
}
slouken@1933
   144
slouken@1933
   145
- (void)windowDidResignKey:(NSNotification *)aNotification
slouken@1933
   146
{
slouken@2059
   147
    /* Some other window will get mouse events, since we're not key. */
slouken@4465
   148
    if (SDL_GetMouseFocus() == _data->window) {
slouken@4465
   149
        SDL_SetMouseFocus(NULL);
slouken@2059
   150
    }
slouken@2059
   151
slouken@2059
   152
    /* Some other window will get keyboard events, since we're not key. */
slouken@4465
   153
    if (SDL_GetKeyboardFocus() == _data->window) {
slouken@4465
   154
        SDL_SetKeyboardFocus(NULL);
slouken@4465
   155
    }
slouken@1933
   156
}
slouken@1933
   157
slouken@1933
   158
- (void)windowDidHide:(NSNotification *)aNotification
slouken@1933
   159
{
slouken@3685
   160
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
slouken@1933
   161
}
slouken@1933
   162
slouken@1933
   163
- (void)windowDidUnhide:(NSNotification *)aNotification
slouken@1933
   164
{
slouken@3685
   165
    SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
slouken@1933
   166
}
slouken@1933
   167
slouken@1933
   168
- (void)mouseDown:(NSEvent *)theEvent
slouken@1933
   169
{
slouken@1959
   170
    int button;
slouken@1933
   171
slouken@1959
   172
    switch ([theEvent buttonNumber]) {
slouken@1959
   173
    case 0:
slouken@1959
   174
        button = SDL_BUTTON_LEFT;
slouken@1959
   175
        break;
slouken@1959
   176
    case 1:
slouken@1959
   177
        button = SDL_BUTTON_RIGHT;
slouken@1959
   178
        break;
slouken@1959
   179
    case 2:
slouken@1959
   180
        button = SDL_BUTTON_MIDDLE;
slouken@1959
   181
        break;
slouken@1959
   182
    default:
slouken@5061
   183
        button = [theEvent buttonNumber] + 1;
slouken@1959
   184
        break;
slouken@1959
   185
    }
slouken@4484
   186
    SDL_SendMouseButton(_data->window, SDL_PRESSED, button);
slouken@1933
   187
}
slouken@1933
   188
slouken@1933
   189
- (void)rightMouseDown:(NSEvent *)theEvent
slouken@1933
   190
{
slouken@1959
   191
    [self mouseDown:theEvent];
slouken@1933
   192
}
slouken@1933
   193
slouken@1933
   194
- (void)otherMouseDown:(NSEvent *)theEvent
slouken@1933
   195
{
slouken@1959
   196
    [self mouseDown:theEvent];
slouken@1933
   197
}
slouken@1933
   198
slouken@1933
   199
- (void)mouseUp:(NSEvent *)theEvent
slouken@1933
   200
{
slouken@1959
   201
    int button;
slouken@1933
   202
slouken@1959
   203
    switch ([theEvent buttonNumber]) {
slouken@1959
   204
    case 0:
slouken@1959
   205
        button = SDL_BUTTON_LEFT;
slouken@1959
   206
        break;
slouken@1959
   207
    case 1:
slouken@1959
   208
        button = SDL_BUTTON_RIGHT;
slouken@1959
   209
        break;
slouken@1959
   210
    case 2:
slouken@1959
   211
        button = SDL_BUTTON_MIDDLE;
slouken@1959
   212
        break;
slouken@1959
   213
    default:
slouken@5061
   214
        button = [theEvent buttonNumber] + 1;
slouken@1959
   215
        break;
slouken@1959
   216
    }
slouken@4484
   217
    SDL_SendMouseButton(_data->window, SDL_RELEASED, button);
slouken@1933
   218
}
slouken@1933
   219
slouken@1933
   220
- (void)rightMouseUp:(NSEvent *)theEvent
slouken@1933
   221
{
slouken@1959
   222
    [self mouseUp:theEvent];
slouken@1933
   223
}
slouken@1933
   224
slouken@1933
   225
- (void)otherMouseUp:(NSEvent *)theEvent
slouken@1933
   226
{
slouken@1959
   227
    [self mouseUp:theEvent];
slouken@1933
   228
}
slouken@1933
   229
slouken@1933
   230
- (void)mouseMoved:(NSEvent *)theEvent
slouken@1933
   231
{
slouken@3685
   232
    SDL_Window *window = _data->window;
slouken@1933
   233
    NSPoint point;
slouken@1933
   234
gzjjgod@5059
   235
    if (window->flags & SDL_WINDOW_FULLSCREEN)
gzjjgod@5059
   236
        return;
gzjjgod@5059
   237
slouken@3517
   238
    point = [theEvent locationInWindow];
slouken@3517
   239
    point.y = window->h - point.y;
slouken@3507
   240
    if ( point.x < 0 || point.x >= window->w ||
slouken@3507
   241
         point.y < 0 || point.y >= window->h ) {
slouken@4465
   242
        if (SDL_GetMouseFocus() == window) {
slouken@4465
   243
            SDL_SetMouseFocus(NULL);
slouken@2059
   244
        }
slouken@2059
   245
    } else {
slouken@4484
   246
        SDL_SendMouseMotion(window, 0, (int)point.x, (int)point.y);
slouken@2059
   247
    }
slouken@1933
   248
}
slouken@1933
   249
slouken@1957
   250
- (void)mouseDragged:(NSEvent *)theEvent
slouken@1957
   251
{
slouken@1957
   252
    [self mouseMoved:theEvent];
slouken@1957
   253
}
slouken@1957
   254
slouken@1958
   255
- (void)rightMouseDragged:(NSEvent *)theEvent
slouken@1958
   256
{
slouken@1958
   257
    [self mouseMoved:theEvent];
slouken@1958
   258
}
slouken@1958
   259
slouken@1958
   260
- (void)otherMouseDragged:(NSEvent *)theEvent
slouken@1958
   261
{
slouken@1958
   262
    [self mouseMoved:theEvent];
slouken@1958
   263
}
slouken@1958
   264
slouken@1933
   265
- (void)scrollWheel:(NSEvent *)theEvent
slouken@1933
   266
{
gzjjgod@5057
   267
    Cocoa_HandleMouseWheel(_data->window, theEvent);
slouken@3688
   268
}
slouken@3688
   269
slouken@4673
   270
- (void)touchesBeganWithEvent:(NSEvent *) theEvent
slouken@4673
   271
{
slouken@4673
   272
    [self handleTouches:COCOA_TOUCH_DOWN withEvent:theEvent];
slouken@4673
   273
}
slouken@4673
   274
slouken@4673
   275
- (void)touchesMovedWithEvent:(NSEvent *) theEvent
slouken@4673
   276
{
slouken@4673
   277
    [self handleTouches:COCOA_TOUCH_MOVE withEvent:theEvent];
slouken@4673
   278
}
slouken@4673
   279
slouken@4673
   280
- (void)touchesEndedWithEvent:(NSEvent *) theEvent
slouken@4673
   281
{
slouken@4673
   282
    [self handleTouches:COCOA_TOUCH_UP withEvent:theEvent];
slouken@4673
   283
}
slouken@4673
   284
slouken@4673
   285
- (void)touchesCancelledWithEvent:(NSEvent *) theEvent
slouken@4673
   286
{
slouken@4673
   287
    [self handleTouches:COCOA_TOUCH_CANCELLED withEvent:theEvent];
slouken@4673
   288
}
slouken@4673
   289
slouken@4673
   290
- (void)handleTouches:(cocoaTouchType)type withEvent:(NSEvent *)event
slouken@4673
   291
{
slouken@4927
   292
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
slouken@4680
   293
    NSSet *touches = 0;
slouken@4680
   294
    NSEnumerator *enumerator;
slouken@4680
   295
    NSTouch *touch;
slouken@4673
   296
slouken@4680
   297
    switch (type) {
slouken@4680
   298
        case COCOA_TOUCH_DOWN:
slouken@4680
   299
            touches = [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil];
slouken@4680
   300
            break;
slouken@4680
   301
        case COCOA_TOUCH_UP:
slouken@4680
   302
        case COCOA_TOUCH_CANCELLED:
slouken@4680
   303
            touches = [event touchesMatchingPhase:NSTouchPhaseEnded inView:nil];
slouken@4680
   304
            break;
slouken@4680
   305
        case COCOA_TOUCH_MOVE:
slouken@4680
   306
            touches = [event touchesMatchingPhase:NSTouchPhaseMoved inView:nil];
slouken@4680
   307
            break;
slouken@4680
   308
    }
slouken@4680
   309
slouken@4680
   310
    enumerator = [touches objectEnumerator];
slouken@4680
   311
    touch = (NSTouch*)[enumerator nextObject];
slouken@4673
   312
    while (touch) {
slouken@4680
   313
        SDL_TouchID touchId = (SDL_TouchID)[touch device];
slouken@4673
   314
        if (!SDL_GetTouch(touchId)) {
slouken@4673
   315
            SDL_Touch touch;
slouken@4673
   316
slouken@4673
   317
            touch.id = touchId;
slouken@4673
   318
            touch.x_min = 0;
slouken@4673
   319
            touch.x_max = 1;
jimtla@4678
   320
            touch.native_xres = touch.x_max - touch.x_min;
slouken@4673
   321
            touch.y_min = 0;
slouken@4673
   322
            touch.y_max = 1;
jimtla@4678
   323
            touch.native_yres = touch.y_max - touch.y_min;
slouken@4673
   324
            touch.pressure_min = 0;
slouken@4673
   325
            touch.pressure_max = 1;
jimtla@4678
   326
            touch.native_pressureres = touch.pressure_max - touch.pressure_min;
slouken@4673
   327
            
slouken@4673
   328
            if (SDL_AddTouch(&touch, "") < 0) {
slouken@4680
   329
                return;
slouken@4673
   330
            }
slouken@4673
   331
        } 
slouken@4687
   332
slouken@4687
   333
        SDL_FingerID fingerId = (SDL_FingerID)[touch identity];
slouken@4673
   334
        float x = [touch normalizedPosition].x;
slouken@4673
   335
        float y = [touch normalizedPosition].y;
slouken@4687
   336
	/* Make the origin the upper left instead of the lower left */
slouken@4687
   337
	y = 1.0f - y;
slouken@4687
   338
slouken@4673
   339
        switch (type) {
slouken@4673
   340
        case COCOA_TOUCH_DOWN:
slouken@4673
   341
            SDL_SendFingerDown(touchId, fingerId, SDL_TRUE, x, y, 1);
slouken@4673
   342
            break;
slouken@4673
   343
        case COCOA_TOUCH_UP:
slouken@4673
   344
        case COCOA_TOUCH_CANCELLED:
slouken@4673
   345
            SDL_SendFingerDown(touchId, fingerId, SDL_FALSE, x, y, 1);
slouken@4673
   346
            break;
slouken@4673
   347
        case COCOA_TOUCH_MOVE:
slouken@4673
   348
            SDL_SendTouchMotion(touchId, fingerId, SDL_FALSE, x, y, 1);
slouken@4673
   349
            break;
slouken@4673
   350
        }
slouken@4673
   351
        
slouken@4673
   352
        touch = (NSTouch*)[enumerator nextObject];
slouken@4673
   353
    }
slouken@4927
   354
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 */
slouken@1933
   355
}
slouken@1933
   356
slouken@1933
   357
@end
slouken@1933
   358
slouken@1973
   359
@interface SDLWindow : NSWindow
slouken@1973
   360
/* These are needed for borderless/fullscreen windows */
slouken@1973
   361
- (BOOL)canBecomeKeyWindow;
slouken@1973
   362
- (BOOL)canBecomeMainWindow;
slouken@1973
   363
@end
slouken@1973
   364
slouken@1973
   365
@implementation SDLWindow
slouken@1973
   366
- (BOOL)canBecomeKeyWindow
slouken@1973
   367
{
slouken@1973
   368
    return YES;
slouken@1973
   369
}
slouken@1973
   370
slouken@1973
   371
- (BOOL)canBecomeMainWindow
slouken@1973
   372
{
slouken@1973
   373
    return YES;
slouken@1973
   374
}
slouken@1973
   375
@end
slouken@1973
   376
gzjjgod@4915
   377
@interface SDLView : NSView {
gzjjgod@4915
   378
    Cocoa_WindowListener *listener;
gzjjgod@4915
   379
}
gzjjgod@4915
   380
@end
gzjjgod@4915
   381
gzjjgod@4915
   382
@implementation SDLView
gzjjgod@4915
   383
gzjjgod@4915
   384
- (id) initWithFrame: (NSRect) rect
gzjjgod@4915
   385
            listener: (Cocoa_WindowListener *) theListener
gzjjgod@4915
   386
{
gzjjgod@4915
   387
    if (self = [super initWithFrame:rect]) {
gzjjgod@4915
   388
        listener = theListener;
gzjjgod@4915
   389
    }
gzjjgod@4915
   390
gzjjgod@4915
   391
    return self;
gzjjgod@4915
   392
}
gzjjgod@4915
   393
gzjjgod@4915
   394
- (void)rightMouseDown:(NSEvent *)theEvent
gzjjgod@4915
   395
{
gzjjgod@4915
   396
    [listener mouseDown:theEvent];
gzjjgod@4915
   397
}
gzjjgod@4915
   398
gzjjgod@4915
   399
@end
gzjjgod@4915
   400
slouken@5249
   401
static unsigned int
slouken@5249
   402
GetStyleMask(SDL_Window * window)
slouken@5249
   403
{
slouken@5249
   404
    unsigned int style;
slouken@5249
   405
slouken@5249
   406
    if (window->flags & SDL_WINDOW_BORDERLESS) {
slouken@5249
   407
        style = NSBorderlessWindowMask;
slouken@5249
   408
    } else {
slouken@5249
   409
        style = (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask);
slouken@5249
   410
    }
slouken@5249
   411
    if (window->flags & SDL_WINDOW_RESIZABLE) {
slouken@5249
   412
        style |= NSResizableWindowMask;
slouken@5249
   413
    }
slouken@5249
   414
    return style;
slouken@5249
   415
}
slouken@5249
   416
slouken@1933
   417
static int
slouken@1951
   418
SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created)
slouken@1933
   419
{
slouken@1933
   420
    NSAutoreleasePool *pool;
slouken@1951
   421
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@1933
   422
    SDL_WindowData *data;
slouken@1933
   423
slouken@1933
   424
    /* Allocate the window data */
slouken@5249
   425
    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
slouken@1933
   426
    if (!data) {
slouken@1933
   427
        SDL_OutOfMemory();
slouken@1933
   428
        return -1;
slouken@1933
   429
    }
slouken@3685
   430
    data->window = window;
slouken@3688
   431
    data->nswindow = nswindow;
slouken@1933
   432
    data->created = created;
slouken@1951
   433
    data->videodata = videodata;
slouken@1933
   434
slouken@1933
   435
    pool = [[NSAutoreleasePool alloc] init];
slouken@1933
   436
slouken@1933
   437
    /* Create an event listener for the window */
slouken@1933
   438
    data->listener = [[Cocoa_WindowListener alloc] init];
slouken@1933
   439
    [data->listener listen:data];
slouken@1933
   440
slouken@1933
   441
    /* Fill in the SDL window with the window data */
slouken@1933
   442
    {
slouken@1933
   443
        NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
gzjjgod@4915
   444
        NSView *contentView = [[SDLView alloc] initWithFrame: rect
gzjjgod@4915
   445
                                                    listener: data->listener];
slouken@4927
   446
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
slouken@4927
   447
        [contentView setAcceptsTouchEvents:YES];
slouken@4927
   448
#endif
gzjjgod@4915
   449
        [nswindow setContentView: contentView];
gzjjgod@4915
   450
        [contentView release];
gzjjgod@4915
   451
slouken@1933
   452
        ConvertNSRect(&rect);
slouken@5246
   453
        window->x = (int)rect.origin.x;
slouken@5246
   454
        window->y = (int)rect.origin.y;
slouken@1933
   455
        window->w = (int)rect.size.width;
slouken@1933
   456
        window->h = (int)rect.size.height;
slouken@1933
   457
    }
slouken@1933
   458
    if ([nswindow isVisible]) {
slouken@1933
   459
        window->flags |= SDL_WINDOW_SHOWN;
slouken@1933
   460
    } else {
slouken@1933
   461
        window->flags &= ~SDL_WINDOW_SHOWN;
slouken@1933
   462
    }
slouken@1933
   463
    {
slouken@1933
   464
        unsigned int style = [nswindow styleMask];
slouken@1933
   465
slouken@1956
   466
        if ((style & ~NSResizableWindowMask) == NSBorderlessWindowMask) {
slouken@1933
   467
            window->flags |= SDL_WINDOW_BORDERLESS;
slouken@1933
   468
        } else {
slouken@1933
   469
            window->flags &= ~SDL_WINDOW_BORDERLESS;
slouken@1933
   470
        }
slouken@1933
   471
        if (style & NSResizableWindowMask) {
slouken@1933
   472
            window->flags |= SDL_WINDOW_RESIZABLE;
slouken@1933
   473
        } else {
slouken@1933
   474
            window->flags &= ~SDL_WINDOW_RESIZABLE;
slouken@1933
   475
        }
slouken@1933
   476
    }
slouken@1933
   477
    if ([nswindow isZoomed]) {
slouken@1933
   478
        window->flags |= SDL_WINDOW_MAXIMIZED;
slouken@1933
   479
    } else {
slouken@1933
   480
        window->flags &= ~SDL_WINDOW_MAXIMIZED;
slouken@1933
   481
    }
slouken@1933
   482
    if ([nswindow isMiniaturized]) {
slouken@1933
   483
        window->flags |= SDL_WINDOW_MINIMIZED;
slouken@1933
   484
    } else {
slouken@1933
   485
        window->flags &= ~SDL_WINDOW_MINIMIZED;
slouken@1933
   486
    }
slouken@1933
   487
    if ([nswindow isKeyWindow]) {
slouken@1933
   488
        window->flags |= SDL_WINDOW_INPUT_FOCUS;
slouken@4465
   489
        SDL_SetKeyboardFocus(data->window);
slouken@1933
   490
slouken@1933
   491
        if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@1933
   492
            /* FIXME */
slouken@1933
   493
        }
slouken@1933
   494
    }
slouken@1933
   495
slouken@1933
   496
    /* All done! */
slouken@1933
   497
    [pool release];
slouken@1933
   498
    window->driverdata = data;
slouken@1933
   499
    return 0;
slouken@1933
   500
}
slouken@1933
   501
slouken@1933
   502
int
slouken@1933
   503
Cocoa_CreateWindow(_THIS, SDL_Window * window)
slouken@1933
   504
{
slouken@3506
   505
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@1933
   506
    NSWindow *nswindow;
slouken@5246
   507
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@1933
   508
    NSRect rect;
slouken@3528
   509
    SDL_Rect bounds;
slouken@1933
   510
    unsigned int style;
slouken@1933
   511
slouken@3528
   512
    Cocoa_GetDisplayBounds(_this, display, &bounds);
slouken@5249
   513
    if (SDL_WINDOWPOS_ISCENTERED(window->x)) {
slouken@3528
   514
        rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
slouken@5246
   515
    } else if (SDL_WINDOWPOS_ISUNDEFINED(window->x)) {
slouken@3528
   516
        rect.origin.x = bounds.x;
slouken@3528
   517
    } else {
slouken@5246
   518
        rect.origin.x = window->x;
slouken@1933
   519
    }
slouken@5249
   520
    if (SDL_WINDOWPOS_ISCENTERED(window->y)) {
slouken@3528
   521
        rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
slouken@5246
   522
    } else if (SDL_WINDOWPOS_ISUNDEFINED(window->y)) {
slouken@3528
   523
        rect.origin.y = bounds.y;
slouken@3528
   524
    } else {
slouken@5246
   525
        rect.origin.y = window->y;
slouken@1933
   526
    }
slouken@1933
   527
    rect.size.width = window->w;
slouken@1933
   528
    rect.size.height = window->h;
slouken@1933
   529
    ConvertNSRect(&rect);
slouken@1933
   530
slouken@5249
   531
    style = GetStyleMask(window);
slouken@1933
   532
slouken@3506
   533
    /* Figure out which screen to place this window */
slouken@3506
   534
    NSArray *screens = [NSScreen screens];
slouken@3506
   535
    NSScreen *screen = nil;
slouken@3506
   536
    NSScreen *candidate;
slouken@3525
   537
    int i, count = [screens count];
slouken@3525
   538
    for (i = 0; i < count; ++i) {
slouken@3529
   539
        candidate = [screens objectAtIndex:i];
slouken@3506
   540
        NSRect screenRect = [candidate frame];
slouken@3506
   541
        if (rect.origin.x >= screenRect.origin.x &&
slouken@3506
   542
            rect.origin.x < screenRect.origin.x + screenRect.size.width &&
slouken@3506
   543
            rect.origin.y >= screenRect.origin.y &&
slouken@3506
   544
            rect.origin.y < screenRect.origin.y + screenRect.size.height) {
slouken@3506
   545
            screen = candidate;
slouken@3506
   546
            rect.origin.x -= screenRect.origin.x;
slouken@3506
   547
            rect.origin.y -= screenRect.origin.y;
slouken@3506
   548
        }
slouken@3506
   549
    }
slouken@3506
   550
    nswindow = [[SDLWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:FALSE screen:screen];
slouken@1933
   551
slouken@1933
   552
    [pool release];
slouken@1933
   553
slouken@1951
   554
    if (SetupWindowData(_this, window, nswindow, SDL_TRUE) < 0) {
slouken@1933
   555
        [nswindow release];
slouken@1933
   556
        return -1;
slouken@1933
   557
    }
slouken@1933
   558
    return 0;
slouken@1933
   559
}
slouken@1933
   560
slouken@1933
   561
int
slouken@1933
   562
Cocoa_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@1933
   563
{
slouken@1933
   564
    NSAutoreleasePool *pool;
slouken@1933
   565
    NSWindow *nswindow = (NSWindow *) data;
slouken@1933
   566
    NSString *title;
slouken@1933
   567
slouken@1933
   568
    pool = [[NSAutoreleasePool alloc] init];
slouken@1933
   569
slouken@1933
   570
    /* Query the title from the existing window */
slouken@1933
   571
    title = [nswindow title];
slouken@1933
   572
    if (title) {
slouken@1933
   573
        window->title = SDL_strdup([title UTF8String]);
slouken@1933
   574
    }
slouken@1933
   575
slouken@1933
   576
    [pool release];
slouken@1933
   577
slouken@1951
   578
    return SetupWindowData(_this, window, nswindow, SDL_FALSE);
slouken@1933
   579
}
slouken@1933
   580
slouken@1933
   581
void
slouken@1933
   582
Cocoa_SetWindowTitle(_THIS, SDL_Window * window)
slouken@1933
   583
{
slouken@1937
   584
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@3688
   585
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   586
    NSString *string;
slouken@1933
   587
slouken@1956
   588
    if(window->title) {
slouken@1956
   589
        string = [[NSString alloc] initWithUTF8String:window->title];
slouken@1956
   590
    } else {
slouken@1956
   591
        string = [[NSString alloc] init];
slouken@1956
   592
    }
slouken@1933
   593
    [nswindow setTitle:string];
slouken@1933
   594
    [string release];
slouken@1956
   595
slouken@1937
   596
    [pool release];
slouken@1933
   597
}
slouken@1933
   598
slouken@1933
   599
void
slouken@1933
   600
Cocoa_SetWindowPosition(_THIS, SDL_Window * window)
slouken@1933
   601
{
slouken@1937
   602
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@3688
   603
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@5246
   604
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@1933
   605
    NSRect rect;
slouken@3528
   606
    SDL_Rect bounds;
slouken@1933
   607
slouken@3528
   608
    Cocoa_GetDisplayBounds(_this, display, &bounds);
slouken@5249
   609
    if (SDL_WINDOWPOS_ISCENTERED(window->x)) {
slouken@3528
   610
        rect.origin.x = bounds.x + (bounds.w - window->w) / 2;
slouken@3075
   611
    } else {
slouken@5246
   612
        rect.origin.x = window->x;
slouken@3075
   613
    }
slouken@5249
   614
    if (SDL_WINDOWPOS_ISCENTERED(window->y)) {
slouken@3528
   615
        rect.origin.y = bounds.y + (bounds.h - window->h) / 2;
slouken@3075
   616
    } else {
slouken@5246
   617
        rect.origin.y = window->y;
slouken@3075
   618
    }
slouken@1933
   619
    rect.size.width = window->w;
slouken@1933
   620
    rect.size.height = window->h;
slouken@1933
   621
    ConvertNSRect(&rect);
slouken@1933
   622
    rect = [nswindow frameRectForContentRect:rect];
slouken@1933
   623
    [nswindow setFrameOrigin:rect.origin];
slouken@1937
   624
    [pool release];
slouken@1933
   625
}
slouken@1933
   626
slouken@1933
   627
void
slouken@1933
   628
Cocoa_SetWindowSize(_THIS, SDL_Window * window)
slouken@1933
   629
{
slouken@1937
   630
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@3688
   631
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   632
    NSSize size;
slouken@1933
   633
slouken@1933
   634
    size.width = window->w;
slouken@1933
   635
    size.height = window->h;
slouken@1933
   636
    [nswindow setContentSize:size];
slouken@1937
   637
    [pool release];
slouken@1933
   638
}
slouken@1933
   639
slouken@1933
   640
void
slouken@1933
   641
Cocoa_ShowWindow(_THIS, SDL_Window * window)
slouken@1933
   642
{
slouken@1937
   643
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@3688
   644
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   645
slouken@1956
   646
    if (![nswindow isMiniaturized]) {
slouken@1956
   647
        [nswindow makeKeyAndOrderFront:nil];
slouken@1956
   648
    }
slouken@1937
   649
    [pool release];
slouken@1933
   650
}
slouken@1933
   651
slouken@1933
   652
void
slouken@1933
   653
Cocoa_HideWindow(_THIS, SDL_Window * window)
slouken@1933
   654
{
slouken@1956
   655
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@3688
   656
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   657
slouken@1956
   658
    [nswindow orderOut:nil];
slouken@1956
   659
    [pool release];
slouken@1933
   660
}
slouken@1933
   661
slouken@1933
   662
void
slouken@1933
   663
Cocoa_RaiseWindow(_THIS, SDL_Window * window)
slouken@1933
   664
{
slouken@1937
   665
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@3688
   666
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   667
slouken@1933
   668
    [nswindow makeKeyAndOrderFront:nil];
slouken@1937
   669
    [pool release];
slouken@1933
   670
}
slouken@1933
   671
slouken@1933
   672
void
slouken@1933
   673
Cocoa_MaximizeWindow(_THIS, SDL_Window * window)
slouken@1933
   674
{
slouken@1937
   675
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@3688
   676
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   677
slouken@1956
   678
    [nswindow zoom:nil];
slouken@1937
   679
    [pool release];
slouken@1933
   680
}
slouken@1933
   681
slouken@1933
   682
void
slouken@1933
   683
Cocoa_MinimizeWindow(_THIS, SDL_Window * window)
slouken@1933
   684
{
slouken@1937
   685
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@3688
   686
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   687
slouken@1956
   688
    [nswindow miniaturize:nil];
slouken@1937
   689
    [pool release];
slouken@1933
   690
}
slouken@1933
   691
slouken@1933
   692
void
slouken@1933
   693
Cocoa_RestoreWindow(_THIS, SDL_Window * window)
slouken@1933
   694
{
slouken@1956
   695
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@3688
   696
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   697
slouken@1956
   698
    if ([nswindow isMiniaturized]) {
slouken@1956
   699
        [nswindow deminiaturize:nil];
slouken@1956
   700
    } else if ([nswindow isZoomed]) {
slouken@1956
   701
        [nswindow zoom:nil];
slouken@1956
   702
    }
slouken@1956
   703
    [pool release];
slouken@1933
   704
}
slouken@1933
   705
slouken@1933
   706
void
slouken@5249
   707
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window)
slouken@5249
   708
{
slouken@5249
   709
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@5249
   710
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5249
   711
    NSWindow *nswindow = data->nswindow;
slouken@5249
   712
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@5249
   713
    NSRect rect;
slouken@5249
   714
    unsigned int style;
slouken@5249
   715
slouken@5249
   716
    if (FULLSCREEN_VISIBLE(window)) {
slouken@5249
   717
        SDL_Rect bounds;
slouken@5249
   718
slouken@5249
   719
        Cocoa_GetDisplayBounds(_this, display, &bounds);
slouken@5249
   720
        rect.origin.x = bounds.x;
slouken@5249
   721
        rect.origin.y = bounds.y;
slouken@5249
   722
        rect.size.width = bounds.w;
slouken@5249
   723
        rect.size.height = bounds.h;
slouken@5249
   724
        ConvertNSRect(&rect);
slouken@5249
   725
slouken@5249
   726
        style = NSBorderlessWindowMask;
slouken@5249
   727
    } else {
slouken@5249
   728
        rect.origin.x = window->windowed.x;
slouken@5249
   729
        rect.origin.y = window->windowed.y;
slouken@5249
   730
        rect.size.width = window->windowed.w;
slouken@5249
   731
        rect.size.height = window->windowed.h;
slouken@5249
   732
        /* FIXME: This calculation is wrong, we're changing the origin */
slouken@5249
   733
        ConvertNSRect(&rect);
slouken@5249
   734
slouken@5249
   735
        style = GetStyleMask(window);
slouken@5249
   736
    }
slouken@5249
   737
slouken@5249
   738
    [nswindow setStyleMask:style];
slouken@5249
   739
    [nswindow setContentSize:rect.size];
slouken@5249
   740
    rect = [nswindow frameRectForContentRect:rect];
slouken@5249
   741
    [nswindow setFrameOrigin:rect.origin];
slouken@5249
   742
slouken@5249
   743
#ifdef FULLSCREEN_TOGGLEABLE
slouken@5249
   744
    if (FULLSCREEN_VISIBLE(window)) {
slouken@5249
   745
        /* OpenGL is rendering to the window, so make it visible! */
slouken@5249
   746
        [nswindow setLevel:CGShieldingWindowLevel()];
slouken@5249
   747
    } else {
slouken@5249
   748
        [nswindow setLevel:kCGNormalWindowLevel];
slouken@5249
   749
    }
slouken@5249
   750
#endif
slouken@5249
   751
    [nswindow makeKeyAndOrderFront:nil];
slouken@5249
   752
slouken@5249
   753
    [pool release];
slouken@5249
   754
}
slouken@5249
   755
slouken@5249
   756
void
slouken@1933
   757
Cocoa_SetWindowGrab(_THIS, SDL_Window * window)
slouken@1933
   758
{
slouken@1933
   759
    if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
slouken@1933
   760
        (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@1933
   761
        /* FIXME: Grab mouse */
slouken@1933
   762
    } else {
slouken@1933
   763
        /* FIXME: Release mouse */
slouken@1933
   764
    }
slouken@1933
   765
}
slouken@1933
   766
slouken@1933
   767
void
slouken@1933
   768
Cocoa_DestroyWindow(_THIS, SDL_Window * window)
slouken@1933
   769
{
slouken@1937
   770
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
slouken@1933
   771
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1933
   772
slouken@1933
   773
    if (data) {
slouken@1933
   774
        [data->listener close];
slouken@1933
   775
        [data->listener release];
slouken@1933
   776
        if (data->created) {
slouken@3688
   777
            [data->nswindow close];
slouken@1933
   778
        }
slouken@1933
   779
        SDL_free(data);
slouken@1933
   780
    }
slouken@1937
   781
    [pool release];
slouken@1933
   782
}
slouken@1933
   783
slouken@1933
   784
SDL_bool
slouken@1933
   785
Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
slouken@1933
   786
{
slouken@4900
   787
    NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
slouken@1933
   788
slouken@1933
   789
    if (info->version.major <= SDL_MAJOR_VERSION) {
slouken@4900
   790
        info->subsystem = SDL_SYSWM_COCOA;
slouken@5056
   791
        info->info.cocoa.window = nswindow;
slouken@1933
   792
        return SDL_TRUE;
slouken@1933
   793
    } else {
slouken@1933
   794
        SDL_SetError("Application not compiled with SDL %d.%d\n",
slouken@1933
   795
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@1933
   796
        return SDL_FALSE;
slouken@1933
   797
    }
slouken@1933
   798
}
slouken@1933
   799
slouken@1933
   800
/* vi: set ts=4 sw=4 expandtab: */