diff options
author | Colin Snover | 2017-07-19 19:15:12 -0500 |
---|---|---|
committer | Colin Snover | 2017-10-15 13:24:20 -0500 |
commit | de2bbe3b9738ef95b2529db989570770ef434f9d (patch) | |
tree | b1a2994225ca92ec454bd4108673f27a6222145b /backends/graphics/sdl | |
parent | 0ad03e492ac030193536e3167e8bf428e88cafb3 (diff) | |
download | scummvm-rg350-de2bbe3b9738ef95b2529db989570770ef434f9d.tar.gz scummvm-rg350-de2bbe3b9738ef95b2529db989570770ef434f9d.tar.bz2 scummvm-rg350-de2bbe3b9738ef95b2529db989570770ef434f9d.zip |
BACKENDS: Refactor OpenGL & SDL graphics backends
This patch refactors the OpenGL and SDL graphics backends,
primarily to unify window scaling and mouse handling, and to
fix coordinate mapping between the ScummVM window and the
virtual game screen when they have different aspect ratios.
Unified code for these two backends has been moved to a new
header-only WindowedGraphicsManager class, so named because it
contains code for managing graphics managers that interact with
a windowing system and render virtual screens within a larger
physical content window.
The biggest behavioral change here is with the coordinate
system mapping:
Previously, mouse offsets were converted by mapping the whole
space within the window as input to the virtual game screen
without maintaining aspect ratio. This was done to prevent
'stickiness' when the mouse cursor was within the window but
outside of the virtual game screen, but it caused noticeable
distortion of mouse movement speed on the axis with blank
space.
Instead of introducing mouse speed distortion to prevent
stickiness, this patch changes coordinate transformation to
show the system cursor when the mouse moves outside of the virtual
game screen when mouse grab is off, or by holding the mouse inside
the virtual game screen (instead of the entire window) when mouse
grab is on.
This patch also improves some other properties of the
GraphicsManager/PaletteManager interfaces:
* Nullipotent operations (getWidth, getHeight, etc.) of the
PaletteManager/GraphicsManager interfaces are now const
* Methods marked `virtual` but not inherited by any subclass have
been de-virtualized
* Extra unnecessary calculations of hardware height in
SurfaceSdlGraphicsManager have been removed
* Methods have been renamed where appropriate for clarity
(setWindowSize -> handleResize, etc.)
* C++11 support improved with `override` specifier added on
overridden virtual methods in subclasses (primarily to avoid
myself accidentally creating new methods in the subclasses
by changing types/names during refactoring)
Additional refactoring can and should be done at some point to
continue to deduplicate code between the OpenGL and SDL backends.
Since the primary goal here was to improve the coordinate mapping,
full refactoring of these backends was not completed here.
Diffstat (limited to 'backends/graphics/sdl')
-rw-r--r-- | backends/graphics/sdl/sdl-graphics.cpp | 36 | ||||
-rw-r--r-- | backends/graphics/sdl/sdl-graphics.h | 66 |
2 files changed, 74 insertions, 28 deletions
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index a181582235..ea947c1073 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -28,15 +28,11 @@ #include "graphics/scaler/aspect.h" SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window) - : _eventSource(source), _window(window) + : _eventSource(source), _window(window), _hwScreen(nullptr) #if SDL_VERSION_ATLEAST(2, 0, 0) , _allowWindowSizeReset(false), _hintedWidth(0), _hintedHeight(0), _lastFlags(0) #endif - { -} - -SdlGraphicsManager::~SdlGraphicsManager() { -} +{} void SdlGraphicsManager::activateManager() { _eventSource->setGraphicsManager(this); @@ -46,7 +42,7 @@ void SdlGraphicsManager::deactivateManager() { _eventSource->setGraphicsManager(0); } -SdlGraphicsManager::State SdlGraphicsManager::getState() { +SdlGraphicsManager::State SdlGraphicsManager::getState() const { State state; state.screenWidth = getWidth(); @@ -152,6 +148,32 @@ void SdlGraphicsManager::initSizeHint(const Graphics::ModeList &modes) { #endif } +void SdlGraphicsManager::notifyMousePosition(Common::Point &mouse) { + int showCursor; + if (_activeArea.drawRect.contains(mouse)) { + showCursor = SDL_DISABLE; + } else { + mouse.x = CLIP<int>(mouse.x, _activeArea.drawRect.left, _activeArea.drawRect.right - 1); + mouse.y = CLIP<int>(mouse.y, _activeArea.drawRect.top, _activeArea.drawRect.bottom - 1); + + if (_window->mouseIsGrabbed()) { + setSystemMousePosition(mouse.x, mouse.y); + showCursor = SDL_DISABLE; + } else { + showCursor = SDL_ENABLE; + } + } + + SDL_ShowCursor(showCursor); + setMousePosition(mouse.x, mouse.y); + mouse = convertWindowToVirtual(mouse.x, mouse.y); +} + +void SdlGraphicsManager::handleResizeImpl(const int width, const int height) { + _eventSource->resetKeyboardEmulation(width - 1, height - 1); + _forceRedraw = true; +} + #if SDL_VERSION_ATLEAST(2, 0, 0) bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint32 flags) { if (!_window) { diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index ce282d842d..886070aedb 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -23,7 +23,7 @@ #ifndef BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H #define BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H -#include "backends/graphics/graphics.h" +#include "backends/graphics/windowed.h" #include "backends/platform/sdl/sdl-window.h" #include "common/rect.h" @@ -32,13 +32,11 @@ class SdlEventSource; /** * Base class for a SDL based graphics manager. - * - * It features a few extra a few extra features required by SdlEventSource. */ -class SdlGraphicsManager : virtual public GraphicsManager { +class SdlGraphicsManager : virtual public WindowedGraphicsManager { public: SdlGraphicsManager(SdlEventSource *source, SdlWindow *window); - virtual ~SdlGraphicsManager(); + virtual ~SdlGraphicsManager() {} /** * Makes this graphics manager active. That means it should be ready to @@ -74,23 +72,20 @@ public: * @param width Requested window width. * @param height Requested window height. */ - virtual void notifyResize(const uint width, const uint height) {} + virtual void notifyResize(const int width, const int height) {} /** - * Transforms real screen coordinates into the current active screen - * coordinates (may be either game screen or overlay). + * Notifies the graphics manager about a mouse position change. * - * @param point Mouse coordinates to transform. - */ - virtual void transformMouseCoordinates(Common::Point &point) = 0; - - /** - * Notifies the graphics manager about a position change according to the - * real screen coordinates. + * The passed point *must* be converted from window coordinates to virtual + * coordinates in order for the event to be processed correctly by the game + * engine. Just use `convertWindowToVirtual` for this unless you need to do + * something special. * - * @param mouse Mouse position. + * @param mouse The mouse position in window coordinates, which must be + * converted synchronously to virtual coordinates. */ - virtual void notifyMousePos(Common::Point mouse) = 0; + virtual void notifyMousePosition(Common::Point &mouse); /** * A (subset) of the graphic manager's state. This is used when switching @@ -108,17 +103,17 @@ public: }; /** - * Queries the current state of the graphic manager. + * Gets the current state of the graphics manager. */ - State getState(); + State getState() const; /** - * Setup a basic state of the graphic manager. + * Sets up a basic state of the graphics manager. */ bool setState(const State &state); /** - * Queries the SDL window. + * @returns the SDL window. */ SdlWindow *getWindow() const { return _window; } @@ -130,6 +125,34 @@ protected: bool defaultGraphicsModeConfig() const; int getGraphicsModeIdByName(const Common::String &name) const; + /** + * Gets the dimensions of the window directly from SDL instead of from the + * values stored by the graphics manager. + */ + void getWindowSizeFromSdl(int *width, int *height) const { +#if SDL_VERSION_ATLEAST(2, 0, 0) + assert(_window); + SDL_GetWindowSize(_window->getSDLWindow(), width, height); +#else + assert(_hwScreen); + + if (width) { + *width = _hwScreen->w; + } + + if (height) { + *height = _hwScreen->h; + } +#endif + } + + virtual void setSystemMousePosition(const int x, const int y) override { + assert(_window); + _window->warpMouseInWindow(x, y); + } + + virtual void handleResizeImpl(const int width, const int height) override; + #if SDL_VERSION_ATLEAST(2, 0, 0) public: void unlockWindowSize() { @@ -146,6 +169,7 @@ protected: bool createOrUpdateWindow(const int width, const int height, const Uint32 flags); #endif + SDL_Surface *_hwScreen; SdlEventSource *_eventSource; SdlWindow *_window; }; |