diff options
-rw-r--r-- | backends/events/sdl/sdl-events.cpp | 36 | ||||
-rw-r--r-- | backends/events/sdl/sdl-events.h | 2 | ||||
-rw-r--r-- | backends/graphics/sdl/sdl-graphics.cpp | 39 | ||||
-rw-r--r-- | backends/graphics/sdl/sdl-graphics.h | 4 | ||||
-rw-r--r-- | backends/graphics/windowed.h | 9 |
5 files changed, 63 insertions, 27 deletions
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index db4aa21ef1..6f34420674 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -169,13 +169,15 @@ int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) { } } -void SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) { +bool SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) { event.mouse.x = x; event.mouse.y = y; if (_graphicsManager) { - _graphicsManager->notifyMousePosition(event.mouse); + return _graphicsManager->notifyMousePosition(event.mouse); } + + return true; } bool SdlEventSource::handleKbdMouse(Common::Event &event) { @@ -307,8 +309,7 @@ bool SdlEventSource::handleKbdMouse(Common::Event &event) { if (_km.x != oldKmX || _km.y != oldKmY) { event.type = Common::EVENT_MOUSEMOVE; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); - return true; + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } } } @@ -548,7 +549,9 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) { // with a mouse wheel event. However, SDL2 does not supply // these, thus we use whatever we got last time. It seems // these are always stored in _km.x, _km.y. - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + if (!processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER)) { + return false; + } if (yDir < 0) { event.type = Common::EVENT_WHEELDOWN; return true; @@ -739,12 +742,12 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) { bool SdlEventSource::handleMouseMotion(SDL_Event &ev, Common::Event &event) { event.type = Common::EVENT_MOUSEMOVE; - processMouseEvent(event, ev.motion.x, ev.motion.y); + // update KbdMouse _km.x = ev.motion.x * MULTIPLIER; _km.y = ev.motion.y * MULTIPLIER; - return true; + return processMouseEvent(event, ev.motion.x, ev.motion.y); } bool SdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { @@ -765,12 +768,11 @@ bool SdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) else return false; - processMouseEvent(event, ev.button.x, ev.button.y); // update KbdMouse _km.x = ev.button.x * MULTIPLIER; _km.y = ev.button.y * MULTIPLIER; - return true; + return processMouseEvent(event, ev.button.x, ev.button.y); } bool SdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { @@ -784,21 +786,21 @@ bool SdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { #endif else return false; - processMouseEvent(event, ev.button.x, ev.button.y); + // update KbdMouse _km.x = ev.button.x * MULTIPLIER; _km.y = ev.button.y * MULTIPLIER; - return true; + return processMouseEvent(event, ev.button.x, ev.button.y); } bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONDOWN; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else if (ev.jbutton.button == JOY_BUT_RMOUSE) { event.type = Common::EVENT_RBUTTONDOWN; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else { event.type = Common::EVENT_KEYDOWN; switch (ev.jbutton.button) { @@ -819,17 +821,17 @@ bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0); break; } + return true; } - return true; } bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONUP; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else if (ev.jbutton.button == JOY_BUT_RMOUSE) { event.type = Common::EVENT_RBUTTONUP; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else { event.type = Common::EVENT_KEYUP; switch (ev.jbutton.button) { @@ -850,8 +852,8 @@ bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0); break; } + return true; } - return true; } bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h index cf445e9e2c..1d701f5ecf 100644 --- a/backends/events/sdl/sdl-events.h +++ b/backends/events/sdl/sdl-events.h @@ -117,7 +117,7 @@ protected: * Assigns the mouse coords to the mouse event. Furthermore notify the * graphics manager about the position change. */ - virtual void processMouseEvent(Common::Event &event, int x, int y); + virtual bool processMouseEvent(Common::Event &event, int x, int y); /** * Remaps key events. This allows platforms to configure diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index 6ce0bc7bac..e6699df1cd 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -169,22 +169,47 @@ bool SdlGraphicsManager::showMouse(const bool visible) { return WindowedGraphicsManager::showMouse(visible); } -void SdlGraphicsManager::notifyMousePosition(Common::Point &mouse) { +bool SdlGraphicsManager::notifyMousePosition(Common::Point &mouse) { int showCursor = SDL_DISABLE; - if (!_activeArea.drawRect.contains(mouse)) { + bool valid = true; + if (_activeArea.drawRect.contains(mouse)) { + _cursorLastInActiveArea = true; + } 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()) { + if (_window->mouseIsGrabbed() || + // Keep the mouse inside the game area during dragging to prevent an + // event mismatch where the mouseup event gets lost because it is + // performed outside of the game area + (_cursorLastInActiveArea && SDL_GetMouseState(nullptr, nullptr) != 0)) { setSystemMousePosition(mouse.x, mouse.y); - } else if (_cursorVisible) { - showCursor = SDL_ENABLE; + } else { + // Allow the in-game mouse to get a final movement event to the edge + // of the window if the mouse was moved out of the game area + if (_cursorLastInActiveArea) { + _cursorLastInActiveArea = false; + } else if (_cursorVisible) { + // Keep sending events to the game if the cursor is invisible, + // since otherwise if a game lets you skip a cutscene by + // clicking and the user moved the mouse outside the active + // area, the clicks wouldn't do anything, which would be + // confusing + valid = false; + } + + if (_cursorVisible) { + showCursor = SDL_ENABLE; + } } } SDL_ShowCursor(showCursor); - setMousePosition(mouse.x, mouse.y); - mouse = convertWindowToVirtual(mouse.x, mouse.y); + if (valid) { + setMousePosition(mouse.x, mouse.y); + mouse = convertWindowToVirtual(mouse.x, mouse.y); + } + return valid; } void SdlGraphicsManager::handleResizeImpl(const int width, const int height) { diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 772bc88637..993a1c3db6 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -84,8 +84,10 @@ public: * * @param mouse The mouse position in window coordinates, which must be * converted synchronously to virtual coordinates. + * @returns true if the mouse was in a valid position for the game and + * should cause the event to be sent to the game. */ - virtual void notifyMousePosition(Common::Point &mouse); + virtual bool notifyMousePosition(Common::Point &mouse); virtual bool showMouse(const bool visible) override; diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h index 52bb96c2cf..1d4958c9d6 100644 --- a/backends/graphics/windowed.h +++ b/backends/graphics/windowed.h @@ -39,7 +39,8 @@ public: _cursorVisible(false), _cursorX(0), _cursorY(0), - _cursorNeedsRedraw(false) {} + _cursorNeedsRedraw(false), + _cursorLastInActiveArea(true) {} virtual void showOverlay() override { if (_overlayVisible) @@ -304,6 +305,12 @@ protected: bool _cursorNeedsRedraw; /** + * Whether the last position of the system cursor was within the active area + * of the window. + */ + bool _cursorLastInActiveArea; + + /** * The position of the mouse cursor, in window coordinates. */ int _cursorX, _cursorY; |