diff --git a/include/SDL_video.h b/include/SDL_video.h index 782fcb0fb..fe1386889 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -722,6 +722,9 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window, * \param window The window for which the input grab mode should be set. * \param grabbed This is SDL_TRUE to grab input, and SDL_FALSE to release input. * + * 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_GetWindowGrab() */ extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window, @@ -736,6 +739,15 @@ extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window, */ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window); +/** + * \brief Get the window that currently has an input grab enabled. + * + * \return This returns the window if input is grabbed, and NULL otherwise. + * + * \sa SDL_SetWindowGrab() + */ +extern DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void); + /** * \brief Set the brightness (gamma correction) for a window. * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 8bcde6312..dcc6d4677 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -591,3 +591,4 @@ #define SDL_QueueAudio SDL_QueueAudio_REAL #define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL #define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL +#define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index c41cdc9f0..6408e3f89 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -623,3 +623,4 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX2,(void),(),return) SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return) SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),) +SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 6966f2bd3..9b2f7d170 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -274,6 +274,7 @@ struct SDL_VideoDevice int num_displays; SDL_VideoDisplay *displays; SDL_Window *windows; + SDL_Window *grabbed_window; Uint8 window_magic; Uint32 next_object_id; char * clipboard_text; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index b93c11e76..c8cb2fac8 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2116,6 +2116,7 @@ void SDL_UpdateWindowGrab(SDL_Window * window) { if (_this->SetWindowGrab) { + SDL_Window *grabbed_window; SDL_bool grabbed; if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) && (window->flags & SDL_WINDOW_INPUT_FOCUS)) { @@ -2123,6 +2124,19 @@ SDL_UpdateWindowGrab(SDL_Window * window) } else { grabbed = SDL_FALSE; } + + grabbed_window = _this->grabbed_window; + if (grabbed) { + if (grabbed_window && (grabbed_window != window)) { + /* stealing a grab from another window! */ + grabbed_window->flags &= ~SDL_WINDOW_INPUT_GRABBED; + _this->SetWindowGrab(_this, grabbed_window, SDL_FALSE); + } + _this->grabbed_window = window; + } else if (grabbed_window == window) { + _this->grabbed_window = NULL; /* ungrabbing. */ + } + _this->SetWindowGrab(_this, window, grabbed); } } @@ -2147,8 +2161,15 @@ 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)); + return window == _this->grabbed_window; +} - return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0); +SDL_Window * +SDL_GetGrabbedWindow(void) +{ + SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0)); + return _this->grabbed_window; } void