mirror of
https://github.com/encounter/SDL.git
synced 2025-12-09 13:37:56 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user