mirror of https://github.com/encounter/SDL.git
Implemented SDL_CaptureMouse().
This commit is contained in:
parent
846a3e0776
commit
b7d2c0e9d6
|
@ -116,6 +116,37 @@ extern DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window * window,
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled);
|
extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Capture the mouse, to track input outside an SDL window.
|
||||||
|
*
|
||||||
|
* \param enabled Whether or not to enable capturing
|
||||||
|
*
|
||||||
|
* Capturing enables your app to obtain mouse events globally, instead of
|
||||||
|
* just within your window. Not all video targets support this function.
|
||||||
|
* When capturing is enabled, the current window will get all mouse events,
|
||||||
|
* but unlike relative mode, no change is made to the cursor and it is
|
||||||
|
* not restrained to your window.
|
||||||
|
*
|
||||||
|
* This function may also deny mouse input to other windows--both those in
|
||||||
|
* your application and others on the system--so you should use this
|
||||||
|
* function sparingly, and in small bursts. For example, you might want to
|
||||||
|
* track the mouse while the user is dragging something, until the user
|
||||||
|
* releases a mouse button. It is not recommended that you capture the mouse
|
||||||
|
* for long periods of time, such as the entire time your app is running.
|
||||||
|
*
|
||||||
|
* While captured, mouse events still report coordinates relative to the
|
||||||
|
* current (foreground) window, but those coordinates may be outside the
|
||||||
|
* bounds of the window (including negative values). Capturing is only
|
||||||
|
* allowed for the foreground window. If the window loses focus while
|
||||||
|
* capturing, the capture will be disabled automatically.
|
||||||
|
*
|
||||||
|
* While capturing is enabled, the current window will have the
|
||||||
|
* SDL_WINDOW_MOUSE_CAPTURE flag set.
|
||||||
|
*
|
||||||
|
* \return 0 on success, or -1 if not supported.
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL SDL_CaptureMouse(SDL_bool enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Query whether relative mouse mode is enabled.
|
* \brief Query whether relative mouse mode is enabled.
|
||||||
*
|
*
|
||||||
|
|
|
@ -108,7 +108,8 @@ typedef enum
|
||||||
SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */
|
SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */
|
||||||
SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
|
SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
|
||||||
SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */
|
SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */
|
||||||
SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000 /**< window should be created in high-DPI mode if supported */
|
SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, /**< window should be created in high-DPI mode if supported */
|
||||||
|
SDL_WINDOW_MOUSE_CAPTURE = 0x00004000 /**< window has mouse captured (unrelated to INPUT_GRABBED) */
|
||||||
} SDL_WindowFlags;
|
} SDL_WindowFlags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -579,3 +579,4 @@
|
||||||
#define SDL_WinRTGetFSPathUNICODE SDL_WinRTGetFSPathUNICODE_REAL
|
#define SDL_WinRTGetFSPathUNICODE SDL_WinRTGetFSPathUNICODE_REAL
|
||||||
#define SDL_WinRTGetFSPathUTF8 SDL_WinRTGetFSPathUTF8_REAL
|
#define SDL_WinRTGetFSPathUTF8 SDL_WinRTGetFSPathUTF8_REAL
|
||||||
#define SDL_WinRTRunApp SDL_WinRTRunApp_REAL
|
#define SDL_WinRTRunApp SDL_WinRTRunApp_REAL
|
||||||
|
#define SDL_CaptureMouse SDL_CaptureMouse_REAL
|
||||||
|
|
|
@ -612,3 +612,4 @@ SDL_DYNAPI_PROC(const wchar_t*,SDL_WinRTGetFSPathUNICODE,(SDL_WinRT_Path a),(a),
|
||||||
SDL_DYNAPI_PROC(const char*,SDL_WinRTGetFSPathUTF8,(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)
|
SDL_DYNAPI_PROC(int,SDL_WinRTRunApp,(int a, char **b, void *c),(a,b,c),return)
|
||||||
#endif
|
#endif
|
||||||
|
SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "SDL_timer.h"
|
#include "SDL_timer.h"
|
||||||
#include "SDL_events.h"
|
#include "SDL_events.h"
|
||||||
#include "SDL_events_c.h"
|
#include "SDL_events_c.h"
|
||||||
|
#include "SDL_assert.h"
|
||||||
#include "../video/SDL_sysvideo.h"
|
#include "../video/SDL_sysvideo.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -619,6 +620,16 @@ SDL_SetKeyboardFocus(SDL_Window * window)
|
||||||
|
|
||||||
/* See if the current window has lost focus */
|
/* See if the current window has lost focus */
|
||||||
if (keyboard->focus && keyboard->focus != window) {
|
if (keyboard->focus && keyboard->focus != window) {
|
||||||
|
|
||||||
|
/* new window shouldn't think it has mouse captured. */
|
||||||
|
SDL_assert(!window || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE));
|
||||||
|
|
||||||
|
/* old window must lose an existing mouse capture. */
|
||||||
|
if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) {
|
||||||
|
SDL_CaptureMouse(SDL_FALSE); /* drop the capture. */
|
||||||
|
SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE));
|
||||||
|
}
|
||||||
|
|
||||||
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
|
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
|
||||||
0, 0);
|
0, 0);
|
||||||
|
|
||||||
|
|
|
@ -140,30 +140,17 @@ static SDL_bool
|
||||||
SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
|
SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
|
||||||
{
|
{
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
int w, h;
|
SDL_bool inWindow = SDL_TRUE;
|
||||||
SDL_bool inWindow;
|
|
||||||
|
|
||||||
SDL_GetWindowSize(window, &w, &h);
|
if ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0) {
|
||||||
if (x < 0 || y < 0 || x >= w || y >= h) {
|
int w, h;
|
||||||
inWindow = SDL_FALSE;
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
} else {
|
if (x < 0 || y < 0 || x >= w || y >= h) {
|
||||||
inWindow = SDL_TRUE;
|
inWindow = SDL_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Linux doesn't give you mouse events outside your window unless you grab
|
|
||||||
the pointer.
|
|
||||||
|
|
||||||
Windows doesn't give you mouse events outside your window unless you call
|
|
||||||
SetCapture().
|
|
||||||
|
|
||||||
Both of these are slightly scary changes, so for now we'll punt and if the
|
|
||||||
mouse leaves the window you'll lose mouse focus and reset button state.
|
|
||||||
*/
|
|
||||||
#ifdef SUPPORT_DRAG_OUTSIDE_WINDOW
|
|
||||||
if (!inWindow && !buttonstate) {
|
|
||||||
#else
|
|
||||||
if (!inWindow) {
|
if (!inWindow) {
|
||||||
#endif
|
|
||||||
if (window == mouse->focus) {
|
if (window == mouse->focus) {
|
||||||
#ifdef DEBUG_MOUSE
|
#ifdef DEBUG_MOUSE
|
||||||
printf("Mouse left window, synthesizing move & focus lost event\n");
|
printf("Mouse left window, synthesizing move & focus lost event\n");
|
||||||
|
@ -204,7 +191,6 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
|
||||||
int posted;
|
int posted;
|
||||||
int xrel;
|
int xrel;
|
||||||
int yrel;
|
int yrel;
|
||||||
int x_max = 0, y_max = 0;
|
|
||||||
|
|
||||||
if (mouse->relative_mode_warp) {
|
if (mouse->relative_mode_warp) {
|
||||||
int center_x = 0, center_y = 0;
|
int center_x = 0, center_y = 0;
|
||||||
|
@ -246,24 +232,29 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
|
||||||
mouse->y += yrel;
|
mouse->y += yrel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* !!! FIXME: shouldn't this be (window) instead of (mouse->focus)? */
|
/* make sure that the pointers find themselves inside the windows,
|
||||||
SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
|
unless we have the mouse captured. */
|
||||||
--x_max;
|
if ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0) {
|
||||||
--y_max;
|
int x_max = 0, y_max = 0;
|
||||||
|
|
||||||
/* make sure that the pointers find themselves inside the windows */
|
// !!! FIXME: shouldn't this be (window) instead of (mouse->focus)?
|
||||||
if (mouse->x > x_max) {
|
SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
|
||||||
mouse->x = x_max;
|
--x_max;
|
||||||
}
|
--y_max;
|
||||||
if (mouse->x < 0) {
|
|
||||||
mouse->x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mouse->y > y_max) {
|
if (mouse->x > x_max) {
|
||||||
mouse->y = y_max;
|
mouse->x = x_max;
|
||||||
}
|
}
|
||||||
if (mouse->y < 0) {
|
if (mouse->x < 0) {
|
||||||
mouse->y = 0;
|
mouse->x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouse->y > y_max) {
|
||||||
|
mouse->y = y_max;
|
||||||
|
}
|
||||||
|
if (mouse->y < 0) {
|
||||||
|
mouse->y = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse->xdelta += xrel;
|
mouse->xdelta += xrel;
|
||||||
|
@ -426,6 +417,7 @@ SDL_MouseQuit(void)
|
||||||
SDL_Cursor *cursor, *next;
|
SDL_Cursor *cursor, *next;
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
|
||||||
|
SDL_CaptureMouse(SDL_FALSE);
|
||||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||||
SDL_ShowCursor(1);
|
SDL_ShowCursor(1);
|
||||||
|
|
||||||
|
@ -572,6 +564,42 @@ SDL_GetRelativeMouseMode()
|
||||||
return mouse->relative_mode;
|
return mouse->relative_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SDL_CaptureMouse(SDL_bool enabled)
|
||||||
|
{
|
||||||
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
SDL_Window *focusWindow;
|
||||||
|
SDL_bool isCaptured;
|
||||||
|
|
||||||
|
if (!mouse->CaptureMouse) {
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
focusWindow = SDL_GetKeyboardFocus();
|
||||||
|
|
||||||
|
isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE);
|
||||||
|
if (isCaptured == enabled) {
|
||||||
|
return 0; /* already done! */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
if (!focusWindow) {
|
||||||
|
return SDL_SetError("No window has focus");
|
||||||
|
} else if (mouse->CaptureMouse(focusWindow) == -1) {
|
||||||
|
return -1; /* CaptureMouse() should call SetError */
|
||||||
|
}
|
||||||
|
focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
|
||||||
|
} else {
|
||||||
|
if (mouse->CaptureMouse(NULL) == -1) {
|
||||||
|
return -1; /* CaptureMouse() should call SetError */
|
||||||
|
}
|
||||||
|
focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SDL_Cursor *
|
SDL_Cursor *
|
||||||
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
|
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
|
||||||
int w, int h, int hot_x, int hot_y)
|
int w, int h, int hot_x, int hot_y)
|
||||||
|
|
|
@ -63,6 +63,9 @@ typedef struct
|
||||||
/* Set relative mode */
|
/* Set relative mode */
|
||||||
int (*SetRelativeMouseMode) (SDL_bool enabled);
|
int (*SetRelativeMouseMode) (SDL_bool enabled);
|
||||||
|
|
||||||
|
/* Set mouse capture */
|
||||||
|
int (*CaptureMouse) (SDL_Window * window);
|
||||||
|
|
||||||
/* Data common to all mice */
|
/* Data common to all mice */
|
||||||
SDL_MouseID mouseID;
|
SDL_MouseID mouseID;
|
||||||
SDL_Window *focus;
|
SDL_Window *focus;
|
||||||
|
|
|
@ -999,10 +999,12 @@ default: return "???";
|
||||||
static void
|
static void
|
||||||
SDLTest_PrintEvent(SDL_Event * event)
|
SDLTest_PrintEvent(SDL_Event * event)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_FINGERMOTION)) {
|
if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_FINGERMOTION)) {
|
||||||
/* Mouse and finger motion are really spammy */
|
/* Mouse and finger motion are really spammy */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case SDL_WINDOWEVENT:
|
case SDL_WINDOWEVENT:
|
||||||
|
@ -1379,6 +1381,14 @@ SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (withShift) {
|
||||||
|
SDL_Window *current_win = SDL_GetKeyboardFocus();
|
||||||
|
if (current_win) {
|
||||||
|
const SDL_bool shouldCapture = (SDL_GetWindowFlags(current_win) & SDL_WINDOW_MOUSE_CAPTURE) == 0;
|
||||||
|
const int rc = SDL_CaptureMouse(shouldCapture);
|
||||||
|
printf("%sapturing mouse %s!\n", shouldCapture ? "C" : "Unc", (rc == 0) ? "succeeded" : "failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SDLK_v:
|
case SDLK_v:
|
||||||
if (withControl) {
|
if (withControl) {
|
||||||
|
|
|
@ -3269,12 +3269,17 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
SDL_bool relative_mode;
|
SDL_bool relative_mode;
|
||||||
int show_cursor_prev;
|
int show_cursor_prev;
|
||||||
|
SDL_bool mouse_captured;
|
||||||
|
SDL_Window *current_window;
|
||||||
|
|
||||||
if (!messageboxdata) {
|
if (!messageboxdata) {
|
||||||
return SDL_InvalidParamError("messageboxdata");
|
return SDL_InvalidParamError("messageboxdata");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_window = SDL_GetKeyboardFocus();
|
||||||
|
mouse_captured = current_window && ((SDL_GetWindowFlags(current_window) & SDL_WINDOW_MOUSE_CAPTURE) != 0);
|
||||||
relative_mode = SDL_GetRelativeMouseMode();
|
relative_mode = SDL_GetRelativeMouseMode();
|
||||||
|
SDL_CaptureMouse(SDL_FALSE);
|
||||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||||
show_cursor_prev = SDL_ShowCursor(1);
|
show_cursor_prev = SDL_ShowCursor(1);
|
||||||
|
|
||||||
|
@ -3326,6 +3331,13 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||||
SDL_SetError("No message system available");
|
SDL_SetError("No message system available");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current_window) {
|
||||||
|
SDL_RaiseWindow(current_window);
|
||||||
|
if (mouse_captured) {
|
||||||
|
SDL_CaptureMouse(SDL_TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SDL_ShowCursor(show_cursor_prev);
|
SDL_ShowCursor(show_cursor_prev);
|
||||||
SDL_SetRelativeMouseMode(relative_mode);
|
SDL_SetRelativeMouseMode(relative_mode);
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,19 @@ WIN_SetRelativeMouseMode(SDL_bool enabled)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
WIN_CaptureMouse(SDL_Window *window)
|
||||||
|
{
|
||||||
|
if (!window) {
|
||||||
|
ReleaseCapture();
|
||||||
|
} else {
|
||||||
|
const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||||
|
SetCapture(data->hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WIN_InitMouse(_THIS)
|
WIN_InitMouse(_THIS)
|
||||||
{
|
{
|
||||||
|
@ -230,6 +243,7 @@ WIN_InitMouse(_THIS)
|
||||||
mouse->FreeCursor = WIN_FreeCursor;
|
mouse->FreeCursor = WIN_FreeCursor;
|
||||||
mouse->WarpMouse = WIN_WarpMouse;
|
mouse->WarpMouse = WIN_WarpMouse;
|
||||||
mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
|
mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
|
||||||
|
mouse->CaptureMouse = WIN_CaptureMouse;
|
||||||
|
|
||||||
SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
|
SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
|
||||||
|
|
||||||
|
|
|
@ -330,6 +330,29 @@ X11_SetRelativeMouseMode(SDL_bool enabled)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
X11_CaptureMouse(SDL_Window *window)
|
||||||
|
{
|
||||||
|
Display *display = GetDisplay();
|
||||||
|
|
||||||
|
if (window) {
|
||||||
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||||
|
const unsigned int mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
|
||||||
|
const int rc = X11_XGrabPointer(display, data->xwindow, False,
|
||||||
|
mask, GrabModeAsync, GrabModeAsync,
|
||||||
|
None, None, CurrentTime);
|
||||||
|
if (rc != GrabSuccess) {
|
||||||
|
return SDL_SetError("X server refused mouse capture");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
X11_XUngrabPointer(display, CurrentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
X11_XSync(display, False);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
X11_InitMouse(_THIS)
|
X11_InitMouse(_THIS)
|
||||||
{
|
{
|
||||||
|
@ -341,6 +364,7 @@ X11_InitMouse(_THIS)
|
||||||
mouse->FreeCursor = X11_FreeCursor;
|
mouse->FreeCursor = X11_FreeCursor;
|
||||||
mouse->WarpMouse = X11_WarpMouse;
|
mouse->WarpMouse = X11_WarpMouse;
|
||||||
mouse->SetRelativeMouseMode = X11_SetRelativeMouseMode;
|
mouse->SetRelativeMouseMode = X11_SetRelativeMouseMode;
|
||||||
|
mouse->CaptureMouse = X11_CaptureMouse;
|
||||||
|
|
||||||
SDL_SetDefaultCursor(X11_CreateDefaultCursor());
|
SDL_SetDefaultCursor(X11_CreateDefaultCursor());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue