src/video/cocoa/SDL_cocoawindow.m
author Jørgen P. Tjernø <jorgen@valvesoftware.com>
Tue, 25 Feb 2014 17:27:41 -0800
changeset 8260 028ed8da2524
parent 8258 569354dec4e9
child 8261 841b66e4397a
permissions -rw-r--r--
Mac: Improve moving relative mode windows.

This makes it possible to move windows by their title bar, even if they're in
relative mode, if you click the title bar when the window does not have focus.

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