src/video/cocoa/SDL_cocoamouse.m
author Jørgen P. Tjernø <jorgen@valvesoftware.com>
Tue, 23 Apr 2013 18:47:41 -0700
changeset 7099 54f187c036e2
parent 7037 3fedf1f25b94
child 7100 ffd910de700b
permissions -rw-r--r--
Mac: Fix unmatched hide/show cursor calls.

This tracks the previous hide/unhide state of the cursor, so we don't
re-hide a hidden cursor.
     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_assert.h"
    26 #include "SDL_events.h"
    27 #include "SDL_cocoavideo.h"
    28 
    29 #include "../../events/SDL_mouse_c.h"
    30 
    31 
    32 static SDL_Cursor *
    33 Cocoa_CreateDefaultCursor()
    34 {
    35     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    36     NSCursor *nscursor;
    37     SDL_Cursor *cursor = NULL;
    38 
    39     nscursor = [NSCursor arrowCursor];
    40 
    41     if (nscursor) {
    42         cursor = SDL_calloc(1, sizeof(*cursor));
    43         if (cursor) {
    44             cursor->driverdata = nscursor;
    45             [nscursor retain];
    46         }
    47     }
    48 
    49     [pool release];
    50 
    51     return cursor;
    52 }
    53 
    54 static SDL_Cursor *
    55 Cocoa_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
    56 {
    57     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    58     NSImage *nsimage;
    59     NSCursor *nscursor = NULL;
    60     SDL_Cursor *cursor = NULL;
    61 
    62     nsimage = Cocoa_CreateImage(surface);
    63     if (nsimage) {
    64         nscursor = [[NSCursor alloc] initWithImage: nsimage hotSpot: NSMakePoint(hot_x, hot_y)];
    65     }
    66 
    67     if (nscursor) {
    68         cursor = SDL_calloc(1, sizeof(*cursor));
    69         if (cursor) {
    70             cursor->driverdata = nscursor;
    71         }
    72     }
    73 
    74     [pool release];
    75 
    76     return cursor;
    77 }
    78 
    79 static SDL_Cursor *
    80 Cocoa_CreateSystemCursor(SDL_SystemCursor id)
    81 {
    82     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    83     NSCursor *nscursor = NULL;
    84     SDL_Cursor *cursor = NULL;
    85 
    86     switch(id)
    87     {
    88     case SDL_SYSTEM_CURSOR_ARROW:
    89         nscursor = [NSCursor arrowCursor];
    90         break;
    91     case SDL_SYSTEM_CURSOR_IBEAM:
    92         nscursor = [NSCursor IBeamCursor];
    93         break;
    94     case SDL_SYSTEM_CURSOR_WAIT:
    95         nscursor = [NSCursor arrowCursor];
    96         break;
    97     case SDL_SYSTEM_CURSOR_CROSSHAIR:
    98         nscursor = [NSCursor crosshairCursor];
    99         break;
   100     case SDL_SYSTEM_CURSOR_WAITARROW:
   101         nscursor = [NSCursor arrowCursor];
   102         break;
   103     case SDL_SYSTEM_CURSOR_SIZENWSE:
   104     case SDL_SYSTEM_CURSOR_SIZENESW:
   105         nscursor = [NSCursor closedHandCursor];
   106         break;
   107     case SDL_SYSTEM_CURSOR_SIZEWE:
   108         nscursor = [NSCursor resizeLeftRightCursor];
   109         break;
   110     case SDL_SYSTEM_CURSOR_SIZENS:
   111         nscursor = [NSCursor resizeUpDownCursor];
   112         break;
   113     case SDL_SYSTEM_CURSOR_SIZEALL:
   114         nscursor = [NSCursor closedHandCursor];
   115         break;
   116     case SDL_SYSTEM_CURSOR_NO:
   117         nscursor = [NSCursor operationNotAllowedCursor];
   118         break;
   119     case SDL_SYSTEM_CURSOR_HAND:
   120         nscursor = [NSCursor pointingHandCursor];
   121         break;
   122     default:
   123         SDL_assert(!"Unknown system cursor");
   124         return NULL;
   125     }
   126 
   127     if (nscursor) {
   128         cursor = SDL_calloc(1, sizeof(*cursor));
   129         if (cursor) {
   130             // We'll free it later, so retain it here
   131             [nscursor retain];
   132             cursor->driverdata = nscursor;
   133         }
   134     }
   135 
   136     [pool release];
   137 
   138     return cursor;
   139 }
   140 
   141 static void
   142 Cocoa_FreeCursor(SDL_Cursor * cursor)
   143 {
   144     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   145     NSCursor *nscursor = (NSCursor *)cursor->driverdata;
   146 
   147     [nscursor release];
   148     SDL_free(cursor);
   149 
   150     [pool release];
   151 }
   152 
   153 static int
   154 Cocoa_ShowCursor(SDL_Cursor * cursor)
   155 {
   156 	/* We need to track the previous state because hide and unhide calls need to
   157 	 * be matched, but ShowCursor calls don't.
   158 	 */
   159 	static SDL_bool isShown = SDL_TRUE;
   160     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   161 
   162     if (cursor) {
   163         NSCursor *nscursor = (NSCursor *)cursor->driverdata;
   164 
   165         [nscursor set];
   166 
   167 		if (!isShown) {
   168 			[NSCursor unhide];
   169 			isShown = SDL_TRUE;
   170 		}
   171 	} else if (isShown) {
   172 		[NSCursor hide];
   173 		isShown = SDL_FALSE;
   174     }
   175 
   176     [pool release];
   177 
   178     return 0;
   179 }
   180 
   181 static void
   182 Cocoa_WarpMouse(SDL_Window * window, int x, int y)
   183 {
   184     CGPoint point;
   185 
   186     point.x = (float)window->x + x;
   187     point.y = (float)window->y + y;
   188     CGWarpMouseCursorPosition(point);
   189 }
   190 
   191 static int
   192 Cocoa_SetRelativeMouseMode(SDL_bool enabled)
   193 {
   194     CGError result;
   195 
   196     if (enabled) {
   197         result = CGAssociateMouseAndMouseCursorPosition(NO);
   198     } else {
   199         result = CGAssociateMouseAndMouseCursorPosition(YES);
   200     }
   201     if (result != kCGErrorSuccess) {
   202         return SDL_SetError("CGAssociateMouseAndMouseCursorPosition() failed");
   203     }
   204     return 0;
   205 }
   206 
   207 void
   208 Cocoa_InitMouse(_THIS)
   209 {
   210     SDL_Mouse *mouse = SDL_GetMouse();
   211 
   212     mouse->CreateCursor = Cocoa_CreateCursor;
   213     mouse->CreateSystemCursor = Cocoa_CreateSystemCursor;
   214     mouse->ShowCursor = Cocoa_ShowCursor;
   215     mouse->FreeCursor = Cocoa_FreeCursor;
   216     mouse->WarpMouse = Cocoa_WarpMouse;
   217     mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
   218 
   219     SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
   220 }
   221 
   222 void
   223 Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
   224 {
   225     SDL_Mouse *mouse = SDL_GetMouse();
   226 
   227     if (mouse->relative_mode &&
   228         ([event type] == NSMouseMoved ||
   229          [event type] == NSLeftMouseDragged ||
   230          [event type] == NSRightMouseDragged ||
   231          [event type] == NSOtherMouseDragged)) {
   232         float x = [event deltaX];
   233         float y = [event deltaY];
   234         SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)x, (int)y);
   235     }
   236 }
   237 
   238 void
   239 Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
   240 {
   241     SDL_Mouse *mouse = SDL_GetMouse();
   242 
   243     float x = [event deltaX];
   244     float y = [event deltaY];
   245 
   246     if (x > 0) {
   247         x += 0.9f;
   248     } else if (x < 0) {
   249         x -= 0.9f;
   250     }
   251     if (y > 0) {
   252         y += 0.9f;
   253     } else if (y < 0) {
   254         y -= 0.9f;
   255     }
   256     SDL_SendMouseWheel(window, mouse->mouseID, (int)x, (int)y);
   257 }
   258 
   259 void
   260 Cocoa_QuitMouse(_THIS)
   261 {
   262 }
   263 
   264 #endif /* SDL_VIDEO_DRIVER_COCOA */
   265 
   266 /* vi: set ts=4 sw=4 expandtab: */