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_GetWindowData()
* \sa SDL_GetWindowFlags() * \sa SDL_GetWindowFlags()
* \sa SDL_GetWindowGrab() * \sa SDL_GetWindowGrab()
* \sa SDL_GetWindowKeyboardGrab()
* \sa SDL_GetWindowMouseGrab()
* \sa SDL_GetWindowPosition() * \sa SDL_GetWindowPosition()
* \sa SDL_GetWindowSize() * \sa SDL_GetWindowSize()
* \sa SDL_GetWindowTitle() * \sa SDL_GetWindowTitle()
@ -79,6 +81,8 @@ typedef struct
* \sa SDL_SetWindowData() * \sa SDL_SetWindowData()
* \sa SDL_SetWindowFullscreen() * \sa SDL_SetWindowFullscreen()
* \sa SDL_SetWindowGrab() * \sa SDL_SetWindowGrab()
* \sa SDL_SetWindowKeyboardGrab()
* \sa SDL_SetWindowMouseGrab()
* \sa SDL_SetWindowIcon() * \sa SDL_SetWindowIcon()
* \sa SDL_SetWindowPosition() * \sa SDL_SetWindowPosition()
* \sa SDL_SetWindowSize() * \sa SDL_SetWindowSize()
@ -104,7 +108,7 @@ typedef enum
SDL_WINDOW_RESIZABLE = 0x00000020, /**< window can be resized */ SDL_WINDOW_RESIZABLE = 0x00000020, /**< window can be resized */
SDL_WINDOW_MINIMIZED = 0x00000040, /**< window is minimized */ SDL_WINDOW_MINIMIZED = 0x00000040, /**< window is minimized */
SDL_WINDOW_MAXIMIZED = 0x00000080, /**< window is maximized */ 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_INPUT_FOCUS = 0x00000200, /**< window has input focus */
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 ),
@ -112,14 +116,17 @@ typedef enum
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.
On macOS NSHighResolutionCapable must be set true in the On macOS NSHighResolutionCapable must be set true in the
application's Info.plist for this to have any effect. */ 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_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_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_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_UTILITY = 0x00020000, /**< window should be treated as a utility window */
SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */ 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_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_VULKAN = 0x10000000, /**< window usable for Vulkan surface */
SDL_WINDOW_METAL = 0x20000000 /**< window usable for Metal view */ 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; } SDL_WindowFlags;
/** /**
@ -486,9 +493,9 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window * window);
* ::SDL_WINDOW_FULLSCREEN, ::SDL_WINDOW_OPENGL, * ::SDL_WINDOW_FULLSCREEN, ::SDL_WINDOW_OPENGL,
* ::SDL_WINDOW_HIDDEN, ::SDL_WINDOW_BORDERLESS, * ::SDL_WINDOW_HIDDEN, ::SDL_WINDOW_BORDERLESS,
* ::SDL_WINDOW_RESIZABLE, ::SDL_WINDOW_MAXIMIZED, * ::SDL_WINDOW_RESIZABLE, ::SDL_WINDOW_MAXIMIZED,
* ::SDL_WINDOW_MINIMIZED, ::SDL_WINDOW_INPUT_GRABBED, * ::SDL_WINDOW_MINIMIZED, ::SDL_WINDOW_MOUSE_GRABBED,
* ::SDL_WINDOW_ALLOW_HIGHDPI, ::SDL_WINDOW_VULKAN * ::SDL_WINDOW_ALLOW_HIGHDPI, ::SDL_WINDOW_KEYBOARD_GRABBED,
* ::SDL_WINDOW_METAL. * ::SDL_WINDOW_VULKAN, ::SDL_WINDOW_METAL.
* *
* \return The created window, or NULL if window creation failed. * \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, * 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. * 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_GetWindowGrab()
* \sa SDL_SetWindowKeyboardGrab()
* \sa SDL_SetWindowMouseGrab()
*/ */
extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window, extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window,
SDL_bool grabbed); 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() * \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); 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. * \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_SoftStretchLinear SDL_SoftStretchLinear_REAL
#define SDL_RenderGetD3D11Device SDL_RenderGetD3D11Device_REAL #define SDL_RenderGetD3D11Device SDL_RenderGetD3D11Device_REAL
#define SDL_UpdateNVTexture SDL_UpdateNVTexture_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) SDL_DYNAPI_PROC(ID3D11Device*,SDL_RenderGetD3D11Device,(SDL_Renderer *a),(a),return)
#endif #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(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]", "[--icon icon.bmp]", "[--center | --position X,Y]", "[--geometry WxH]",
"[--min-geometry WxH]", "[--max-geometry WxH]", "[--logical WxH]", "[--min-geometry WxH]", "[--max-geometry WxH]", "[--logical WxH]",
"[--scale N]", "[--depth N]", "[--refresh R]", "[--vsync]", "[--noframe]", "[--scale N]", "[--depth N]", "[--refresh R]", "[--vsync]", "[--noframe]",
"[--resize]", "[--minimize]", "[--maximize]", "[--grab]", "[--resize]", "[--minimize]", "[--maximize]", "[--grab]", "[--keyboard-grab]",
"[--allow-highdpi]", "[--usable-bounds]" "[--allow-highdpi]", "[--usable-bounds]"
}; };
@ -412,7 +412,11 @@ SDLTest_CommonArg(SDLTest_CommonState * state, int index)
return 1; return 1;
} }
if (SDL_strcasecmp(argv[index], "--grab") == 0) { 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; return 1;
} }
if (SDL_strcasecmp(argv[index], "--rate") == 0) { if (SDL_strcasecmp(argv[index], "--rate") == 0) {
@ -1764,13 +1768,22 @@ SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
break; break;
case SDLK_g: case SDLK_g:
if (withControl) { if (withControl) {
/* Ctrl-G toggle grab */ /* Ctrl-G toggle mouse grab */
SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
if (window) { if (window) {
SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window) ? SDL_TRUE : SDL_FALSE); SDL_SetWindowGrab(window, !SDL_GetWindowGrab(window) ? SDL_TRUE : SDL_FALSE);
} }
} }
break; 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: case SDLK_m:
if (withControl) { if (withControl) {
/* Ctrl-M maximize */ /* Ctrl-M maximize */

View File

@ -1433,9 +1433,17 @@ SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
if (flags & SDL_WINDOW_FULLSCREEN) { if (flags & SDL_WINDOW_FULLSCREEN) {
SDL_SetWindowFullscreen(window, flags); 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); SDL_SetWindowGrab(window, SDL_TRUE);
} }
if (flags & SDL_WINDOW_KEYBOARD_GRABBED) {
SDL_SetWindowKeyboardGrab(window, SDL_TRUE);
}
if (!(flags & SDL_WINDOW_HIDDEN)) { if (!(flags & SDL_WINDOW_HIDDEN)) {
SDL_ShowWindow(window); SDL_ShowWindow(window);
} }
@ -2638,41 +2646,46 @@ SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
void void
SDL_UpdateWindowGrab(SDL_Window * window) SDL_UpdateWindowGrab(SDL_Window * window)
{ {
SDL_Window *grabbed_window; SDL_bool keyboard_grabbed, mouse_grabbed;
SDL_bool grabbed;
if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) && if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
(window->flags & SDL_WINDOW_INPUT_FOCUS)) { if (SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_MOUSE_GRABBED)) {
grabbed = SDL_TRUE; mouse_grabbed = SDL_TRUE;
} else { } else {
grabbed = SDL_FALSE; mouse_grabbed = SDL_FALSE;
} }
grabbed_window = _this->grabbed_window; if (window->flags & SDL_WINDOW_KEYBOARD_GRABBED) {
if (grabbed) { keyboard_grabbed = SDL_TRUE;
if (grabbed_window && (grabbed_window != window)) { } else {
keyboard_grabbed = SDL_FALSE;
}
} else {
mouse_grabbed = SDL_FALSE;
keyboard_grabbed = SDL_FALSE;
}
if (mouse_grabbed || keyboard_grabbed) {
if (_this->grabbed_window && (_this->grabbed_window != window)) {
/* stealing a grab from another 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) { if (_this->SetWindowMouseGrab) {
_this->SetWindowMouseGrab(_this, grabbed_window, SDL_FALSE); _this->SetWindowMouseGrab(_this, _this->grabbed_window, SDL_FALSE);
} }
if (_this->SetWindowKeyboardGrab) { if (_this->SetWindowKeyboardGrab) {
_this->SetWindowKeyboardGrab(_this, grabbed_window, SDL_FALSE); _this->SetWindowKeyboardGrab(_this, _this->grabbed_window, SDL_FALSE);
} }
} }
_this->grabbed_window = window; _this->grabbed_window = window;
} else if (grabbed_window == window) { } else if (_this->grabbed_window == window) {
_this->grabbed_window = NULL; /* ungrabbing. */ _this->grabbed_window = NULL; /* ungrabbing input. */
} }
if (_this->SetWindowMouseGrab) { if (_this->SetWindowMouseGrab) {
_this->SetWindowMouseGrab(_this, window, grabbed); _this->SetWindowMouseGrab(_this, window, mouse_grabbed);
} }
if (_this->SetWindowKeyboardGrab) { if (_this->SetWindowKeyboardGrab) {
if (grabbed && SDL_GetHintBoolean(SDL_HINT_GRAB_KEYBOARD, SDL_FALSE)) { _this->SetWindowKeyboardGrab(_this, window, keyboard_grabbed);
_this->SetWindowKeyboardGrab(_this, window, SDL_TRUE);
} else {
_this->SetWindowKeyboardGrab(_this, window, SDL_FALSE);
}
} }
} }
@ -2681,13 +2694,41 @@ SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed)
{ {
CHECK_WINDOW_MAGIC(window,); 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; return;
} }
if (grabbed) { if (grabbed) {
window->flags |= SDL_WINDOW_INPUT_GRABBED; window->flags |= SDL_WINDOW_KEYBOARD_GRABBED;
} else { } 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); SDL_UpdateWindowGrab(window);
} }
@ -2696,14 +2737,34 @@ SDL_bool
SDL_GetWindowGrab(SDL_Window * window) SDL_GetWindowGrab(SDL_Window * window)
{ {
CHECK_WINDOW_MAGIC(window, SDL_FALSE); 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; 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_Window *
SDL_GetGrabbedWindow(void) 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; return _this->grabbed_window;
} }

View File

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

View File

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

View File

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

View File

@ -183,7 +183,7 @@ static VOID _mouseCheck(WINDATA *pWinData)
{ {
SDL_Mouse *pSDLMouse = SDL_GetMouse(); 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)) { ((pWinData->window->flags & SDL_WINDOW_INPUT_FOCUS) != 0)) {
/* We will make a real capture in _wmMouseButton() */ /* We will make a real capture in _wmMouseButton() */
} else { } 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 || pSDLMouse->relative_mode_warp) {
if (!pSDLMouse->relative_mode && fWinActive && 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)) { (WinQueryCapture(HWND_DESKTOP) == pWinData->hwnd)) {
pointl.x = lX; pointl.x = lX;
@ -281,7 +281,7 @@ static VOID _wmMouseButton(WINDATA *pWinData, ULONG ulButton, BOOL fDown)
SDL_BUTTON_MIDDLE }; SDL_BUTTON_MIDDLE };
SDL_Mouse *pSDLMouse = SDL_GetMouse(); 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) && ((pWinData->window->flags & SDL_WINDOW_INPUT_FOCUS) != 0) &&
(WinQueryCapture(HWND_DESKTOP) != pWinData->hwnd)) { (WinQueryCapture(HWND_DESKTOP) != pWinData->hwnd)) {
/* Mouse should be captured. */ /* 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; window->flags |= SDL_WINDOW_INPUT_FOCUS;
SDL_SetKeyboardFocus(data->window); SDL_SetKeyboardFocus(data->window);
if (window->flags & SDL_WINDOW_INPUT_GRABBED) { if (window->flags & SDL_WINDOW_MOUSE_GRABBED) {
RECT rect; RECT rect;
GetClientRect(hwnd, &rect); GetClientRect(hwnd, &rect);
ClientToScreen(hwnd, (LPPOINT) & rect); ClientToScreen(hwnd, (LPPOINT) & rect);
@ -973,7 +973,7 @@ WIN_UpdateClipCursor(SDL_Window *window)
return; 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)) { (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
if (mouse->relative_mode && !mouse->relative_mode_warp) { if (mouse->relative_mode && !mouse->relative_mode_warp) {
if (GetWindowRect(data->hwnd, &rect)) { if (GetWindowRect(data->hwnd, &rect)) {

View File

@ -325,7 +325,7 @@ SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
SDL_SetKeyboardFocus(data->window); SDL_SetKeyboardFocus(data->window);
} }
if (window->flags & SDL_WINDOW_INPUT_GRABBED) { if (window->flags & SDL_WINDOW_MOUSE_GRABBED) {
/* Tell x11 to clip mouse */ /* Tell x11 to clip mouse */
} }
} }
@ -1623,6 +1623,13 @@ X11_SetWindowKeyboardGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
Display *display = data->videodata->display; Display *display = data->videodata->display;
if (grabbed) { 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, X11_XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
GrabModeAsync, CurrentTime); GrabModeAsync, CurrentTime);
} else { } else {

View File

@ -265,7 +265,7 @@ video_createWindowVariousFlags(void *arg)
w = SDLTest_RandomIntegerInRange(320, 1024); w = SDLTest_RandomIntegerInRange(320, 1024);
h = SDLTest_RandomIntegerInRange(320, 768); h = SDLTest_RandomIntegerInRange(320, 768);
for (fVariation = 0; fVariation < 13; fVariation++) { for (fVariation = 0; fVariation < 14; fVariation++) {
switch(fVariation) { switch(fVariation) {
case 0: case 0:
flags = SDL_WINDOW_FULLSCREEN; flags = SDL_WINDOW_FULLSCREEN;
@ -299,7 +299,7 @@ video_createWindowVariousFlags(void *arg)
flags = SDL_WINDOW_MAXIMIZED; flags = SDL_WINDOW_MAXIMIZED;
break; break;
case 9: case 9:
flags = SDL_WINDOW_INPUT_GRABBED; flags = SDL_WINDOW_MOUSE_GRABBED;
break; break;
case 10: case 10:
flags = SDL_WINDOW_INPUT_FOCUS; flags = SDL_WINDOW_INPUT_FOCUS;
@ -310,6 +310,9 @@ video_createWindowVariousFlags(void *arg)
case 12: case 12:
flags = SDL_WINDOW_FOREIGN; flags = SDL_WINDOW_FOREIGN;
break; break;
case 13:
flags = SDL_WINDOW_KEYBOARD_GRABBED;
break;
} }
window = SDL_CreateWindow(title, x, y, w, h, flags); window = SDL_CreateWindow(title, x, y, w, h, flags);
@ -744,87 +747,213 @@ video_getWindowGammaRampNegative(void *arg)
return TEST_COMPLETED; return TEST_COMPLETED;
} }
/* Helper for setting and checking the window grab state */ /* Helper for setting and checking the window mouse grab state */
void void
_setAndCheckWindowGrabState(SDL_Window* window, SDL_bool desiredState) _setAndCheckWindowMouseGrabState(SDL_Window* window, SDL_bool desiredState)
{ {
SDL_bool currentState; SDL_bool currentState;
/* Set state */ /* Set state */
SDL_SetWindowGrab(window, desiredState); SDL_SetWindowMouseGrab(window, desiredState);
SDLTest_AssertPass("Call to SDL_SetWindowGrab(%s)", (desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE"); SDLTest_AssertPass("Call to SDL_SetWindowMouseGrab(%s)", (desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE");
/* Get and check state */ /* Get and check state */
currentState = SDL_GetWindowGrab(window); currentState = SDL_GetWindowMouseGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowGrab()"); SDLTest_AssertPass("Call to SDL_GetWindowMouseGrab()");
SDLTest_AssertCheck( SDLTest_AssertCheck(
currentState == desiredState, currentState == desiredState,
"Validate returned state; expected: %s, got: %s", "Validate returned state; expected: %s, got: %s",
(desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE", (desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE",
(currentState == 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/SDL_GetWindowGrab
* @sa http://wiki.libsdl.org/moin.fcg/SDL_SetWindowGrab * @sa http://wiki.libsdl.org/SDL_SetWindowGrab
*/ */
int int
video_getSetWindowGrab(void *arg) video_getSetWindowGrab(void *arg)
{ {
const char* title = "video_getSetWindowGrab Test Window"; const char* title = "video_getSetWindowGrab Test Window";
SDL_Window* window; SDL_Window* window;
SDL_bool originalState, dummyState, currentState, desiredState; SDL_bool originalMouseState, originalKeyboardState, dummyState;
/* Call against new test window */ /* Call against new test window */
window = _createVideoSuiteTestWindow(title); window = _createVideoSuiteTestWindow(title);
if (window == NULL) return TEST_ABORTED; if (window == NULL) return TEST_ABORTED;
/* Get state */ /* Get state */
originalState = SDL_GetWindowGrab(window); originalMouseState = SDL_GetWindowMouseGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowGrab()"); SDLTest_AssertPass("Call to SDL_GetWindowMouseGrab()");
originalKeyboardState = SDL_GetWindowKeyboardGrab(window);
SDLTest_AssertPass("Call to SDL_GetWindowKeyboardGrab()");
/* F */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* M: T --> F */
_setAndCheckWindowGrabState(window, SDL_FALSE); /* 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 */ /* Negative tests */
dummyState = SDL_GetWindowGrab(NULL); dummyState = SDL_GetWindowGrab(NULL);
SDLTest_AssertPass("Call to SDL_GetWindowGrab(window=NULL)"); SDLTest_AssertPass("Call to SDL_GetWindowGrab(window=NULL)");
_checkInvalidWindowError(); _checkInvalidWindowError();
dummyState = SDL_GetWindowKeyboardGrab(NULL);
SDLTest_AssertPass("Call to SDL_GetWindowKeyboardGrab(window=NULL)");
_checkInvalidWindowError();
SDL_SetWindowGrab(NULL, SDL_FALSE); SDL_SetWindowGrab(NULL, SDL_FALSE);
SDLTest_AssertPass("Call to SDL_SetWindowGrab(window=NULL,SDL_FALSE)"); SDLTest_AssertPass("Call to SDL_SetWindowGrab(window=NULL,SDL_FALSE)");
_checkInvalidWindowError(); _checkInvalidWindowError();
SDL_SetWindowGrab(NULL, SDL_TRUE); SDL_SetWindowKeyboardGrab(NULL, SDL_FALSE);
SDLTest_AssertPass("Call to SDL_SetWindowGrab(window=NULL,SDL_FALSE)"); SDLTest_AssertPass("Call to SDL_SetWindowKeyboardGrab(window=NULL,SDL_FALSE)");
_checkInvalidWindowError(); _checkInvalidWindowError();
/* State should still be F */ SDL_SetWindowGrab(NULL, SDL_TRUE);
desiredState = SDL_FALSE; SDLTest_AssertPass("Call to SDL_SetWindowGrab(window=NULL,SDL_TRUE)");
currentState = SDL_GetWindowGrab(window); _checkInvalidWindowError();
SDLTest_AssertPass("Call to SDL_GetWindowGrab()");
SDLTest_AssertCheck( SDL_SetWindowKeyboardGrab(NULL, SDL_TRUE);
currentState == desiredState, SDLTest_AssertPass("Call to SDL_SetWindowKeyboardGrab(window=NULL,SDL_TRUE)");
"Validate returned state; expected: %s, got: %s", _checkInvalidWindowError();
(desiredState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE",
(currentState == SDL_FALSE) ? "SDL_FALSE" : "SDL_TRUE");
/* Restore state */ /* Restore state */
_setAndCheckWindowGrabState(window, originalState); _setAndCheckWindowMouseGrabState(window, originalMouseState);
_setAndCheckWindowKeyboardGrabState(window, originalKeyboardState);
/* Clean up */ /* Clean up */
_destroyVideoSuiteTestWindow(window); _destroyVideoSuiteTestWindow(window);