diff src/video/quartz/SDL_QuartzWM.m @ 1708:cd14138a8703 SDL-1.3

Merged fix for bug #240 from SDL 1.2
author Sam Lantinga <slouken@libsdl.org>
date Sat, 24 Jun 2006 17:31:46 +0000
parents 782fd950bd46
children
line wrap: on
line diff
--- a/src/video/quartz/SDL_QuartzWM.m	Sat Jun 24 17:01:29 2006 +0000
+++ b/src/video/quartz/SDL_QuartzWM.m	Sat Jun 24 17:31:46 2006 +0000
@@ -26,57 +26,82 @@
 
 struct WMcursor
 {
-    Cursor curs;
+    NSCursor *nscursor;
 };
 
 void
-QZ_FreeWMCursor (_THIS, WMcursor * cursor)
+QZ_FreeWMCursor(_THIS, WMcursor * cursor)
 {
 
-    if (cursor != NULL)
-        free (cursor);
+    if (cursor != NULL) {
+        [cursor->nscursor release];
+        free(cursor);
+    }
 }
 
-/* Use the Carbon cursor routines for now */
 WMcursor *
-QZ_CreateWMCursor (_THIS, Uint8 * data, Uint8 * mask,
-                   int w, int h, int hot_x, int hot_y)
+QZ_CreateWMCursor(_THIS, Uint8 * data, Uint8 * mask,
+                  int w, int h, int hot_x, int hot_y)
 {
     WMcursor *cursor;
-    int row, bytes;
+    NSBitmapImageRep *imgrep;
+    NSImage *img;
+    unsigned char *planes[5];
+    int i;
+    NSAutoreleasePool *pool;
+
+    pool =[[NSAutoreleasePool alloc] init];
 
     /* Allocate the cursor memory */
-    cursor = (WMcursor *) SDL_malloc (sizeof (WMcursor));
-    if (cursor == NULL) {
-        SDL_OutOfMemory ();
-        return (NULL);
+    cursor = (WMcursor *) SDL_malloc(sizeof(WMcursor));
+    if (cursor == NULL)
+        goto outOfMemory;
+
+    /* create the image representation and get the pointers to its storage */
+  imgrep =[[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL pixelsWide: w pixelsHigh: h bitsPerSample: 1 samplesPerPixel: 2 hasAlpha: YES isPlanar: YES colorSpaceName: NSDeviceBlackColorSpace bytesPerRow: (w + 7) / 8 bitsPerPixel:0] autorelease];
+    if (imgrep == nil)
+        goto outOfMemory;
+  [imgrep getBitmapDataPlanes:planes];
+
+    /* copy data and mask, extending the mask to all black pixels because the inversion effect doesn't work with Cocoa's alpha-blended cursors */
+    for (i = 0; i < (w + 7) / 8 * h; i++) {
+        planes[0][i] = data[i];
+        planes[1][i] = mask[i] | data[i];
     }
-    SDL_memset (cursor, 0, sizeof (*cursor));
-
-    if (w > 16)
-        w = 16;
-
-    if (h > 16)
-        h = 16;
 
-    bytes = (w + 7) / 8;
-
-    for (row = 0; row < h; ++row) {
-        SDL_memcpy (&cursor->curs.data[row], data, bytes);
-        data += bytes;
+    /* create image and cursor */
+  img =[[[NSImage alloc] initWithSize:NSMakeSize(w, h)] autorelease];
+    if (img == nil)
+        goto outOfMemory;
+  [img addRepresentation:imgrep];
+    if (system_version < 0x1030) {      /* on 10.2, cursors must be 16*16 */
+        if (w > 16 || h > 16) { /* too big: scale it down */
+          [img setScalesWhenResized:YES];
+            hot_x = hot_x * 16 / w;
+            hot_y = hot_y * 16 / h;
+        } else {                /* too small (or just right): extend it (from the bottom left corner, so hot_y must be adjusted) */
+            hot_y += 16 - h;
+        }
+      [img setSize:NSMakeSize(16, 16)];
     }
-    for (row = 0; row < h; ++row) {
-        SDL_memcpy (&cursor->curs.mask[row], mask, bytes);
-        mask += bytes;
-    }
-    cursor->curs.hotSpot.h = hot_x;
-    cursor->curs.hotSpot.v = hot_y;
+  cursor->nscursor =[[NSCursor alloc] initWithImage: img hotSpot:NSMakePoint(hot_x,
+                hot_y)];
+    if (cursor->nscursor == nil)
+        goto outOfMemory;
 
+    [pool release];
     return (cursor);
+
+  outOfMemory:
+    [pool release];
+    if (cursor != NULL)
+        SDL_free(cursor);
+    SDL_OutOfMemory();
+    return (NULL);
 }
 
 void
-QZ_ShowMouse (_THIS)
+QZ_ShowMouse(_THIS)
 {
     if (!cursor_visible) {
         [NSCursor unhide];
@@ -85,42 +110,42 @@
 }
 
 void
-QZ_HideMouse (_THIS)
+QZ_HideMouse(_THIS)
 {
-    if ((SDL_GetAppState () & SDL_APPMOUSEFOCUS) && cursor_visible) {
+    if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) && cursor_visible) {
         [NSCursor hide];
         cursor_visible = NO;
     }
 }
 
 BOOL
-QZ_IsMouseInWindow (_THIS)
+QZ_IsMouseInWindow(_THIS)
 {
     if (qz_window == nil)
         return YES;             /*fullscreen */
     else {
         NSPoint p =[qz_window mouseLocationOutsideOfEventStream];
         p.y -= 1.0f;            /* Apparently y goes from 1 to h, not from 0 to h-1 (i.e. the "location of the mouse" seems to be defined as "the location of the top left corner of the mouse pointer's hot pixel" */
-        return NSPointInRect (p,[window_view frame]);
+        return NSPointInRect(p,[window_view frame]);
     }
 }
 
 int
-QZ_ShowWMCursor (_THIS, WMcursor * cursor)
+QZ_ShowWMCursor(_THIS, WMcursor * cursor)
 {
 
     if (cursor == NULL) {
         if (cursor_should_be_visible) {
-            QZ_HideMouse (this);
+            QZ_HideMouse(this);
             cursor_should_be_visible = NO;
-            QZ_ChangeGrabState (this, QZ_HIDECURSOR);
+            QZ_ChangeGrabState(this, QZ_HIDECURSOR);
         }
     } else {
-        SetCursor (&cursor->curs);
+        [cursor->nscursor set];
         if (!cursor_should_be_visible) {
-            QZ_ShowMouse (this);
+            QZ_ShowMouse(this);
             cursor_should_be_visible = YES;
-            QZ_ChangeGrabState (this, QZ_SHOWCURSOR);
+            QZ_ChangeGrabState(this, QZ_SHOWCURSOR);
         }
     }
 
@@ -137,7 +162,7 @@
 
 /* Convert Cocoa screen coordinate to Cocoa window coordinate */
 void
-QZ_PrivateGlobalToLocal (_THIS, NSPoint * p)
+QZ_PrivateGlobalToLocal(_THIS, NSPoint * p)
 {
 
   *p =[qz_window convertScreenToBase:*p];
@@ -146,7 +171,7 @@
 
 /* Convert Cocoa window coordinate to Cocoa screen coordinate */
 void
-QZ_PrivateLocalToGlobal (_THIS, NSPoint * p)
+QZ_PrivateLocalToGlobal(_THIS, NSPoint * p)
 {
 
   *p =[qz_window convertBaseToScreen:*p];
@@ -154,18 +179,18 @@
 
 /* Convert SDL coordinate to Cocoa coordinate */
 void
-QZ_PrivateSDLToCocoa (_THIS, NSPoint * p)
+QZ_PrivateSDLToCocoa(_THIS, NSPoint * p)
 {
 
-    if (CGDisplayIsCaptured (display_id)) {     /* capture signals fullscreen */
+    if (CGDisplayIsCaptured(display_id)) {      /* capture signals fullscreen */
 
-        p->y = CGDisplayPixelsHigh (display_id) - p->y;
+        p->y = CGDisplayPixelsHigh(display_id) - p->y;
     } else {
 
       *p =[window_view convertPoint: *p toView:nil];
 
         /* We need a workaround in OpenGL mode */
-        if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) {
+        if (SDL_VideoSurface->flags & SDL_OPENGL) {
             p->y =[window_view frame].size.height - p->y;
         }
     }
@@ -173,19 +198,19 @@
 
 /* Convert Cocoa coordinate to SDL coordinate */
 void
-QZ_PrivateCocoaToSDL (_THIS, NSPoint * p)
+QZ_PrivateCocoaToSDL(_THIS, NSPoint * p)
 {
 
-    if (CGDisplayIsCaptured (display_id)) {     /* capture signals fullscreen */
+    if (CGDisplayIsCaptured(display_id)) {      /* capture signals fullscreen */
 
-        p->y = CGDisplayPixelsHigh (display_id) - p->y;
+        p->y = CGDisplayPixelsHigh(display_id) - p->y;
     } else {
 
       *p =[window_view convertPoint: *p fromView:nil];
 
         /* We need a workaround in OpenGL mode */
         if (SDL_VideoSurface != NULL
-            && (SDL_VideoSurface->flags & SDL_INTERNALOPENGL)) {
+            && (SDL_VideoSurface->flags & SDL_OPENGL)) {
             p->y =[window_view frame].size.height - p->y;
         }
     }
@@ -193,19 +218,19 @@
 
 /* Convert SDL coordinate to window server (CoreGraphics) coordinate */
 CGPoint
-QZ_PrivateSDLToCG (_THIS, NSPoint * p)
+QZ_PrivateSDLToCG(_THIS, NSPoint * p)
 {
 
     CGPoint cgp;
 
-    if (!CGDisplayIsCaptured (display_id)) {    /* not captured => not fullscreen => local coord */
+    if (!CGDisplayIsCaptured(display_id)) {     /* not captured => not fullscreen => local coord */
 
         int height;
 
-        QZ_PrivateSDLToCocoa (this, p);
-        QZ_PrivateLocalToGlobal (this, p);
+        QZ_PrivateSDLToCocoa(this, p);
+        QZ_PrivateLocalToGlobal(this, p);
 
-        height = CGDisplayPixelsHigh (display_id);
+        height = CGDisplayPixelsHigh(display_id);
         p->y = height - p->y;
     }
 
@@ -218,40 +243,40 @@
 #if 0                           /* Dead code */
 /* Convert window server (CoreGraphics) coordinate to SDL coordinate */
 void
-QZ_PrivateCGToSDL (_THIS, NSPoint * p)
+QZ_PrivateCGToSDL(_THIS, NSPoint * p)
 {
 
-    if (!CGDisplayIsCaptured (display_id)) {    /* not captured => not fullscreen => local coord */
+    if (!CGDisplayIsCaptured(display_id)) {     /* not captured => not fullscreen => local coord */
 
         int height;
 
         /* Convert CG Global to Cocoa Global */
-        height = CGDisplayPixelsHigh (display_id);
+        height = CGDisplayPixelsHigh(display_id);
         p->y = height - p->y;
 
-        QZ_PrivateGlobalToLocal (this, p);
-        QZ_PrivateCocoaToSDL (this, p);
+        QZ_PrivateGlobalToLocal(this, p);
+        QZ_PrivateCocoaToSDL(this, p);
     }
 }
 #endif /* Dead code */
 
 void
-QZ_PrivateWarpCursor (_THIS, int x, int y)
+QZ_PrivateWarpCursor(_THIS, int x, int y)
 {
 
     NSPoint p;
     CGPoint cgp;
 
-    p = NSMakePoint (x, y);
-    cgp = QZ_PrivateSDLToCG (this, &p);
+    p = NSMakePoint(x, y);
+    cgp = QZ_PrivateSDLToCG(this, &p);
 
     /* this is the magic call that fixes cursor "freezing" after warp */
-    CGSetLocalEventsSuppressionInterval (0.0);
-    CGWarpMouseCursorPosition (cgp);
+    CGSetLocalEventsSuppressionInterval(0.0);
+    CGWarpMouseCursorPosition(cgp);
 }
 
 void
-QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y)
+QZ_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
 {
 
     /* Only allow warping when in foreground */
@@ -260,23 +285,23 @@
 
     /* Do the actual warp */
     if (grab_state != QZ_INVISIBLE_GRAB)
-        QZ_PrivateWarpCursor (this, x, y);
+        QZ_PrivateWarpCursor(this, x, y);
 
     /* Generate the mouse moved event */
-    SDL_PrivateMouseMotion (0, 0, x, y);
+    SDL_PrivateMouseMotion(0, 0, x, y);
 }
 
 void
-QZ_MoveWMCursor (_THIS, int x, int y)
+QZ_MoveWMCursor(_THIS, int x, int y)
 {
 }
 void
-QZ_CheckMouseMode (_THIS)
+QZ_CheckMouseMode(_THIS)
 {
 }
 
 void
-QZ_SetCaption (_THIS, const char *title, const char *icon)
+QZ_SetCaption(_THIS, const char *title, const char *icon)
 {
 
     if (qz_window != nil) {
@@ -295,7 +320,7 @@
 }
 
 void
-QZ_SetIcon (_THIS, SDL_Surface * icon, Uint8 * mask)
+QZ_SetIcon(_THIS, SDL_Surface * icon, Uint8 * mask)
 {
     NSBitmapImageRep *imgrep;
     NSImage *img;
@@ -312,7 +337,7 @@
     if (imgrep == nil)
         goto freePool;
     pixels =[imgrep bitmapData];
-    SDL_memset (pixels, 0, 4 * icon->w * icon->h);      /* make the background, which will survive in colorkeyed areas, completely transparent */
+    SDL_memset(pixels, 0, 4 * icon->w * icon->h);       /* make the background, which will survive in colorkeyed areas, completely transparent */
 
 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
 #define BYTEORDER_DEPENDENT_RGBA_MASKS 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
@@ -320,20 +345,20 @@
 #define BYTEORDER_DEPENDENT_RGBA_MASKS 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
 #endif
     mergedSurface =
-        SDL_CreateRGBSurfaceFrom (pixels, icon->w, icon->h, 32, 4 * icon->w,
-                                  BYTEORDER_DEPENDENT_RGBA_MASKS);
+        SDL_CreateRGBSurfaceFrom(pixels, icon->w, icon->h, 32, 4 * icon->w,
+                                 BYTEORDER_DEPENDENT_RGBA_MASKS);
     if (mergedSurface == NULL)
         goto freePool;
 
     /* blit, with temporarily cleared SRCALPHA flag because we want to copy, not alpha-blend */
     iconSrcAlpha = ((icon->flags & SDL_SRCALPHA) != 0);
     iconAlphaValue = icon->format->alpha;
-    SDL_SetAlpha (icon, 0, 255);
-    SDL_BlitSurface (icon, NULL, mergedSurface, NULL);
+    SDL_SetAlpha(icon, 0, 255);
+    SDL_BlitSurface(icon, NULL, mergedSurface, NULL);
     if (iconSrcAlpha)
-        SDL_SetAlpha (icon, SDL_SRCALPHA, iconAlphaValue);
+        SDL_SetAlpha(icon, SDL_SRCALPHA, iconAlphaValue);
 
-    SDL_FreeSurface (mergedSurface);
+    SDL_FreeSurface(mergedSurface);
 
     /* apply mask, source alpha, and premultiply color values by alpha */
     maskPitch = (icon->w + 7) / 8;
@@ -361,8 +386,8 @@
         }
     }
 
-  img =[[[NSImage alloc] initWithSize:NSMakeSize (icon->w,
-                icon->h)] autorelease];
+  img =[[[NSImage alloc] initWithSize:NSMakeSize(icon->w,
+               icon->h)] autorelease];
     if (img == nil)
         goto freePool;
   [img addRepresentation:imgrep];
@@ -373,14 +398,14 @@
 }
 
 int
-QZ_IconifyWindow (_THIS)
+QZ_IconifyWindow(_THIS)
 {
 
     if (![qz_window isMiniaturized]) {
       [qz_window miniaturize:nil];
         return 1;
     } else {
-        SDL_SetError ("window already iconified");
+        SDL_SetError("window already iconified");
         return 0;
     }
 }
@@ -392,7 +417,7 @@
 }*/
 
 void
-QZ_ChangeGrabState (_THIS, int action)
+QZ_ChangeGrabState(_THIS, int action)
 {
 
     /* 
@@ -412,7 +437,7 @@
         else if (action == QZ_HIDECURSOR)
             grab_state = QZ_INVISIBLE_GRAB;
     } else {
-        assert (grab_state == QZ_INVISIBLE_GRAB);
+        assert(grab_state == QZ_INVISIBLE_GRAB);
 
         if (action == QZ_DISABLE_GRAB)
             grab_state = QZ_UNGRABBED;
@@ -423,28 +448,28 @@
     /* now apply the new state */
     if (grab_state == QZ_UNGRABBED) {
 
-        CGAssociateMouseAndMouseCursorPosition (1);
+        CGAssociateMouseAndMouseCursorPosition(1);
     } else if (grab_state == QZ_VISIBLE_GRAB) {
 
-        CGAssociateMouseAndMouseCursorPosition (1);
+        CGAssociateMouseAndMouseCursorPosition(1);
     } else {
-        assert (grab_state == QZ_INVISIBLE_GRAB);
+        assert(grab_state == QZ_INVISIBLE_GRAB);
 
-        QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2,
-                              SDL_VideoSurface->h / 2);
-        CGAssociateMouseAndMouseCursorPosition (0);
+        QZ_PrivateWarpCursor(this, SDL_VideoSurface->w / 2,
+                             SDL_VideoSurface->h / 2);
+        CGAssociateMouseAndMouseCursorPosition(0);
     }
 }
 
 SDL_GrabMode
-QZ_GrabInput (_THIS, SDL_GrabMode grab_mode)
+QZ_GrabInput(_THIS, SDL_GrabMode grab_mode)
 {
 
     int doGrab = grab_mode & SDL_GRAB_ON;
     /*int fullscreen = grab_mode & SDL_GRAB_FULLSCREEN; */
 
     if (this->screen == NULL) {
-        SDL_SetError ("QZ_GrabInput: screen is NULL");
+        SDL_SetError("QZ_GrabInput: screen is NULL");
         return SDL_GRAB_OFF;
     }
 
@@ -456,9 +481,9 @@
 
     if (grab_mode != SDL_GRAB_QUERY) {
         if (doGrab)
-            QZ_ChangeGrabState (this, QZ_ENABLE_GRAB);
+            QZ_ChangeGrabState(this, QZ_ENABLE_GRAB);
         else
-            QZ_ChangeGrabState (this, QZ_DISABLE_GRAB);
+            QZ_ChangeGrabState(this, QZ_DISABLE_GRAB);
 
         current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF;
     }