src/video/cocoa/SDL_cocoawindow.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Mar 2011 08:49:20 -0800
changeset 5466 006883d5fa51
parent 5406 1517da4ab6b1
child 5478 6b65ff3cee62
permissions -rw-r--r--
Gamma support is back!

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