Implemented mouse relative mode on Mac OS X.
authorSam Lantinga <slouken@libsdl.org>
Sun, 27 Feb 2011 22:06:46 -0800
changeset 5406 1517da4ab6b1
parent 5405 64fa8526e1ce
child 5407 40c9d744e595
Implemented mouse relative mode on Mac OS X.
src/events/SDL_mouse.c
src/events/SDL_mouse_c.h
src/video/cocoa/SDL_cocoamouse.m
src/video/cocoa/SDL_cocoawindow.m
test/common.c
--- a/src/events/SDL_mouse.c	Sun Feb 27 21:36:23 2011 -0800
+++ b/src/events/SDL_mouse.c	Sun Feb 27 22:06:46 2011 -0800
@@ -308,8 +308,18 @@
 {
     SDL_Mouse *mouse = SDL_GetMouse();
 
-    /* Flush pending mouse motion */
-    SDL_FlushEvent(SDL_MOUSEMOTION);
+    if (enabled == mouse->relative_mode) {
+        return 0;
+    }
+
+    if (!mouse->SetRelativeMouseMode) {
+        SDL_Unsupported();
+        return -1;
+    }
+
+    if (mouse->SetRelativeMouseMode(enabled) < 0) {
+        return -1;
+    }
 
     /* Set the relative mode */
     mouse->relative_mode = enabled;
@@ -319,6 +329,9 @@
         SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
     }
 
+    /* Flush pending mouse motion */
+    SDL_FlushEvent(SDL_MOUSEMOTION);
+
     /* Update cursor visibility */
     SDL_SetCursor(NULL);
 
--- a/src/events/SDL_mouse_c.h	Sun Feb 27 21:36:23 2011 -0800
+++ b/src/events/SDL_mouse_c.h	Sun Feb 27 22:06:46 2011 -0800
@@ -49,6 +49,9 @@
     /* Warp the mouse to (x,y) */
     void (*WarpMouse) (SDL_Window * window, int x, int y);
 
+    /* Set relative mode */
+    int (*SetRelativeMouseMode) (SDL_bool enabled);
+
     /* Data common to all mice */
     SDL_Window *focus;
     int x;
--- a/src/video/cocoa/SDL_cocoamouse.m	Sun Feb 27 21:36:23 2011 -0800
+++ b/src/video/cocoa/SDL_cocoamouse.m	Sun Feb 27 22:06:46 2011 -0800
@@ -116,6 +116,23 @@
     CGWarpMouseCursorPosition(point);
 }
 
+static int
+Cocoa_SetRelativeMouseMode(SDL_bool enabled)
+{
+    CGError result;
+
+    if (enabled) {
+        result = CGAssociateMouseAndMouseCursorPosition(NO);
+    } else {
+        result = CGAssociateMouseAndMouseCursorPosition(YES);
+    }
+    if (result != kCGErrorSuccess) {
+        SDL_SetError("CGAssociateMouseAndMouseCursorPosition() failed");
+        return -1;
+    }
+    return 0;
+}
+
 void
 Cocoa_InitMouse(_THIS)
 {
@@ -123,8 +140,9 @@
 
     mouse->CreateCursor = Cocoa_CreateCursor;
     mouse->ShowCursor = Cocoa_ShowCursor;
+    mouse->FreeCursor = Cocoa_FreeCursor;
     mouse->WarpMouse = Cocoa_WarpMouse;
-    mouse->FreeCursor = Cocoa_FreeCursor;
+    mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
 
     SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
 }
@@ -147,7 +165,13 @@
 void
 Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
 {
-    /* We're correctly using views even in fullscreen mode now */
+    SDL_Mouse *mouse = SDL_GetMouse();
+
+    if (mouse->relative_mode && [event type] == NSMouseMoved) {
+        float x = [event deltaX];
+        float y = [event deltaY];
+        SDL_SendMouseMotion(mouse->focus, 1, (int)x, (int)y);
+    }
 }
 
 void
--- a/src/video/cocoa/SDL_cocoawindow.m	Sun Feb 27 21:36:23 2011 -0800
+++ b/src/video/cocoa/SDL_cocoawindow.m	Sun Feb 27 22:06:46 2011 -0800
@@ -302,15 +302,14 @@
 
 - (void)mouseMoved:(NSEvent *)theEvent
 {
+    SDL_Mouse *mouse = SDL_GetMouse();
     SDL_Window *window = _data->window;
     NSPoint point;
     int x, y;
 
-#ifdef RELATIVE_MOTION
-    if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
+    if (mouse->relative_mode) {
         return;
     }
-#endif
 
     point = [theEvent locationInWindow];
     x = (int)point.x;
@@ -861,19 +860,6 @@
 void
 Cocoa_SetWindowGrab(_THIS, SDL_Window * window)
 {
-#ifdef RELATIVE_MOTION
-    /* FIXME: work in progress
-        You set relative mode by using the following code in conjunction with
-        CGDisplayHideCursor(kCGDirectMainDisplay) and
-        CGDisplayShowCursor(kCGDirectMainDisplay)
-    */
-    if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
-        (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
-        CGAssociateMouseAndMouseCursorPosition(NO);
-    } else {
-        CGAssociateMouseAndMouseCursorPosition(YES);
-    }
-#else
     /* Move the cursor to the nearest point in the window */
     if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
         (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
@@ -885,7 +871,6 @@
         cgpoint.y = window->y + y;
         CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
     }
-#endif
 }
 
 void
--- a/test/common.c	Sun Feb 27 21:36:23 2011 -0800
+++ b/test/common.c	Sun Feb 27 22:06:46 2011 -0800
@@ -812,7 +812,7 @@
 {
     if (event->type == SDL_MOUSEMOTION) {
         /* Mouse motion is really spammy */
-        return;
+        //return;
     }
 
     fprintf(stderr, "SDL EVENT: ");
@@ -1044,6 +1044,12 @@
                 }
             }
             break;
+        case SDLK_r:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-R toggle mouse relative mode */
+                SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode());
+            }
+            break;
         case SDLK_z:
             if (event->key.keysym.mod & KMOD_CTRL) {
                 /* Ctrl-Z minimize */