Implemented SDL_GetAbsoluteMouseState(). X11 only for now, but this should be doable on every platform, I think.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
diff --git a/include/SDL_mouse.h b/include/SDL_mouse.h
index 571754a..fdb68f0 100644
--- a/include/SDL_mouse.h
+++ b/include/SDL_mouse.h
@@ -78,6 +78,31 @@ extern DECLSPEC SDL_Window * SDLCALL SDL_GetMouseFocus(void);
extern DECLSPEC Uint32 SDLCALL SDL_GetMouseState(int *x, int *y);
/**
+ * \brief Get the current state of the mouse, in relation to the desktop
+ *
+ * This works just like SDL_GetMouseState(), but the coordinates will be
+ * reported relative to the top-left of the desktop. This can be useful if
+ * you need to track the mouse outside of a specific window and
+ * SDL_CaptureMouse() doesn't fit your needs. For example, it could be
+ * useful if you need to track the mouse while dragging a window, where
+ * coordinates relative to a window might not be in sync at all times.
+ *
+ * \note SDL_GetMouseState() returns the mouse position as SDL understands
+ * it from the last pump of the event queue. This function, however,
+ * queries the OS for the current mouse position, and as such, might
+ * be a slightly less efficient function. Unless you know what you're
+ * doing and have a good reason to use this function, you probably want
+ * SDL_GetMouseState() instead.
+ *
+ * \param x Returns the current X coord, relative to the desktop. Can be NULL.
+ * \param y Returns the current Y coord, relative to the desktop. Can be NULL.
+ * \return The current button state as a bitmask, which can be tested using the SDL_BUTTON(X) macros.
+ *
+ * \sa SDL_GetMouseState
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetAbsoluteMouseState(int *x, int *y);
+
+/**
* \brief Retrieve the relative state of the mouse.
*
* The current button state is returned as a button bitmask, which can
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index ce11175..aa99639 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -581,3 +581,4 @@
#define SDL_WinRTRunApp SDL_WinRTRunApp_REAL
#define SDL_CaptureMouse SDL_CaptureMouse_REAL
#define SDL_SetWindowHitTest SDL_SetWindowHitTest_REAL
+#define SDL_GetAbsoluteMouseState SDL_GetAbsoluteMouseState_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index ba78b98..1df1222 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -614,3 +614,4 @@ SDL_DYNAPI_PROC(int,SDL_WinRTRunApp,(int a, char **b, void *c),(a,b,c),return)
#endif
SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return)
SDL_DYNAPI_PROC(int,SDL_SetWindowHitTest,(SDL_Window *a, SDL_HitTest b, void *c),(a,b,c),return)
+SDL_DYNAPI_PROC(Uint32,SDL_GetAbsoluteMouseState,(int *a, int *b),(a,b),return)
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 757c634..970cc78 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -469,6 +469,30 @@ SDL_GetRelativeMouseState(int *x, int *y)
return mouse->buttonstate;
}
+Uint32
+SDL_GetAbsoluteMouseState(int *x, int *y)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+ int tmpx, tmpy;
+
+ /* make sure these are never NULL for the backend implementations... */
+ if (!x) {
+ x = &tmpx;
+ }
+ if (!y) {
+ y = &tmpy;
+ }
+
+ *x = *y = 0;
+
+ if (!mouse->GetAbsoluteMouseState) {
+ SDL_assert(0 && "This should really be implemented for every target.");
+ return 0;
+ }
+
+ return mouse->GetAbsoluteMouseState(x, y);
+}
+
void
SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
{
diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h
index 34cd259..70b3ec0 100644
--- a/src/events/SDL_mouse_c.h
+++ b/src/events/SDL_mouse_c.h
@@ -66,6 +66,9 @@ typedef struct
/* Set mouse capture */
int (*CaptureMouse) (SDL_Window * window);
+ /* Get absolute mouse coordinates. (x) and (y) are never NULL and set to zero before call. */
+ Uint32 (*GetAbsoluteMouseState) (int *x, int *y);
+
/* Data common to all mice */
SDL_MouseID mouseID;
SDL_Window *focus;
diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c
index 2c4cabc..fa6c1fe 100644
--- a/src/test/SDL_test_common.c
+++ b/src/test/SDL_test_common.c
@@ -1488,6 +1488,19 @@ SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
}
}
break;
+ case SDLK_a:
+ if (withControl) {
+ /* Ctrl-A reports absolute mouse position. */
+ int x, y;
+ const Uint32 mask = SDL_GetAbsoluteMouseState(&x, &y);
+ SDL_Log("ABSOLUTE MOUSE: (%d, %d)%s%s%s%s%s\n", x, y,
+ (mask & SDL_BUTTON_LMASK) ? " [LBUTTON]" : "",
+ (mask & SDL_BUTTON_MMASK) ? " [MBUTTON]" : "",
+ (mask & SDL_BUTTON_RMASK) ? " [RBUTTON]" : "",
+ (mask & SDL_BUTTON_X1MASK) ? " [X2BUTTON]" : "",
+ (mask & SDL_BUTTON_X2MASK) ? " [X2BUTTON]" : "");
+ }
+ break;
case SDLK_0:
if (withControl) {
SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c
index 74dc878..7386da5 100644
--- a/src/video/x11/SDL_x11mouse.c
+++ b/src/video/x11/SDL_x11mouse.c
@@ -353,6 +353,39 @@ X11_CaptureMouse(SDL_Window *window)
return 0;
}
+static Uint32
+X11_GetAbsoluteMouseState(int *x, int *y)
+{
+ Display *display = GetDisplay();
+ const int num_screens = SDL_GetNumVideoDisplays();
+ int i;
+
+ /* !!! FIXME: should we XSync() here first? */
+
+ for (i = 0; i < num_screens; i++) {
+ SDL_DisplayData *data = (SDL_DisplayData *) SDL_GetDisplayDriverData(i);
+ if (data != NULL) {
+ Window root, child;
+ int rootx, rooty, winx, winy;
+ unsigned int mask;
+ if (X11_XQueryPointer(display, RootWindow(display, data->screen), &root, &child, &rootx, &rooty, &winx, &winy, &mask)) {
+ Uint32 retval = 0;
+ retval |= (mask & Button1Mask) ? SDL_BUTTON_LMASK : 0;
+ retval |= (mask & Button2Mask) ? SDL_BUTTON_MMASK : 0;
+ retval |= (mask & Button3Mask) ? SDL_BUTTON_RMASK : 0;
+ *x = data->x + rootx;
+ *y = data->y + rooty;
+ return retval;
+ }
+ }
+ }
+
+ SDL_assert(0 && "The pointer wasn't on any X11 screen?!");
+
+ return 0;
+}
+
+
void
X11_InitMouse(_THIS)
{
@@ -365,6 +398,7 @@ X11_InitMouse(_THIS)
mouse->WarpMouse = X11_WarpMouse;
mouse->SetRelativeMouseMode = X11_SetRelativeMouseMode;
mouse->CaptureMouse = X11_CaptureMouse;
+ mouse->GetAbsoluteMouseState = X11_GetAbsoluteMouseState;
SDL_SetDefaultCursor(X11_CreateDefaultCursor());
}