diff options
Diffstat (limited to 'backends/platform/sdl')
-rw-r--r-- | backends/platform/sdl/sdl-window.cpp | 63 | ||||
-rw-r--r-- | backends/platform/sdl/sdl-window.h | 13 |
2 files changed, 65 insertions, 11 deletions
diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp index 609186a061..543320f3be 100644 --- a/backends/platform/sdl/sdl-window.cpp +++ b/backends/platform/sdl/sdl-window.cpp @@ -28,9 +28,12 @@ #include "icons/scummvm.xpm" +static const uint32 fullscreenMask = SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN; + SdlWindow::SdlWindow() #if SDL_VERSION_ATLEAST(2, 0, 0) - : _window(nullptr), _inputGrabState(false), _windowCaption("ScummVM") + : _window(nullptr), _inputGrabState(false), _windowCaption("ScummVM"), + _lastFlags(0), _lastX(SDL_WINDOWPOS_UNDEFINED), _lastY(SDL_WINDOWPOS_UNDEFINED) #endif { } @@ -199,25 +202,67 @@ SDL_Surface *copySDLSurface(SDL_Surface *src) { return res; } -bool SdlWindow::createWindow(int width, int height, uint32 flags) { - destroyWindow(); - +bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) { if (_inputGrabState) { flags |= SDL_WINDOW_INPUT_GRABBED; } - _window = SDL_CreateWindow(_windowCaption.c_str(), SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, width, height, flags); + // SDL_WINDOW_RESIZABLE can also be updated without recreating the window + // starting with SDL 2.0.5, but it is not treated as updateable here + // because: + // 1. It is currently only changed in conjunction with the SDL_WINDOW_OPENGL + // flag, so the window will always be recreated anyway when changing + // resizability; and + // 2. Users (particularly on Windows) will sometimes swap older SDL DLLs + // to avoid bugs, which would be impossible if the feature was enabled + // at compile time using SDL_VERSION_ATLEAST. + const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_INPUT_GRABBED; + + const uint32 oldNonUpdateableFlags = _lastFlags & ~updateableFlagsMask; + const uint32 newNonUpdateableFlags = flags & ~updateableFlagsMask; + + if (!_window || oldNonUpdateableFlags != newNonUpdateableFlags) { + destroyWindow(); + _window = SDL_CreateWindow(_windowCaption.c_str(), _lastX, + _lastY, width, height, flags); + if (_window) { + setupIcon(); + } + } else { + const uint32 fullscreenFlags = flags & fullscreenMask; + + if (fullscreenFlags) { + SDL_DisplayMode fullscreenMode; + fullscreenMode.w = width; + fullscreenMode.h = height; + fullscreenMode.driverdata = nullptr; + fullscreenMode.format = 0; + fullscreenMode.refresh_rate = 0; + SDL_SetWindowDisplayMode(_window, &fullscreenMode); + } else { + SDL_SetWindowSize(_window, width, height); + } + + SDL_SetWindowFullscreen(_window, fullscreenFlags); + SDL_SetWindowGrab(_window, (flags & SDL_WINDOW_INPUT_GRABBED) ? SDL_TRUE : SDL_FALSE); + } + if (!_window) { return false; } - setupIcon(); + + _lastFlags = flags; return true; } void SdlWindow::destroyWindow() { - SDL_DestroyWindow(_window); - _window = nullptr; + if (_window) { + if (!(_lastFlags & fullscreenMask)) { + SDL_GetWindowPosition(_window, &_lastX, &_lastY); + } + SDL_DestroyWindow(_window); + _window = nullptr; + } } #endif diff --git a/backends/platform/sdl/sdl-window.h b/backends/platform/sdl/sdl-window.h index b62860960d..d75e811f56 100644 --- a/backends/platform/sdl/sdl-window.h +++ b/backends/platform/sdl/sdl-window.h @@ -81,14 +81,14 @@ public: SDL_Window *getSDLWindow() const { return _window; } /** - * Creates a new SDL window (and destroys the old one). + * Creates or updates the SDL window. * * @param width Width of the window. * @param height Height of the window. * @param flags SDL flags passed to SDL_CreateWindow * @return true on success, false otherwise */ - bool createWindow(int width, int height, uint32 flags); + bool createOrUpdateWindow(int width, int height, uint32 flags); /** * Destroys the current SDL window. @@ -99,6 +99,15 @@ protected: SDL_Window *_window; private: + uint32 _lastFlags; + + /** + * Switching between software and OpenGL modes requires the window to be + * destroyed and recreated. These properties store the position of the last + * window so the new window will be created in the same place. + */ + int _lastX, _lastY; + bool _inputGrabState; Common::String _windowCaption; #endif |