Expose separate keyboard and mouse grab support

This adds SDL_SetWindowKeyboardGrab(), SDL_GetWindowKeyboardGrab(),
SDL_SetWindowMouseGrab(), SDL_GetWindowMouseGrab(), and new
SDL_WINDOW_KEYBOARD_GRABBED flag. It also updates the test harness to exercise
this functionality and makes a minor fix to X11 that I missed in
https://hg.libsdl.org/SDL/rev/02a2d609369b

To fit in with this new support, SDL_WINDOW_INPUT_CAPTURE has been renamed to
SDL_WINDOW_MOUSE_CAPTURE with the old name remaining as an alias for backwards
compatibility with older code.
This commit is contained in:
Cameron Gutman 2021-01-26 19:16:17 -06:00
parent ff827fc767
commit 6b057c6783
12 changed files with 367 additions and 84 deletions

View File

@ -68,6 +68,8 @@ typedef struct
* \sa SDL_GetWindowData()
* \sa SDL_GetWindowFlags()
* \sa SDL_GetWindowGrab()
* \sa SDL_GetWindowKeyboardGrab()
* \sa SDL_GetWindowMouseGrab()
* \sa SDL_GetWindowPosition()
* \sa SDL_GetWindowSize()
* \sa SDL_GetWindowTitle()
@ -79,6 +81,8 @@ typedef struct
* \sa SDL_SetWindowData()
* \sa SDL_SetWindowFullscreen()
* \sa SDL_SetWindowGrab()
* \sa SDL_SetWindowKeyboardGrab()
* \sa SDL_SetWindowMouseGrab()
* \sa SDL_SetWindowIcon()
* \sa SDL_SetWindowPosition()
* \sa SDL_SetWindowSize()
@ -104,7 +108,7 @@ typedef enum
SDL_WINDOW_RESIZABLE = 0x00000020, /**< window can be resized */
SDL_WINDOW_MINIMIZED = 0x00000040, /**< window is minimized */
SDL_WINDOW_MAXIMIZED = 0x00000080, /**< window is maximized */
SDL_WINDOW_INPUT_GRABBED = 0x00000100, /**< window has grabbed input focus */
SDL_WINDOW_MOUSE_GRABBED = 0x00000100, /**< window has grabbed mouse input */
SDL_WINDOW_INPUT_FOCUS = 0x00000200, /**< window has input focus */
SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */
SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
@ -112,14 +116,17 @@ typedef enum
SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, /**< window should be created in high-DPI mode if supported.
On macOS NSHighResolutionCapable must be set true in the
application's Info.plist for this to have any effect. */
SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to INPUT_GRABBED) */
SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */
SDL_WINDOW_SKIP_TASKBAR = 0x00010000, /**< window should not be added to the taskbar */
SDL_WINDOW_UTILITY = 0x00020000, /**< window should be treated as a utility window */
SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */
SDL_WINDOW_POPUP_MENU = 0x00080000, /**< window should be treated as a popup menu */
SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */
SDL_WINDOW_METAL = 0x20000000 /**< window usable for Metal view */
SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to MOUSE_GRABBED) */
SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */
SDL_WINDOW_SKIP_TASKBAR = 0x00010000, /**< window should not be added to the taskbar */
SDL_WINDOW_UTILITY = 0x00020000, /**< window should be treated as a utility window */
SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */
SDL_WINDOW_POPUP_MENU = 0x00080000, /**< window should be treated as a popup menu */
SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */
SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */
SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */
SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */
} SDL_WindowFlags;
/**
@ -486,9 +493,9 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window * window);
* ::SDL_WINDOW_FULLSCREEN, ::SDL_WINDOW_OPENGL,
* ::SDL_WINDOW_HIDDEN, ::SDL_WINDOW_BORDERLESS,
* ::SDL_WINDOW_RESIZABLE, ::SDL_WINDOW_MAXIMIZED,
* ::SDL_WINDOW_MINIMIZED, ::SDL_WINDOW_INPUT_GRABBED,
* ::SDL_WINDOW_ALLOW_HIGHDPI, ::SDL_WINDOW_VULKAN
* ::SDL_WINDOW_METAL.
* ::SDL_WINDOW_MINIMIZED, ::SDL_WINDOW_MOUSE_GRABBED,
* ::SDL_WINDOW_ALLOW_HIGHDPI, ::SDL_WINDOW_KEYBOARD_GRABBED,
* ::SDL_WINDOW_VULKAN, ::SDL_WINDOW_METAL.
*
* \return The created window, or NULL if window creation failed.
*
@ -881,20 +888,78 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window,
* If the caller enables a grab while another window is currently grabbed,
* the other window loses its grab in favor of the caller's window.
*
* If SDL_HINT_GRAB_KEYBOARD=1, this also grabs keyboard input.
*
* \sa SDL_GetWindowGrab()
* \sa SDL_SetWindowKeyboardGrab()
* \sa SDL_SetWindowMouseGrab()
*/
extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window,
SDL_bool grabbed);
/**
* \brief Get a window's input grab mode.
* \brief Set a window's keyboard grab mode.
*
* \return This returns SDL_TRUE if input is grabbed, and SDL_FALSE otherwise.
* \param window The window for which the keyboard grab mode should be set.
* \param grabbed This is SDL_TRUE to grab keyboard, and SDL_FALSE to release keyboard grab.
*
* If the caller enables a grab while another window is currently grabbed,
* the other window loses its grab in favor of the caller's window.
*
* \sa SDL_GetWindowKeyboardGrab()
* \sa SDL_SetWindowMouseGrab()
* \sa SDL_SetWindowGrab()
*/
extern DECLSPEC void SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window * window,
SDL_bool grabbed);
/**
* \brief Set a window's mouse grab mode.
*
* \param window The window for which the mouse grab mode should be set.
* \param grabbed This is SDL_TRUE to grab mouse, and SDL_FALSE to release mouse grab.
*
* If the caller enables a grab while another window is currently grabbed,
* the other window loses its grab in favor of the caller's window.
*
* \sa SDL_GetWindowMouseGrab()
* \sa SDL_SetWindowKeyboardGrab()
* \sa SDL_SetWindowGrab()
*/
extern DECLSPEC void SDLCALL SDL_SetWindowMouseGrab(SDL_Window * window,
SDL_bool grabbed);
/**
* \brief Get a window's input grab mode.
*
* \return This returns SDL_TRUE if keyboard or mouse input is grabbed, and SDL_FALSE otherwise.
*
* \sa SDL_SetWindowGrab()
* \sa SDL_GetWindowMouseGrab()
* \sa SDL_GetWindowKeyboardGrab()
*/
extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window);
/**
* \brief Get a window's keyboard grab mode.
*
* \return This returns SDL_TRUE if keyboard is grabbed, and SDL_FALSE otherwise.
*
* \sa SDL_SetWindowKeyboardGrab()
* \sa SDL_GetWindowGrab()
*/
extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowKeyboardGrab(SDL_Window * window);
/**
* \brief Get a window's mouse grab mode.
*
* \return This returns SDL_TRUE if mouse is grabbed, and SDL_FALSE otherwise.
*
* \sa SDL_SetWindowKeyboardGrab()
* \sa SDL_GetWindowGrab()
*/
extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window * window);
/**
* \brief Get the window that currently has an input grab enabled.
*

View File

@ -795,3 +795,7 @@
#define SDL_SoftStretchLinear SDL_SoftStretchLinear_REAL
#define SDL_RenderGetD3D11Device SDL_RenderGetD3D11Device_REAL
#define SDL_UpdateNVTexture SDL_UpdateNVTexture_REAL
#define SDL_SetWindowKeyboardGrab SDL_SetWindowKeyboardGrab_REAL
#define SDL_SetWindowMouseGrab SDL_SetWindowMouseGrab_REAL
#define SDL_GetWindowKeyboardGrab SDL_GetWindowKeyboardGrab_REAL
#define SDL_GetWindowMouseGrab SDL_GetWindowMouseGrab_REAL

View File

@ -858,3 +858,7 @@ SDL_DYNAPI_PROC(int,SDL_SoftStretchLinear,(SDL_Surface *a, const SDL_Rect *b, SD
SDL_DYNAPI_PROC(ID3D11Device*,SDL_RenderGetD3D11Device,(SDL_Renderer *a),(a),return)
#endif
SDL_DYNAPI_PROC(int,SDL_UpdateNVTexture,(SDL_Texture *a, const SDL_Rect *b, const Uint8 *c, int d, const Uint8 *e, int f),(a,b,c,d,e,f),return)
SDL_DYNAPI_PROC(void,SDL_SetWindowKeyboardGrab,(SDL_Window *a, SDL_bool b),(a,b),)
SDL_DYNAPI_PROC(void,SDL_SetWindowMouseGrab,(SDL_Window *a, SDL_bool b),(a,b),)
SDL_DYNAPI_PROC(SDL_bool,SDL_GetWindowKeyboardGrab,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_GetWindowMouseGrab,(SDL_Window *a),(a),return)

View File

@ -34,7 +34,7 @@ static const char *video_usage[] = {
"[--icon icon.bmp]", "[--center | --position X,Y]", "[--geometry WxH]",
"[--min-geometry WxH]", "[--max-geometry WxH]", "[--logical WxH]",
"[--scale N]", "[--depth N]", "[--refresh R]", "[--vsync]", "[--noframe]",
"[--resize]", "[--minimize]", "[--maximize]", "[--grab]",
"[--resize]", "[--minimize]", "[--maximize]", "[--grab]", "[--keyboard-grab]",
"[--allow-highdpi]", "[--usable-bounds]"
};
@ -412,7 +412,11 @@ SDLTest_CommonArg(SDLTest_CommonState * state, int index)
return 1;
}
if (SDL_strcasecmp(argv[index], "--grab") == 0) {
state->window_flags |= SDL_WINDOW_INPUT_GRABBED;
state->window_flags |= SDL_WINDOW_MOUSE_GRABBED;
return 1;
}
if (SDL_strcasecmp(argv[index], "--keyboard-grab") == 0) {
state->window_flags |= SDL_WINDOW_KEYBOARD_GRABBED;
return 1;
}
if (SDL_strcasecmp(argv[index], "--rate") == 0) {
@ -1764,13 +1768,22 @@ SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
break;
case SDLK_g:
if (withControl) {
/* Ctrl-G toggle grab */
/* Ctrl-G toggle mouse grab */
SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
if (window) {
SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window) ? SDL_TRUE : SDL_FALSE);
}
}
break;
case SDLK_k:
if (withControl) {
/* Ctrl-K toggle keyboard grab */
SDL_Window* window = SDL_GetWindowFromID(event->key.windowID);
if (window) {
SDL_SetWindowKeyboardGrab(window, !SDL_GetWindowKeyboardGrab(window) ? SDL_TRUE : SDL_FALSE);
}
}
break;
case SDLK_m:
if (withControl) {
/* Ctrl-M maximize */

View File

@ -1433,9 +1433,17 @@ SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
if (flags & SDL_WINDOW_FULLSCREEN) {
SDL_SetWindowFullscreen(window, flags);
}
if (flags & SDL_WINDOW_INPUT_GRABBED) {
if (flags & SDL_WINDOW_MOUSE_GRABBED) {
/* We must specifically call SDL_SetWindowGrab() and not
SDL_SetWindowMouseGrab() here because older applications may use
this flag plus SDL_HINT_GRAB_KEYBOARD to indicate that they want
the keyboard grabbed too and SDL_SetWindowMouseGrab() won't do that.
*/
SDL_SetWindowGrab(window, SDL_TRUE);
}
if (flags & SDL_WINDOW_KEYBOARD_GRABBED) {
SDL_SetWindowKeyboardGrab(window, SDL_TRUE);
}
if (!(flags & SDL_WINDOW_HIDDEN)) {
SDL_ShowWindow(window);
}
@ -2638,41 +2646,46 @@ SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
void
SDL_UpdateWindowGrab(SDL_Window * window)
{
SDL_Window *grabbed_window;
SDL_bool grabbed;
if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
grabbed = SDL_TRUE;
SDL_bool keyboard_grabbed, mouse_grabbed;
if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
if (SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_MOUSE_GRABBED)) {
mouse_grabbed = SDL_TRUE;
} else {
mouse_grabbed = SDL_FALSE;
}
if (window->flags & SDL_WINDOW_KEYBOARD_GRABBED) {
keyboard_grabbed = SDL_TRUE;
} else {
keyboard_grabbed = SDL_FALSE;
}
} else {
grabbed = SDL_FALSE;
mouse_grabbed = SDL_FALSE;
keyboard_grabbed = SDL_FALSE;
}
grabbed_window = _this->grabbed_window;
if (grabbed) {
if (grabbed_window && (grabbed_window != window)) {
if (mouse_grabbed || keyboard_grabbed) {
if (_this->grabbed_window && (_this->grabbed_window != window)) {
/* stealing a grab from another window! */
grabbed_window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
_this->grabbed_window->flags &= ~(SDL_WINDOW_MOUSE_GRABBED | SDL_WINDOW_KEYBOARD_GRABBED);
if (_this->SetWindowMouseGrab) {
_this->SetWindowMouseGrab(_this, grabbed_window, SDL_FALSE);
_this->SetWindowMouseGrab(_this, _this->grabbed_window, SDL_FALSE);
}
if (_this->SetWindowKeyboardGrab) {
_this->SetWindowKeyboardGrab(_this, grabbed_window, SDL_FALSE);
_this->SetWindowKeyboardGrab(_this, _this->grabbed_window, SDL_FALSE);
}
}
_this->grabbed_window = window;
} else if (grabbed_window == window) {
_this->grabbed_window = NULL; /* ungrabbing. */
} else if (_this->grabbed_window == window) {
_this->grabbed_window = NULL; /* ungrabbing input. */
}
if (_this->SetWindowMouseGrab) {
_this->SetWindowMouseGrab(_this, window, grabbed);
_this->SetWindowMouseGrab(_this, window, mouse_grabbed);
}
if (_this->SetWindowKeyboardGrab) {
if (grabbed && SDL_GetHintBoolean(SDL_HINT_GRAB_KEYBOARD, SDL_FALSE)) {
_this->SetWindowKeyboardGrab(_this, window, SDL_TRUE);
} else {
_this->SetWindowKeyboardGrab(_this, window, SDL_FALSE);
}
_this->SetWindowKeyboardGrab(_this, window, keyboard_grabbed);
}
}
@ -2681,13 +2694,41 @@ SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
{
CHECK_WINDOW_MAGIC(window,);
if (!!grabbed == !!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
SDL_SetWindowMouseGrab(window, grabbed);
if (SDL_GetHintBoolean(SDL_HINT_GRAB_KEYBOARD, SDL_FALSE)) {
SDL_SetWindowKeyboardGrab(window, grabbed);
}
}
void
SDL_SetWindowKeyboardGrab(SDL_Window * window, SDL_bool grabbed)
{
CHECK_WINDOW_MAGIC(window,);
if (!!grabbed == !!(window->flags & SDL_WINDOW_KEYBOARD_GRABBED)) {
return;
}
if (grabbed) {
window->flags |= SDL_WINDOW_INPUT_GRABBED;
window->flags |= SDL_WINDOW_KEYBOARD_GRABBED;
} else {
window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
window->flags &= ~SDL_WINDOW_KEYBOARD_GRABBED;
}
SDL_UpdateWindowGrab(window);
}
void
SDL_SetWindowMouseGrab(SDL_Window * window, SDL_bool grabbed)
{
CHECK_WINDOW_MAGIC(window,);
if (!!grabbed == !!(window->flags & SDL_WINDOW_MOUSE_GRABBED)) {
return;
}
if (grabbed) {
window->flags |= SDL_WINDOW_MOUSE_GRABBED;
} else {
window->flags &= ~SDL_WINDOW_MOUSE_GRABBED;
}
SDL_UpdateWindowGrab(window);
}
@ -2696,14 +2737,34 @@ SDL_bool
SDL_GetWindowGrab(SDL_Window * window)
{
CHECK_WINDOW_MAGIC(window, SDL_FALSE);
SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
SDL_assert(!_this->grabbed_window ||
((_this->grabbed_window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0) ||
((_this->grabbed_window->flags & SDL_WINDOW_KEYBOARD_GRABBED) != 0));
return window == _this->grabbed_window;
}
SDL_bool
SDL_GetWindowKeyboardGrab(SDL_Window * window)
{
CHECK_WINDOW_MAGIC(window, SDL_FALSE);
return window == _this->grabbed_window &&
((_this->grabbed_window->flags & SDL_WINDOW_KEYBOARD_GRABBED) != 0);
}
SDL_bool
SDL_GetWindowMouseGrab(SDL_Window * window)
{
CHECK_WINDOW_MAGIC(window, SDL_FALSE);
return window == _this->grabbed_window &&
((_this->grabbed_window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0);
}
SDL_Window *
SDL_GetGrabbedWindow(void)
{
SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
SDL_assert(!_this->grabbed_window ||
((_this->grabbed_window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0) ||
((_this->grabbed_window->flags & SDL_WINDOW_KEYBOARD_GRABBED) != 0));
return _this->grabbed_window;
}

View File

@ -90,7 +90,7 @@ Cocoa_MouseTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event
return event;
}
if (!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
if (!(window->flags & SDL_WINDOW_MOUSE_GRABBED)) {
return event;
}

View File

@ -1109,7 +1109,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
x = (int)point.x;
y = (int)(window->h - point.y);
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
if (window->flags & SDL_WINDOW_MOUSE_GRABBED) {
if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
if (x < 0) {
x = 0;

View File

@ -212,7 +212,7 @@ ProcessWindowEvent(_THIS, SDL_Window *sdlwin, DFBWindowEvent * evt)
case DWET_MOTION:
if (ClientXY(windata, &evt->x, &evt->y)) {
if (!devdata->use_linux_input) {
if (!(sdlwin->flags & SDL_WINDOW_INPUT_GRABBED))
if (!(sdlwin->flags & SDL_WINDOW_MOUSE_GRABBED))
SDL_SendMouseMotion_ex(sdlwin, devdata->mouse_id[0], 0,
evt->x, evt->y, 0);
} else {

View File

@ -183,7 +183,7 @@ static VOID _mouseCheck(WINDATA *pWinData)
{
SDL_Mouse *pSDLMouse = SDL_GetMouse();
if ((pSDLMouse->relative_mode || (pWinData->window->flags & SDL_WINDOW_INPUT_GRABBED) != 0) &&
if ((pSDLMouse->relative_mode || (pWinData->window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0) &&
((pWinData->window->flags & SDL_WINDOW_INPUT_FOCUS) != 0)) {
/* We will make a real capture in _wmMouseButton() */
} else {
@ -232,7 +232,7 @@ static VOID _wmMouseMove(WINDATA *pWinData, SHORT lX, SHORT lY)
if (!pSDLMouse->relative_mode || pSDLMouse->relative_mode_warp) {
if (!pSDLMouse->relative_mode && fWinActive &&
((pWinData->window->flags & SDL_WINDOW_INPUT_GRABBED) != 0) &&
((pWinData->window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0) &&
(WinQueryCapture(HWND_DESKTOP) == pWinData->hwnd)) {
pointl.x = lX;
@ -281,7 +281,7 @@ static VOID _wmMouseButton(WINDATA *pWinData, ULONG ulButton, BOOL fDown)
SDL_BUTTON_MIDDLE };
SDL_Mouse *pSDLMouse = SDL_GetMouse();
if ((pSDLMouse->relative_mode || ((pWinData->window->flags & SDL_WINDOW_INPUT_GRABBED) != 0)) &&
if ((pSDLMouse->relative_mode || ((pWinData->window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0)) &&
((pWinData->window->flags & SDL_WINDOW_INPUT_FOCUS) != 0) &&
(WinQueryCapture(HWND_DESKTOP) != pWinData->hwnd)) {
/* Mouse should be captured. */

View File

@ -282,7 +282,7 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool cre
window->flags |= SDL_WINDOW_INPUT_FOCUS;
SDL_SetKeyboardFocus(data->window);
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
if (window->flags & SDL_WINDOW_MOUSE_GRABBED) {
RECT rect;
GetClientRect(hwnd, &rect);
ClientToScreen(hwnd, (LPPOINT) & rect);
@ -973,7 +973,7 @@ WIN_UpdateClipCursor(SDL_Window *window)
return;
}
if ((mouse->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
if ((mouse->relative_mode || (window->flags & SDL_WINDOW_MOUSE_GRABBED)) &&
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
if (mouse->relative_mode && !mouse->relative_mode_warp) {
if (GetWindowRect(data->hwnd, &rect)) {

View File

@ -325,7 +325,7 @@ SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
SDL_SetKeyboardFocus(data->window);
}
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
if (window->flags & SDL_WINDOW_MOUSE_GRABBED) {
/* Tell x11 to clip mouse */
}
}
@ -1623,6 +1623,13 @@ X11_SetWindowKeyboardGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
Display *display = data->videodata->display;
if (grabbed) {
/* If the window is unmapped, XGrab calls return GrabNotViewable,
so when we get a MapNotify later, we'll try to update the grab as
appropriate. */
if (window->flags & SDL_WINDOW_HIDDEN) {
return;
}
X11_XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
GrabModeAsync, CurrentTime);
} else {

View File

@ -265,7 +265,7 @@ video_createWindowVariousFlags(void *arg)
w = SDLTest_RandomIntegerInRange(320, 1024);
h = SDLTest_RandomIntegerInRange(320, 768);
for (fVariation = 0; fVariation < 13; fVariation++) {
for (fVariation = 0; fVariation < 14; fVariation++) {
switch(fVariation) {
case 0:
flags = SDL_WINDOW_FULLSCREEN;
@ -299,7 +299,7 @@ video_createWindowVariousFlags(void *arg)
flags = SDL_WINDOW_MAXIMIZED;
break;
case 9:
flags = SDL_WINDOW_INPUT_GRABBED;
flags = SDL_WINDOW_MOUSE_GRABBED;
break;
case 10:
flags = SDL_WINDOW_INPUT_FOCUS;
@ -310,6 +310,9 @@ video_createWindowVariousFlags(void *arg)
case 12:
flags = SDL_WINDOW_FOREIGN;
break;
case 13:
flags = SDL_WINDOW_KEYBOARD_GRABBED;
break;
}
window = SDL_CreateWindow(title, x, y, w, h, flags);
@ -744,87 +747,213 @@ video_getWindowGammaRampNegative(void *arg)
return TEST_COMPLETED;
}
/* Helper for setting and checking the window grab state */
/* Helper for setting and checking the window mouse grab state */
void
_setAndCheckWindowGrabState(SDL_Window* window, SDL_bool desiredState)
_setAndCheckWindowMouseGrabState(SDL_Window* window, SDL_bool desiredState)
{
SDL_bool currentState;
/* Set state */
SDL_SetWindowGrab(window, desiredState);
SDLTest_AssertPass("Call to SDL_SetWindowGrab(%s)", (desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE");
SDL_SetWindowMouseGrab(window, desiredState);
SDLTest_AssertPass("Call to SDL_SetWindowMouseGrab(%s)", (desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE");
/* Get and check state */
currentState = SDL_GetWindowGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowGrab()");
currentState = SDL_GetWindowMouseGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowMouseGrab()");
SDLTest_AssertCheck(
currentState == desiredState,
"Validate returned state; expected: %s, got: %s",
(desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE",
(currentState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE");
if (desiredState) {
SDLTest_AssertCheck(
SDL_GetGrabbedWindow() == window,
"Grabbed window should be to our window");
SDLTest_AssertCheck(
SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_TRUE");
SDLTest_AssertCheck(
SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_GRABBED,
"SDL_WINDOW_MOUSE_GRABBED should be set");
} else {
SDLTest_AssertCheck(
!(SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_GRABBED),
"SDL_WINDOW_MOUSE_GRABBED should be unset");
}
}
/* Helper for setting and checking the window keyboard grab state */
void
_setAndCheckWindowKeyboardGrabState(SDL_Window* window, SDL_bool desiredState)
{
SDL_bool currentState;
/* Set state */
SDL_SetWindowKeyboardGrab(window, desiredState);
SDLTest_AssertPass("Call to SDL_SetWindowKeyboardGrab(%s)", (desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE");
/* Get and check state */
currentState = SDL_GetWindowKeyboardGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowKeyboardGrab()");
SDLTest_AssertCheck(
currentState == desiredState,
"Validate returned state; expected: %s, got: %s",
(desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE",
(currentState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE");
if (desiredState) {
SDLTest_AssertCheck(
SDL_GetGrabbedWindow() == window,
"Grabbed window should be set to our window");
SDLTest_AssertCheck(
SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_TRUE");
SDLTest_AssertCheck(
SDL_GetWindowFlags(window) & SDL_WINDOW_KEYBOARD_GRABBED,
"SDL_WINDOW_KEYBOARD_GRABBED should be set");
} else {
SDLTest_AssertCheck(
!(SDL_GetWindowFlags(window) & SDL_WINDOW_KEYBOARD_GRABBED),
"SDL_WINDOW_KEYBOARD_GRABBED should be unset");
}
}
/**
* @brief Tests call to SDL_GetWindowGrab and SDL_SetWindowGrab
* @brief Tests keyboard and mouse grab support
*
* @sa http://wiki.libsdl.org/moin.fcg/SDL_GetWindowGrab
* @sa http://wiki.libsdl.org/moin.fcg/SDL_SetWindowGrab
* @sa http://wiki.libsdl.org/SDL_GetWindowGrab
* @sa http://wiki.libsdl.org/SDL_SetWindowGrab
*/
int
video_getSetWindowGrab(void *arg)
{
const char* title = "video_getSetWindowGrab Test Window";
SDL_Window* window;
SDL_bool originalState, dummyState, currentState, desiredState;
SDL_bool originalMouseState, originalKeyboardState, dummyState;
/* Call against new test window */
window = _createVideoSuiteTestWindow(title);
if (window == NULL) return TEST_ABORTED;
/* Get state */
originalState = SDL_GetWindowGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowGrab()");
originalMouseState = SDL_GetWindowMouseGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowMouseGrab()");
originalKeyboardState = SDL_GetWindowKeyboardGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowKeyboardGrab()");
/* F */
_setAndCheckWindowGrabState(window, SDL_FALSE);
_setAndCheckWindowKeyboardGrabState(window, SDL_FALSE);
_setAndCheckWindowMouseGrabState(window, SDL_FALSE);
SDLTest_AssertCheck(!SDL_GetWindowGrab(window),
"SDL_GetWindowGrab should return SDL_FALSE");
SDLTest_AssertCheck(SDL_GetGrabbedWindow() == NULL,
"Expected NULL grabbed window");
/* F --> F */
_setAndCheckWindowGrabState(window, SDL_FALSE);
_setAndCheckWindowMouseGrabState(window, SDL_FALSE);
_setAndCheckWindowKeyboardGrabState(window, SDL_FALSE);
SDLTest_AssertCheck(SDL_GetGrabbedWindow() == NULL,
"Expected NULL grabbed window");
/* F --> T */
_setAndCheckWindowGrabState(window, SDL_TRUE);
_setAndCheckWindowMouseGrabState(window, SDL_TRUE);
_setAndCheckWindowKeyboardGrabState(window, SDL_TRUE);
SDLTest_AssertCheck(SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_TRUE");
/* T --> T */
_setAndCheckWindowGrabState(window, SDL_TRUE);
_setAndCheckWindowKeyboardGrabState(window, SDL_TRUE);
_setAndCheckWindowMouseGrabState(window, SDL_TRUE);
SDLTest_AssertCheck(SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_TRUE");
/* T --> F */
_setAndCheckWindowGrabState(window, SDL_FALSE);
/* M: T --> F */
/* K: T --> T */
_setAndCheckWindowKeyboardGrabState(window, SDL_TRUE);
_setAndCheckWindowMouseGrabState(window, SDL_FALSE);
SDLTest_AssertCheck(SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_TRUE");
/* M: F --> T */
/* K: T --> F */
_setAndCheckWindowMouseGrabState(window, SDL_TRUE);
_setAndCheckWindowKeyboardGrabState(window, SDL_FALSE);
SDLTest_AssertCheck(SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_TRUE");
/* M: T --> F */
/* K: F --> F */
_setAndCheckWindowMouseGrabState(window, SDL_FALSE);
_setAndCheckWindowKeyboardGrabState(window, SDL_FALSE);
SDLTest_AssertCheck(!SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_FALSE");
SDLTest_AssertCheck(SDL_GetGrabbedWindow() == NULL,
"Expected NULL grabbed window");
/* Using the older SDL_SetWindowGrab API should only grab mouse by default */
SDL_SetWindowGrab(window, SDL_TRUE);
SDLTest_AssertPass("Call to SDL_SetWindowGrab(SDL_TRUE)");
SDLTest_AssertCheck(SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_TRUE");
SDLTest_AssertCheck(SDL_GetWindowMouseGrab(window),
"SDL_GetWindowMouseGrab() should return SDL_TRUE");
SDLTest_AssertCheck(!SDL_GetWindowKeyboardGrab(window),
"SDL_GetWindowKeyboardGrab() should return SDL_FALSE");
SDL_SetWindowGrab(window, SDL_FALSE);
SDLTest_AssertCheck(!SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_FALSE");
SDLTest_AssertCheck(!SDL_GetWindowMouseGrab(window),
"SDL_GetWindowMouseGrab() should return SDL_FALSE");
SDLTest_AssertCheck(!SDL_GetWindowKeyboardGrab(window),
"SDL_GetWindowKeyboardGrab() should return SDL_FALSE");
/* Now test with SDL_HINT_GRAB_KEYBOARD set. We should get keyboard grab now. */
SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1");
SDL_SetWindowGrab(window, SDL_TRUE);
SDLTest_AssertPass("Call to SDL_SetWindowGrab(SDL_TRUE)");
SDLTest_AssertCheck(SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_TRUE");
SDLTest_AssertCheck(SDL_GetWindowMouseGrab(window),
"SDL_GetWindowMouseGrab() should return SDL_TRUE");
SDLTest_AssertCheck(SDL_GetWindowKeyboardGrab(window),
"SDL_GetWindowKeyboardGrab() should return SDL_TRUE");
SDL_SetWindowGrab(window, SDL_FALSE);
SDLTest_AssertCheck(!SDL_GetWindowGrab(window),
"SDL_GetWindowGrab() should return SDL_FALSE");
SDLTest_AssertCheck(!SDL_GetWindowMouseGrab(window),
"SDL_GetWindowMouseGrab() should return SDL_FALSE");
SDLTest_AssertCheck(!SDL_GetWindowKeyboardGrab(window),
"SDL_GetWindowKeyboardGrab() should return SDL_FALSE");
/* Negative tests */
dummyState = SDL_GetWindowGrab(NULL);
SDLTest_AssertPass("Call to SDL_GetWindowGrab(window=NULL)");
_checkInvalidWindowError();
dummyState = SDL_GetWindowKeyboardGrab(NULL);
SDLTest_AssertPass("Call to SDL_GetWindowKeyboardGrab(window=NULL)");
_checkInvalidWindowError();
SDL_SetWindowGrab(NULL, SDL_FALSE);
SDLTest_AssertPass("Call to SDL_SetWindowGrab(window=NULL,SDL_FALSE)");
_checkInvalidWindowError();
SDL_SetWindowGrab(NULL, SDL_TRUE);
SDLTest_AssertPass("Call to SDL_SetWindowGrab(window=NULL,SDL_FALSE)");
SDL_SetWindowKeyboardGrab(NULL, SDL_FALSE);
SDLTest_AssertPass("Call to SDL_SetWindowKeyboardGrab(window=NULL,SDL_FALSE)");
_checkInvalidWindowError();
/* State should still be F */
desiredState = SDL_FALSE;
currentState = SDL_GetWindowGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowGrab()");
SDLTest_AssertCheck(
currentState == desiredState,
"Validate returned state; expected: %s, got: %s",
(desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE",
(currentState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE");
SDL_SetWindowGrab(NULL, SDL_TRUE);
SDLTest_AssertPass("Call to SDL_SetWindowGrab(window=NULL,SDL_TRUE)");
_checkInvalidWindowError();
SDL_SetWindowKeyboardGrab(NULL, SDL_TRUE);
SDLTest_AssertPass("Call to SDL_SetWindowKeyboardGrab(window=NULL,SDL_TRUE)");
_checkInvalidWindowError();
/* Restore state */
_setAndCheckWindowGrabState(window, originalState);
_setAndCheckWindowMouseGrabState(window, originalMouseState);
_setAndCheckWindowKeyboardGrabState(window, originalKeyboardState);
/* Clean up */
_destroyVideoSuiteTestWindow(window);