diff options
author | Johannes Schickel | 2015-12-13 20:20:23 +0100 |
---|---|---|
committer | Johannes Schickel | 2015-12-13 21:30:25 +0100 |
commit | 5d48e211aa76a64c438457350a25f365cbdfdcd7 (patch) | |
tree | af0f04365ab50f6789b81b0b5e8499edd15d3242 | |
parent | 942d0fdad46d2105f1606ddea8cd9146acec70d8 (diff) | |
download | scummvm-rg350-5d48e211aa76a64c438457350a25f365cbdfdcd7.tar.gz scummvm-rg350-5d48e211aa76a64c438457350a25f365cbdfdcd7.tar.bz2 scummvm-rg350-5d48e211aa76a64c438457350a25f365cbdfdcd7.zip |
SDL: Fix mouse emulation with SDL2.
The mouse emulation via keyboard (or other means) was broken with
079037b73990b6107e59c7f1cd971c3a1cc221d1.
-rw-r--r-- | backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 74 | ||||
-rw-r--r-- | backends/graphics/surfacesdl/surfacesdl-graphics.h | 5 |
2 files changed, 43 insertions, 36 deletions
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 7d666bdbfa..b2da47110b 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -32,6 +32,7 @@ #include "common/textconsole.h" #include "common/translation.h" #include "common/util.h" +#include "common/frac.h" #ifdef USE_RGB_COLOR #include "common/list.h" #endif @@ -125,7 +126,7 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou _hwscreen(0), #if SDL_VERSION_ATLEAST(2, 0, 0) _renderer(nullptr), _screenTexture(nullptr), - _viewportX(0), _viewportY(0), _renderScaleX(1.0f), _renderScaleY(1.0f), _mouseScaleX(1.0f), _mouseScaleY(1.0f), + _viewport(), _windowWidth(1), _windowHeight(1), #else _originalBitsPerPixel(0), #endif @@ -890,9 +891,14 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { SDL_SetColorKey(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOSDColorKey); #endif +#if !SDL_VERSION_ATLEAST(2, 0, 0) + // For SDL2 the output resolution might differ from the requested + // resolution. We handle resetting the keyboard emulation properly inside + // our SDL_SetVideoMode wrapper for SDL2. _eventSource->resetKeyboadEmulation( _videoMode.screenWidth * _videoMode.scaleFactor - 1, effectiveScreenHeight() - 1); +#endif // Distinguish 555 and 565 mode if (_hwscreen->format->Rmask == 0x7C00) @@ -1774,8 +1780,10 @@ void SurfaceSdlGraphicsManager::warpMouse(int x, int y) { } #if SDL_VERSION_ATLEAST(2, 0, 0) - x1 = (int)((x1 + _viewportX) * _renderScaleX); - y1 = (int)((y1 + _viewportY) * _renderScaleY); + // Transform our coordinates in "virtual" output coordinate space into + // actual output coordinate space. + x1 = x1 * _windowWidth / _videoMode.hardwareWidth; + y1 = y1 * _windowHeight / _videoMode.hardwareHeight; #endif _window->warpMouseInWindow(x1, y1); @@ -2361,13 +2369,13 @@ void SurfaceSdlGraphicsManager::notifyVideoExpose() { void SurfaceSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { #if SDL_VERSION_ATLEAST(2, 0, 0) - // In fullscreen mode we can easily get coordinates outside the actual - // screen area. For example, if black bars are added left/right we can end - // up with negative x coordinates if the user moves the mouse inside the - // black bar. Here, we post process the received cooridnates to give the - // user the feeling the black bars do not exist. - point.x = (int)((point.x + _viewportX) * _mouseScaleX); - point.y = (int)((point.y + _viewportY) * _mouseScaleY); + // In SDL2 the actual output resolution might be different from what we + // requested. Thus, we transform the coordinates from actual output + // coordinate space into the "virtual" output coordinate space. + // Please note that we ignore the possible existence of black bars here, + // this avoids the feeling of stickyness to black bars. + point.x = point.x * _videoMode.hardwareWidth / _windowWidth; + point.y = point.y * _videoMode.hardwareHeight / _windowHeight; #endif if (!_overlayVisible) { @@ -2408,31 +2416,31 @@ SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, return nullptr; } - // We set the logical renderer size to the requested resolution in - // fullscreen. This assures that SDL2 adds black bars if needed to prevent - // stretching. - if (isFullscreen && SDL_RenderSetLogicalSize(_renderer, width, height) < 0) { - deinitializeRenderer(); - return nullptr; - } + SDL_GetWindowSize(_window->getSDLWindow(), &_windowWidth, &_windowHeight); + // We expect full screen resolution as inputs coming from the event system. + _eventSource->resetKeyboadEmulation(_windowWidth - 1, _windowHeight - 1); + + // Calculate the "viewport" for the actual area we draw in. In fullscreen + // we can easily get a different resolution than what we requested. In + // this case, we add black bars if necessary to assure the aspect ratio + // is preserved. + const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight; + const frac_t desiredAspect = intToFrac(width) / height; - // To provide smooth mouse handling in case black borders are added, we - // obtain the actual window size and the internal renderer scaling. - // Based on this we calculate scale factors to scale received mouse - // coordinates into actual screen area coordinates. - SDL_RenderGetScale(_renderer, &_renderScaleX, &_renderScaleY); - int windowWidth = 1, windowHeight = 1; - SDL_GetWindowSize(_window->getSDLWindow(), &windowWidth, &windowHeight); + _viewport.w = _windowWidth; + _viewport.h = _windowHeight; - _mouseScaleX = (width * _renderScaleX) / windowWidth; - _mouseScaleY = (height * _renderScaleY) / windowHeight; + // Adjust one dimension for mantaining the aspect ratio. + if (abs(outputAspect - desiredAspect) >= (int)(FRAC_ONE / 1000)) { + if (outputAspect < desiredAspect) { + _viewport.h = height * _windowWidth / width; + } else if (outputAspect > desiredAspect) { + _viewport.w = width * _windowHeight / height; + } + } - // Obtain viewport top left coordinates to transform received coordinates - // into visible area coordinates (i.e. including black borders). - SDL_Rect viewport; - SDL_RenderGetViewport(_renderer, &viewport); - _viewportX = viewport.x; - _viewportY = viewport.y; + _viewport.x = (_windowWidth - _viewport.w) / 2; + _viewport.y = (_windowHeight - _viewport.h) / 2; _screenTexture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height); if (!_screenTexture) { @@ -2453,7 +2461,7 @@ void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrect SDL_UpdateTexture(_screenTexture, nullptr, screen->pixels, screen->pitch); SDL_RenderClear(_renderer); - SDL_RenderCopy(_renderer, _screenTexture, NULL, NULL); + SDL_RenderCopy(_renderer, _screenTexture, NULL, &_viewport); SDL_RenderPresent(_renderer); } #endif // SDL_VERSION_ATLEAST(2, 0, 0) diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index 4d74ec575b..ac9844c849 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -171,9 +171,8 @@ protected: * around this API to keep the code paths as close as possible. */ SDL_Renderer *_renderer; SDL_Texture *_screenTexture; - int _viewportX, _viewportY; - float _renderScaleX, _renderScaleY; - float _mouseScaleX, _mouseScaleY; + SDL_Rect _viewport; + int _windowWidth, _windowHeight; void deinitializeRenderer(); SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags); |