Minor input grab clarifications.
authorRyan C. Gordon <icculus@icculus.org>
Sat, 28 Mar 2015 00:48:03 -0400
changeset 9447728a4bf8e02f
parent 9445 17095a4130ce
child 9448 3d3ed3a5ba8d
Minor input grab clarifications.

Clarify that grabbing the mouse only works with one window at a time; this was
always true at the system level, though SDL could previously get confused
by multiple simultaneous grabs, so now we explicitly break any existing
grab before starting a new one and document it as such.

Also track the window that is currently grabbed, and provide an API to query
for that window. This makes it easy to automate mouse ungrabbing at
breakpoints with gdb7's scripting, since the scripts can now know which window
to ungrab.

In 2.1, we should probably change this API to SDL_GrabInput(win) and
SDL_UngrabInput(void), or something.
include/SDL_video.h
src/dynapi/SDL_dynapi_overrides.h
src/dynapi/SDL_dynapi_procs.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
     1.1 --- a/include/SDL_video.h	Fri Mar 27 18:09:51 2015 -0400
     1.2 +++ b/include/SDL_video.h	Sat Mar 28 00:48:03 2015 -0400
     1.3 @@ -722,6 +722,9 @@
     1.4   *  \param window The window for which the input grab mode should be set.
     1.5   *  \param grabbed This is SDL_TRUE to grab input, and SDL_FALSE to release input.
     1.6   *
     1.7 + *  If the caller enables a grab while another window is currently grabbed,
     1.8 + *  the other window loses its grab in favor of the caller's window.
     1.9 + *
    1.10   *  \sa SDL_GetWindowGrab()
    1.11   */
    1.12  extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window,
    1.13 @@ -737,6 +740,15 @@
    1.14  extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window);
    1.15  
    1.16  /**
    1.17 + *  \brief Get the window that currently has an input grab enabled.
    1.18 + *
    1.19 + *  \return This returns the window if input is grabbed, and NULL otherwise.
    1.20 + *
    1.21 + *  \sa SDL_SetWindowGrab()
    1.22 + */
    1.23 +extern DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void);
    1.24 +
    1.25 +/**
    1.26   *  \brief Set the brightness (gamma correction) for a window.
    1.27   *
    1.28   *  \return 0 on success, or -1 if setting the brightness isn't supported.
     2.1 --- a/src/dynapi/SDL_dynapi_overrides.h	Fri Mar 27 18:09:51 2015 -0400
     2.2 +++ b/src/dynapi/SDL_dynapi_overrides.h	Sat Mar 28 00:48:03 2015 -0400
     2.3 @@ -591,3 +591,4 @@
     2.4  #define SDL_QueueAudio SDL_QueueAudio_REAL
     2.5  #define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL
     2.6  #define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL
     2.7 +#define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL
     3.1 --- a/src/dynapi/SDL_dynapi_procs.h	Fri Mar 27 18:09:51 2015 -0400
     3.2 +++ b/src/dynapi/SDL_dynapi_procs.h	Sat Mar 28 00:48:03 2015 -0400
     3.3 @@ -623,3 +623,4 @@
     3.4  SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c),(a,b,c),return)
     3.5  SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return)
     3.6  SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),)
     3.7 +SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return)
     4.1 --- a/src/video/SDL_sysvideo.h	Fri Mar 27 18:09:51 2015 -0400
     4.2 +++ b/src/video/SDL_sysvideo.h	Sat Mar 28 00:48:03 2015 -0400
     4.3 @@ -274,6 +274,7 @@
     4.4      int num_displays;
     4.5      SDL_VideoDisplay *displays;
     4.6      SDL_Window *windows;
     4.7 +    SDL_Window *grabbed_window;
     4.8      Uint8 window_magic;
     4.9      Uint32 next_object_id;
    4.10      char * clipboard_text;
     5.1 --- a/src/video/SDL_video.c	Fri Mar 27 18:09:51 2015 -0400
     5.2 +++ b/src/video/SDL_video.c	Sat Mar 28 00:48:03 2015 -0400
     5.3 @@ -2116,6 +2116,7 @@
     5.4  SDL_UpdateWindowGrab(SDL_Window * window)
     5.5  {
     5.6      if (_this->SetWindowGrab) {
     5.7 +        SDL_Window *grabbed_window;
     5.8          SDL_bool grabbed;
     5.9          if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
    5.10               (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
    5.11 @@ -2123,6 +2124,19 @@
    5.12          } else {
    5.13              grabbed = SDL_FALSE;
    5.14          }
    5.15 +
    5.16 +        grabbed_window = _this->grabbed_window;
    5.17 +        if (grabbed) {
    5.18 +            if (grabbed_window && (grabbed_window != window)) {
    5.19 +                /* stealing a grab from another window! */
    5.20 +                grabbed_window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
    5.21 +                _this->SetWindowGrab(_this, grabbed_window, SDL_FALSE);
    5.22 +            }
    5.23 +            _this->grabbed_window = window;
    5.24 +        } else if (grabbed_window == window) {
    5.25 +            _this->grabbed_window = NULL;  /* ungrabbing. */
    5.26 +        }
    5.27 +
    5.28          _this->SetWindowGrab(_this, window, grabbed);
    5.29      }
    5.30  }
    5.31 @@ -2147,8 +2161,15 @@
    5.32  SDL_GetWindowGrab(SDL_Window * window)
    5.33  {
    5.34      CHECK_WINDOW_MAGIC(window, SDL_FALSE);
    5.35 -
    5.36 -    return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
    5.37 +    SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
    5.38 +    return window == _this->grabbed_window;
    5.39 +}
    5.40 +
    5.41 +SDL_Window *
    5.42 +SDL_GetGrabbedWindow(void)
    5.43 +{
    5.44 +    SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
    5.45 +    return _this->grabbed_window;
    5.46  }
    5.47  
    5.48  void