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