From 6c64eaf08e16b4946aabf0bc25b7f5f812c42365 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 27 Feb 2011 22:06:46 -0800 Subject: [PATCH] Implemented mouse relative mode on Mac OS X. --- src/events/SDL_mouse.c | 17 +++++++++++++++-- src/events/SDL_mouse_c.h | 3 +++ src/video/cocoa/SDL_cocoamouse.m | 28 ++++++++++++++++++++++++++-- src/video/cocoa/SDL_cocoawindow.m | 19 ++----------------- test/common.c | 8 +++++++- 5 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 1c84f3546..cf10f47d7 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -308,8 +308,18 @@ SDL_SetRelativeMouseMode(SDL_bool enabled) { 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_SetRelativeMouseMode(SDL_bool enabled) SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y); } + /* Flush pending mouse motion */ + SDL_FlushEvent(SDL_MOUSEMOTION); + /* Update cursor visibility */ SDL_SetCursor(NULL); diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index f3a851cca..c6eabc167 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -49,6 +49,9 @@ typedef struct /* 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; diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m index cbab74896..b579f5569 100644 --- a/src/video/cocoa/SDL_cocoamouse.m +++ b/src/video/cocoa/SDL_cocoamouse.m @@ -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->WarpMouse = Cocoa_WarpMouse; mouse->FreeCursor = Cocoa_FreeCursor; + mouse->WarpMouse = Cocoa_WarpMouse; + 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 diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index d77c5799a..b87321208 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -302,15 +302,14 @@ - (void)mouseExited:(NSEvent *)theEvent - (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)rightMouseDown:(NSEvent *)theEvent 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 @@ - (void)rightMouseDown:(NSEvent *)theEvent cgpoint.y = window->y + y; CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint); } -#endif } void diff --git a/test/common.c b/test/common.c index 51270e5a0..fb134a474 100644 --- a/test/common.c +++ b/test/common.c @@ -812,7 +812,7 @@ PrintEvent(SDL_Event * event) { if (event->type == SDL_MOUSEMOTION) { /* Mouse motion is really spammy */ - return; + //return; } fprintf(stderr, "SDL EVENT: "); @@ -1044,6 +1044,12 @@ CommonEvent(CommonState * state, SDL_Event * event, int *done) } } 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 */