Browse Source

Added an API function to warp the mouse cursor in global screen space: SDL_WarpMouseGlobal()

Sam Lantinga 11 years ago
parent
commit
45ed5ee494

+ 10 - 0
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.
  *

+ 2 - 1
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

+ 2 - 1
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),)

+ 12 - 2
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)
 {

+ 4 - 1
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);
 

+ 25 - 0
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());

+ 7 - 0
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;
 

+ 9 - 0
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());
 }

+ 7 - 1
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());

+ 11 - 0
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());

+ 10 - 0
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());