Skip to content

Commit

Permalink
SDL: Fix mouse emulation with SDL2.
Browse files Browse the repository at this point in the history
The mouse emulation via keyboard (or other means) was broken with
079037b.
  • Loading branch information
Johannes Schickel committed Dec 13, 2015
1 parent 942d0fd commit 5d48e21
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 36 deletions.
74 changes: 41 additions & 33 deletions backends/graphics/surfacesdl/surfacesdl-graphics.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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)
Expand Down
5 changes: 2 additions & 3 deletions backends/graphics/surfacesdl/surfacesdl-graphics.h
Expand Up @@ -171,9 +171,8 @@ class SurfaceSdlGraphicsManager : public SdlGraphicsManager, public Common::Even
* 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);
Expand Down

0 comments on commit 5d48e21

Please sign in to comment.