Skip to content

Commit

Permalink
Implemented SDL_GetAbsoluteMouseState().
Browse files Browse the repository at this point in the history
X11 only for now, but this should be doable on every platform, I think.
  • Loading branch information
icculus committed Jun 5, 2014
1 parent 264eb4b commit b861efd
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 0 deletions.
25 changes: 25 additions & 0 deletions include/SDL_mouse.h
Expand Up @@ -77,6 +77,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.
*
Expand Down
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Expand Up @@ -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
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_procs.h
Expand Up @@ -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)
24 changes: 24 additions & 0 deletions src/events/SDL_mouse.c
Expand Up @@ -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)
{
Expand Down
3 changes: 3 additions & 0 deletions src/events/SDL_mouse_c.h
Expand Up @@ -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;
Expand Down
13 changes: 13 additions & 0 deletions src/test/SDL_test_common.c
Expand Up @@ -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);
Expand Down
34 changes: 34 additions & 0 deletions src/video/x11/SDL_x11mouse.c
Expand Up @@ -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)
{
Expand All @@ -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());
}
Expand Down

0 comments on commit b861efd

Please sign in to comment.