From 45ed5ee4945050de59a1868679e75a68d97e6977 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 4 Jun 2014 10:55:26 -0700 Subject: [PATCH] Added an API function to warp the mouse cursor in global screen space: SDL_WarpMouseGlobal() --- include/SDL_mouse.h | 10 ++++++++++ src/dynapi/SDL_dynapi_overrides.h | 3 ++- src/dynapi/SDL_dynapi_procs.h | 3 ++- src/events/SDL_mouse.c | 14 ++++++++++++-- src/events/SDL_mouse_c.h | 5 ++++- src/video/cocoa/SDL_cocoamouse.m | 25 +++++++++++++++++++++++++ src/video/mir/SDL_mirmouse.c | 7 +++++++ src/video/raspberry/SDL_rpimouse.c | 9 +++++++++ src/video/wayland/SDL_waylandmouse.c | 8 +++++++- src/video/windows/SDL_windowsmouse.c | 11 +++++++++++ src/video/x11/SDL_x11mouse.c | 10 ++++++++++ 11 files changed, 99 insertions(+), 6 deletions(-) diff --git a/include/SDL_mouse.h b/include/SDL_mouse.h index ebfd18fa7..69eb8545f 100644 --- a/include/SDL_mouse.h +++ b/include/SDL_mouse.h @@ -98,6 +98,16 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetRelativeMouseState(int *x, int *y); extern DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window * window, int x, int y); +/** + * \brief Moves the mouse to the given position in global screen space. + * + * \param x The x coordinate + * \param y The y coordinate + * + * \note This function generates a mouse motion event + */ +extern DECLSPEC void SDLCALL SDL_WarpMouseGlobal(int x, int y); + /** * \brief Set relative mouse mode. * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 52b3d454e..42f12a79f 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -576,6 +576,7 @@ #define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL #define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_REAL #define SDL_RenderIsClipEnabled SDL_RenderIsClipEnabled_REAL +#define SDL_WinRTRunApp SDL_WinRTRunApp_REAL +#define SDL_WarpMouseGlobal SDL_WarpMouseGlobal_REAL #define SDL_WinRTGetFSPathUNICODE SDL_WinRTGetFSPathUNICODE_REAL #define SDL_WinRTGetFSPathUTF8 SDL_WinRTGetFSPathUTF8_REAL -#define SDL_WinRTRunApp SDL_WinRTRunApp_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index d84a93885..d39b19a04 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -608,7 +608,8 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_DXGIGetOutputInfo,(int a,int *b, int *c),(a,b,c),re #endif SDL_DYNAPI_PROC(SDL_bool,SDL_RenderIsClipEnabled,(SDL_Renderer *a),(a),return) #ifdef __WINRT__ +SDL_DYNAPI_PROC(int,SDL_WinRTRunApp,(int a, char **b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(const wchar_t*,SDL_WinRTGetFSPathUNICODE,(SDL_WinRT_Path a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_WinRTGetFSPathUTF8,(SDL_WinRT_Path a),(a),return) -SDL_DYNAPI_PROC(int,SDL_WinRTRunApp,(int a, char **b, void *c),(a,b,c),return) #endif +SDL_DYNAPI_PROC(void,SDL_WarpMouseGlobal,(int a, int b),(a,b),) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 3f82b4ee8..4ee68844d 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -482,10 +482,10 @@ SDL_WarpMouseInWindow(SDL_Window * window, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); - if ( window == NULL ) + if (window == NULL) window = mouse->focus; - if ( window == NULL ) + if (window == NULL) return; if (mouse->WarpMouse) { @@ -495,6 +495,16 @@ SDL_WarpMouseInWindow(SDL_Window * window, int x, int y) } } +void +SDL_WarpMouseGlobal(int x, int y) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + + if (mouse->WarpMouseGlobal) { + mouse->WarpMouseGlobal(x, y); + } +} + static SDL_bool ShouldUseRelativeModeWarp(SDL_Mouse *mouse) { diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index e0d917cbc..7157a1c46 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -57,9 +57,12 @@ typedef struct /* Free a window manager cursor */ void (*FreeCursor) (SDL_Cursor * cursor); - /* Warp the mouse to (x,y) */ + /* Warp the mouse to (x,y) within a window */ void (*WarpMouse) (SDL_Window * window, int x, int y); + /* Warp the mouse to (x,y) in screen space */ + void (*WarpMouseGlobal) (int x, int y); + /* Set relative mode */ int (*SetRelativeMouseMode) (SDL_bool enabled); diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m index 8fc742ecf..54dcb1cf9 100644 --- a/src/video/cocoa/SDL_cocoamouse.m +++ b/src/video/cocoa/SDL_cocoamouse.m @@ -241,6 +241,30 @@ Cocoa_WarpMouse(SDL_Window * window, int x, int y) } } +static void +Cocoa_WarpMouseGlobal(int x, int y) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + CGPoint point = CGPointMake((float)x, (float)y); + + Cocoa_HandleMouseWarp(point.x, point.y); + + /* According to the docs, this was deprecated in 10.6, but it's still + * around. The substitute requires a CGEventSource, but I'm not entirely + * sure how we'd procure the right one for this event. + */ + CGSetLocalEventsSuppressionInterval(0.0); + CGWarpMouseCursorPosition(point); + CGSetLocalEventsSuppressionInterval(0.25); + + if (!mouse->relative_mode && mouse->focus) { + /* CGWarpMouseCursorPosition doesn't generate a window event, unlike our + * other implementations' APIs. + */ + SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x - mouse->focus.x, y - mouse->focus.y); + } +} + static int Cocoa_SetRelativeMouseMode(SDL_bool enabled) { @@ -295,6 +319,7 @@ Cocoa_InitMouse(_THIS) mouse->ShowCursor = Cocoa_ShowCursor; mouse->FreeCursor = Cocoa_FreeCursor; mouse->WarpMouse = Cocoa_WarpMouse; + mouse->WarpMouseGlobal = Cocoa_WarpMouseGlobal; mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode; SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor()); diff --git a/src/video/mir/SDL_mirmouse.c b/src/video/mir/SDL_mirmouse.c index def9dbd06..72f4b6a3c 100644 --- a/src/video/mir/SDL_mirmouse.c +++ b/src/video/mir/SDL_mirmouse.c @@ -110,6 +110,12 @@ MIR_WarpMouse(SDL_Window* window, int x, int y) SDL_Unsupported(); } +static void +MIR_WarpMouseGlobal(int x, int y) +{ + SDL_Unsupported(); +} + static int MIR_SetRelativeMouseMode(SDL_bool enabled) { @@ -126,6 +132,7 @@ MIR_InitMouse() mouse->ShowCursor = MIR_ShowCursor; mouse->FreeCursor = MIR_FreeCursor; mouse->WarpMouse = MIR_WarpMouse; + mouse->WarpMouseGlobal = MIR_WarpMouseGlobal; mouse->CreateSystemCursor = MIR_CreateSystemCursor; mouse->SetRelativeMouseMode = MIR_SetRelativeMouseMode; diff --git a/src/video/raspberry/SDL_rpimouse.c b/src/video/raspberry/SDL_rpimouse.c index 718fef81b..b0ba88de3 100644 --- a/src/video/raspberry/SDL_rpimouse.c +++ b/src/video/raspberry/SDL_rpimouse.c @@ -48,6 +48,7 @@ static int RPI_ShowCursor(SDL_Cursor * cursor); static void RPI_MoveCursor(SDL_Cursor * cursor); static void RPI_FreeCursor(SDL_Cursor * cursor); static void RPI_WarpMouse(SDL_Window * window, int x, int y); +static void RPI_WarpMouseGlobal(int x, int y); static SDL_Cursor * RPI_CreateDefaultCursor(void) @@ -210,6 +211,13 @@ RPI_FreeCursor(SDL_Cursor * cursor) /* Warp the mouse to (x,y) */ static void RPI_WarpMouse(SDL_Window * window, int x, int y) +{ + RPI_WarpMouseGlobal(x, y); +} + +/* Warp the mouse to (x,y) */ +static void +RPI_WarpMouseGlobal(int x, int y) { RPI_CursorData *curdata; DISPMANX_UPDATE_HANDLE_T update; @@ -254,6 +262,7 @@ RPI_InitMouse(_THIS) mouse->MoveCursor = RPI_MoveCursor; mouse->FreeCursor = RPI_FreeCursor; mouse->WarpMouse = RPI_WarpMouse; + mouse->WarpMouseGlobal = RPI_WarpMouseGlobal; SDL_SetDefaultCursor(RPI_CreateDefaultCursor()); } diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c index 74a9f9b73..8abf22752 100644 --- a/src/video/wayland/SDL_waylandmouse.c +++ b/src/video/wayland/SDL_waylandmouse.c @@ -345,7 +345,12 @@ static void Wayland_WarpMouse(SDL_Window *window, int x, int y) { SDL_Unsupported(); - return; +} + +static void +Wayland_WarpMouseGlobal(int x, int y) +{ + SDL_Unsupported(); } static int @@ -365,6 +370,7 @@ Wayland_InitMouse(void) mouse->ShowCursor = Wayland_ShowCursor; mouse->FreeCursor = Wayland_FreeCursor; mouse->WarpMouse = Wayland_WarpMouse; + mouse->WarpMouseGlobal = Wayland_WarpMouseGlobal; mouse->SetRelativeMouseMode = Wayland_SetRelativeMouseMode; SDL_SetDefaultCursor(Wayland_CreateDefaultCursor()); diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index b49249db6..14e99b480 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -198,6 +198,16 @@ WIN_WarpMouse(SDL_Window * window, int x, int y) SetCursorPos(pt.x, pt.y); } +static void +WIN_WarpMouseGlobal(int x, int y) +{ + POINT pt; + + pt.x = x; + pt.y = y; + SetCursorPos(pt.x, pt.y); +} + static int WIN_SetRelativeMouseMode(SDL_bool enabled) { @@ -229,6 +239,7 @@ WIN_InitMouse(_THIS) mouse->ShowCursor = WIN_ShowCursor; mouse->FreeCursor = WIN_FreeCursor; mouse->WarpMouse = WIN_WarpMouse; + mouse->WarpMouseGlobal = WIN_WarpMouseGlobal; mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode; SDL_SetDefaultCursor(WIN_CreateDefaultCursor()); diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 38bb86656..35baa5cee 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -318,6 +318,15 @@ X11_WarpMouse(SDL_Window * window, int x, int y) X11_XSync(display, False); } +static void +X11_WarpMouseGlobal(int x, int y) +{ + Display *display = GetDisplay(); + + X11_XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, x, y); + X11_XSync(display, False); +} + static int X11_SetRelativeMouseMode(SDL_bool enabled) { @@ -340,6 +349,7 @@ X11_InitMouse(_THIS) mouse->ShowCursor = X11_ShowCursor; mouse->FreeCursor = X11_FreeCursor; mouse->WarpMouse = X11_WarpMouse; + mouse->WarpMouseGlobal = X11_WarpMouseGlobal; mouse->SetRelativeMouseMode = X11_SetRelativeMouseMode; SDL_SetDefaultCursor(X11_CreateDefaultCursor());