* Implemented X11 fullscreen input grab
authorSam Lantinga <slouken@libsdl.org>
Wed, 17 Dec 2008 07:17:54 +0000
changeset 287591a7e08cd238
parent 2874 36e312e0fac0
child 2876 3fcb0d447bcd
* Implemented X11 fullscreen input grab
* Progress towards being able to toggle in and out of fullscreen mode
src/events/SDL_windowevents.c
src/video/SDL_video.c
src/video/win32/SDL_win32window.c
src/video/x11/SDL_x11window.c
     1.1 --- a/src/events/SDL_windowevents.c	Tue Dec 16 17:44:10 2008 +0000
     1.2 +++ b/src/events/SDL_windowevents.c	Wed Dec 17 07:17:54 2008 +0000
     1.3 @@ -58,6 +58,12 @@
     1.4          if (window->flags & SDL_WINDOW_FULLSCREEN) {
     1.5              return 0;
     1.6          }
     1.7 +        if (data1 == SDL_WINDOWPOS_UNDEFINED) {
     1.8 +            data1 = window->x;
     1.9 +        }
    1.10 +        if (data2 == SDL_WINDOWPOS_UNDEFINED) {
    1.11 +            data2 = window->y;
    1.12 +        }
    1.13          if (data1 == window->x && data2 == window->y) {
    1.14              return 0;
    1.15          }
     2.1 --- a/src/video/SDL_video.c	Tue Dec 16 17:44:10 2008 +0000
     2.2 +++ b/src/video/SDL_video.c	Wed Dec 17 07:17:54 2008 +0000
     2.3 @@ -123,8 +123,7 @@
     2.4  static SDL_VideoDevice *_this = NULL;
     2.5  
     2.6  /* Various local functions */
     2.7 -int SDL_VideoInit(const char *driver_name, Uint32 flags);
     2.8 -void SDL_VideoQuit(void);
     2.9 +static void SDL_UpdateWindowGrab(SDL_Window *window);
    2.10  
    2.11  static int
    2.12  cmpmodes(const void *A, const void *B)
    2.13 @@ -635,8 +634,7 @@
    2.14      for (i = 0; i < display->num_windows; ++i) {
    2.15          SDL_Window *window = &display->windows[i];
    2.16          if (FULLSCREEN_VISIBLE(window)) {
    2.17 -            SDL_SetWindowPosition(window->id, SDL_WINDOWPOS_CENTERED,
    2.18 -                                  SDL_WINDOWPOS_CENTERED);
    2.19 +            SDL_SetWindowPosition(window->id, window->x, window->y);
    2.20          }
    2.21      }
    2.22  
    2.23 @@ -752,7 +750,8 @@
    2.24      const Uint32 allowed_flags = (SDL_WINDOW_FULLSCREEN |
    2.25                                    SDL_WINDOW_OPENGL |
    2.26                                    SDL_WINDOW_BORDERLESS |
    2.27 -                                  SDL_WINDOW_RESIZABLE);
    2.28 +                                  SDL_WINDOW_RESIZABLE |
    2.29 +                                  SDL_WINDOW_INPUT_GRABBED);
    2.30      SDL_VideoDisplay *display;
    2.31      SDL_Window window;
    2.32      int num_windows;
    2.33 @@ -766,11 +765,6 @@
    2.34          SDL_SetError("No OpenGL support in video driver");
    2.35          return 0;
    2.36      }
    2.37 -    /* Fullscreen windows don't have any window decorations */
    2.38 -    if (flags & SDL_WINDOW_FULLSCREEN) {
    2.39 -        flags |= SDL_WINDOW_BORDERLESS;
    2.40 -        flags &= ~SDL_WINDOW_RESIZABLE;
    2.41 -    }
    2.42      SDL_zero(window);
    2.43      window.id = _this->next_object_id++;
    2.44      window.x = x;
    2.45 @@ -809,9 +803,8 @@
    2.46      if (flags & SDL_WINDOW_SHOWN) {
    2.47          SDL_ShowWindow(window.id);
    2.48      }
    2.49 -    if (flags & SDL_WINDOW_INPUT_GRABBED) {
    2.50 -        SDL_SetWindowGrab(window.id, 1);
    2.51 -    }
    2.52 +    SDL_UpdateWindowGrab(&window);
    2.53 +
    2.54      return window.id;
    2.55  }
    2.56  
    2.57 @@ -889,9 +882,8 @@
    2.58      if (flags & SDL_WINDOW_SHOWN) {
    2.59          SDL_ShowWindow(window->id);
    2.60      }
    2.61 -    if (flags & SDL_WINDOW_INPUT_GRABBED) {
    2.62 -        SDL_SetWindowGrab(window->id, 1);
    2.63 -    }
    2.64 +    SDL_UpdateWindowGrab(window);
    2.65 +
    2.66      return 0;
    2.67  }
    2.68  
    2.69 @@ -1004,19 +996,16 @@
    2.70      if (!window) {
    2.71          return;
    2.72      }
    2.73 -    if (x == SDL_WINDOWPOS_CENTERED) {
    2.74 -        window->x = (display->current_mode.w - window->w) / 2;
    2.75 -    } else if (x != SDL_WINDOWPOS_UNDEFINED) {
    2.76 +    if (x != SDL_WINDOWPOS_UNDEFINED) {
    2.77          window->x = x;
    2.78      }
    2.79 -    if (y == SDL_WINDOWPOS_CENTERED) {
    2.80 -        window->y = (display->current_mode.h - window->h) / 2;
    2.81 -    } else if (y != SDL_WINDOWPOS_UNDEFINED) {
    2.82 +    if (y != SDL_WINDOWPOS_UNDEFINED) {
    2.83          window->y = y;
    2.84      }
    2.85      if (_this->SetWindowPosition) {
    2.86          _this->SetWindowPosition(_this, window);
    2.87      }
    2.88 +    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MOVED, x, y);
    2.89  }
    2.90  
    2.91  void
    2.92 @@ -1082,11 +1071,11 @@
    2.93      if (!window || (window->flags & SDL_WINDOW_SHOWN)) {
    2.94          return;
    2.95      }
    2.96 -    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_SHOWN, 0, 0);
    2.97  
    2.98      if (_this->ShowWindow) {
    2.99          _this->ShowWindow(_this, window);
   2.100      }
   2.101 +    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_SHOWN, 0, 0);
   2.102  }
   2.103  
   2.104  void
   2.105 @@ -1097,11 +1086,11 @@
   2.106      if (!window || !(window->flags & SDL_WINDOW_SHOWN)) {
   2.107          return;
   2.108      }
   2.109 -    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   2.110  
   2.111      if (_this->HideWindow) {
   2.112          _this->HideWindow(_this, window);
   2.113      }
   2.114 +    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   2.115  }
   2.116  
   2.117  void
   2.118 @@ -1125,11 +1114,11 @@
   2.119      if (!window || (window->flags & SDL_WINDOW_MAXIMIZED)) {
   2.120          return;
   2.121      }
   2.122 -    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
   2.123  
   2.124      if (_this->MaximizeWindow) {
   2.125          _this->MaximizeWindow(_this, window);
   2.126      }
   2.127 +    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
   2.128  }
   2.129  
   2.130  void
   2.131 @@ -1140,11 +1129,11 @@
   2.132      if (!window || (window->flags & SDL_WINDOW_MINIMIZED)) {
   2.133          return;
   2.134      }
   2.135 -    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
   2.136  
   2.137      if (_this->MinimizeWindow) {
   2.138          _this->MinimizeWindow(_this, window);
   2.139      }
   2.140 +    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
   2.141  }
   2.142  
   2.143  void
   2.144 @@ -1156,11 +1145,11 @@
   2.145          || (window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
   2.146          return;
   2.147      }
   2.148 -    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESTORED, 0, 0);
   2.149  
   2.150      if (_this->RestoreWindow) {
   2.151          _this->RestoreWindow(_this, window);
   2.152      }
   2.153 +    SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESTORED, 0, 0);
   2.154  }
   2.155  
   2.156  int
   2.157 @@ -1217,7 +1206,12 @@
   2.158      } else {
   2.159          window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
   2.160      }
   2.161 +    SDL_UpdateWindowGrab(window);
   2.162 +}
   2.163  
   2.164 +static void
   2.165 +SDL_UpdateWindowGrab(SDL_Window *window)
   2.166 +{
   2.167      if ((window->flags & SDL_WINDOW_INPUT_FOCUS) && _this->SetWindowGrab) {
   2.168          _this->SetWindowGrab(_this, window);
   2.169      }
   2.170 @@ -1237,11 +1231,17 @@
   2.171  void
   2.172  SDL_OnWindowShown(SDL_Window * window)
   2.173  {
   2.174 +    if (window->flags & SDL_WINDOW_FULLSCREEN) {
   2.175 +        SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
   2.176 +    }
   2.177  }
   2.178  
   2.179  void
   2.180  SDL_OnWindowHidden(SDL_Window * window)
   2.181  {
   2.182 +    if (window->flags & SDL_WINDOW_FULLSCREEN) {
   2.183 +        SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
   2.184 +    }
   2.185  }
   2.186  
   2.187  void
   2.188 @@ -1265,7 +1265,7 @@
   2.189      if (display->gamma && _this->SetDisplayGammaRamp) {
   2.190          _this->SetDisplayGammaRamp(_this, display->gamma);
   2.191      }
   2.192 -    if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && _this->SetWindowGrab) {
   2.193 +    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED|SDL_WINDOW_FULLSCREEN)) && _this->SetWindowGrab) {
   2.194          _this->SetWindowGrab(_this, window);
   2.195      }
   2.196  }
   2.197 @@ -1282,7 +1282,7 @@
   2.198      if (display->gamma && _this->SetDisplayGammaRamp) {
   2.199          _this->SetDisplayGammaRamp(_this, display->saved_gamma);
   2.200      }
   2.201 -    if ((window->flags & SDL_WINDOW_INPUT_GRABBED) && _this->SetWindowGrab) {
   2.202 +    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED|SDL_WINDOW_FULLSCREEN)) && _this->SetWindowGrab) {
   2.203          _this->SetWindowGrab(_this, window);
   2.204      }
   2.205  }
     3.1 --- a/src/video/win32/SDL_win32window.c	Tue Dec 16 17:44:10 2008 +0000
     3.2 +++ b/src/video/win32/SDL_win32window.c	Wed Dec 17 07:17:54 2008 +0000
     3.3 @@ -159,12 +159,12 @@
     3.4      int x, y;
     3.5      int w, h;
     3.6  
     3.7 -    if (window->flags & SDL_WINDOW_BORDERLESS) {
     3.8 +    if (window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN)) {
     3.9          style |= WS_POPUP;
    3.10      } else {
    3.11          style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
    3.12      }
    3.13 -    if (window->flags & SDL_WINDOW_RESIZABLE) {
    3.14 +    if ((window->flags & SDL_WINDOW_RESIZABLE) && !(window->flags & SDL_WINDOW_FULLSCREEN)) {
    3.15          style |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
    3.16      }
    3.17  
    3.18 @@ -182,14 +182,14 @@
    3.19      w = (rect.right - rect.left);
    3.20      h = (rect.bottom - rect.top);
    3.21  
    3.22 -    if (window->x == SDL_WINDOWPOS_CENTERED) {
    3.23 +    if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) {
    3.24          x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
    3.25      } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
    3.26          x = CW_USEDEFAULT;
    3.27      } else {
    3.28          x = window->x + rect.left;
    3.29      }
    3.30 -    if (window->y == SDL_WINDOWPOS_CENTERED) {
    3.31 +    if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) {
    3.32          y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
    3.33      } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
    3.34          y = CW_USEDEFAULT;
    3.35 @@ -331,8 +331,17 @@
    3.36      AdjustWindowRectEx(&rect, style,
    3.37                         (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) !=
    3.38                                                             NULL), 0);
    3.39 -    x = window->x + rect.left;
    3.40 -    y = window->y + rect.top;
    3.41 +
    3.42 +    if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) {
    3.43 +        x = (GetSystemMetrics(SM_CXSCREEN) - window->w) / 2;
    3.44 +    } else {
    3.45 +        x = window->x + rect.left;
    3.46 +    }
    3.47 +    if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) {
    3.48 +        y = (GetSystemMetrics(SM_CYSCREEN) - window->h) / 2;
    3.49 +    } else {
    3.50 +        y = window->y + rect.top;
    3.51 +    }
    3.52  
    3.53      SetWindowPos(hwnd, top, x, y, 0, 0, (SWP_NOCOPYBITS | SWP_NOSIZE));
    3.54  }
    3.55 @@ -425,7 +434,7 @@
    3.56  {
    3.57      HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
    3.58  
    3.59 -    if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
    3.60 +    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED|SDL_WINDOW_FULLSCREEN)) &&
    3.61          (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
    3.62          RECT rect;
    3.63          GetClientRect(hwnd, &rect);
     4.1 --- a/src/video/x11/SDL_x11window.c	Tue Dec 16 17:44:10 2008 +0000
     4.2 +++ b/src/video/x11/SDL_x11window.c	Wed Dec 17 07:17:54 2008 +0000
     4.3 @@ -287,7 +287,7 @@
     4.4                              visual, AllocNone);
     4.5      }
     4.6  
     4.7 -    if (window->x == SDL_WINDOWPOS_CENTERED) {
     4.8 +    if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) {
     4.9          x = (DisplayWidth(data->display, displaydata->screen) -
    4.10               window->w) / 2;
    4.11      } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
    4.12 @@ -295,7 +295,7 @@
    4.13      } else {
    4.14          x = window->x;
    4.15      }
    4.16 -    if (window->y == SDL_WINDOWPOS_CENTERED) {
    4.17 +    if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) {
    4.18          y = (DisplayHeight(data->display, displaydata->screen) -
    4.19               window->h) / 2;
    4.20      } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
    4.21 @@ -321,7 +321,7 @@
    4.22  
    4.23      sizehints = XAllocSizeHints();
    4.24      if (sizehints) {
    4.25 -        if (window->flags & SDL_WINDOW_RESIZABLE) {
    4.26 +        if ((window->flags & SDL_WINDOW_RESIZABLE) && !(window->flags & SDL_WINDOW_FULLSCREEN)) {
    4.27              sizehints->min_width = 32;
    4.28              sizehints->min_height = 32;
    4.29              sizehints->max_height = 4096;
    4.30 @@ -342,7 +342,7 @@
    4.31          XFree(sizehints);
    4.32      }
    4.33  
    4.34 -    if (window->flags & SDL_WINDOW_BORDERLESS) {
    4.35 +    if (window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN)) {
    4.36          SDL_bool set;
    4.37          Atom WM_HINTS;
    4.38  
    4.39 @@ -601,8 +601,19 @@
    4.40      SDL_DisplayData *displaydata =
    4.41          (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
    4.42      Display *display = data->videodata->display;
    4.43 +    int x, y;
    4.44  
    4.45 -    XMoveWindow(display, data->window, window->x, window->y);
    4.46 +    if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->x == SDL_WINDOWPOS_CENTERED) {
    4.47 +        x = (DisplayWidth(display, displaydata->screen) - window->w) / 2;
    4.48 +    } else {
    4.49 +        x = window->x;
    4.50 +    }
    4.51 +    if ((window->flags & SDL_WINDOW_FULLSCREEN) || window->y == SDL_WINDOWPOS_CENTERED) {
    4.52 +        y = (DisplayHeight(display, displaydata->screen) - window->h) / 2;
    4.53 +    } else {
    4.54 +        y = window->y;
    4.55 +    }
    4.56 +    XMoveWindow(display, data->window, x, y);
    4.57  }
    4.58  
    4.59  void
    4.60 @@ -662,7 +673,29 @@
    4.61  void
    4.62  X11_SetWindowGrab(_THIS, SDL_Window * window)
    4.63  {
    4.64 -    /* FIXME */
    4.65 +    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    4.66 +    Display *display = data->videodata->display;
    4.67 +
    4.68 +    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED|SDL_WINDOW_FULLSCREEN)) &&
    4.69 +        (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
    4.70 +        /* Try to grab the mouse */
    4.71 +        for ( ; ; ) {
    4.72 +            int result = XGrabPointer(display, data->window, True, 0, GrabModeAsync, GrabModeAsync, data->window, None, CurrentTime);
    4.73 +            if ( result == GrabSuccess ) {
    4.74 +                break;
    4.75 +            }
    4.76 +            SDL_Delay(100);
    4.77 +        }
    4.78 +
    4.79 +        /* Raise the window if we grab the mouse */
    4.80 +        XRaiseWindow(display, data->window);
    4.81 +
    4.82 +        /* Now grab the keyboard */
    4.83 +        XGrabKeyboard(display, data->window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
    4.84 +    } else {
    4.85 +        XUngrabPointer(display, CurrentTime);
    4.86 +        XUngrabKeyboard(display, CurrentTime);
    4.87 +    }
    4.88  }
    4.89  
    4.90  void