Browse Source

Minor refactoring of mouse input handling

Ivan Savenko 2 years ago
parent
commit
34123c7f07

+ 9 - 34
client/eventsSDL/InputHandler.cpp

@@ -37,8 +37,6 @@ InputHandler::InputHandler()
 	, fingerHandler(std::make_unique<InputSourceTouch>())
 	, textHandler(std::make_unique<InputSourceText>())
 	, userHandler(std::make_unique<UserEventHandler>())
-	, mouseButtonsMask(0)
-	, pointerSpeedMultiplier(settings["general"]["relativePointerSpeedMultiplier"].Float())
 {
 }
 
@@ -77,14 +75,8 @@ void InputHandler::processEvents()
 {
 	boost::unique_lock<boost::mutex> lock(eventsMutex);
 	for (auto const & currentEvent : eventsQueue)
-	{
-		if (currentEvent.type == SDL_MOUSEMOTION)
-		{
-			cursorPosition = Point(currentEvent.motion.x, currentEvent.motion.y);
-			mouseButtonsMask = currentEvent.motion.state;
-		}
 		handleCurrentEvent(currentEvent);
-	}
+
 	eventsQueue.clear();
 }
 
@@ -211,25 +203,15 @@ bool InputHandler::isKeyboardShiftDown() const
 	return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
 }
 
-
-void InputHandler::fakeMoveCursor(float dx, float dy)
+void InputHandler::moveCursorPosition(const Point & distance)
 {
-	int x, y, w, h;
-
-	SDL_Event event;
-	SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0, 0, 0};
-
-	sme.state = SDL_GetMouseState(&x, &y);
-	SDL_GetWindowSize(mainWindow, &w, &h);
-
-	sme.x = GH.getCursorPosition().x + (int)(pointerSpeedMultiplier * w * dx);
-	sme.y = GH.getCursorPosition().y + (int)(pointerSpeedMultiplier * h * dy);
-
-	vstd::abetween(sme.x, 0, w);
-	vstd::abetween(sme.y, 0, h);
+	setCursorPosition(getCursorPosition() + distance);
+}
 
-	event.motion = sme;
-	SDL_PushEvent(&event);
+void InputHandler::setCursorPosition(const Point & position)
+{
+	cursorPosition = position;
+	GH.events().dispatchMouseMoved(position);
 }
 
 void InputHandler::startTextInput(const Rect & where)
@@ -244,14 +226,7 @@ void InputHandler::stopTextInput()
 
 bool InputHandler::isMouseButtonPressed(MouseButton button) const
 {
-	static_assert(static_cast<uint32_t>(MouseButton::LEFT)   == SDL_BUTTON_LEFT,   "mismatch between VCMI and SDL enum!");
-	static_assert(static_cast<uint32_t>(MouseButton::MIDDLE) == SDL_BUTTON_MIDDLE, "mismatch between VCMI and SDL enum!");
-	static_assert(static_cast<uint32_t>(MouseButton::RIGHT)  == SDL_BUTTON_RIGHT,  "mismatch between VCMI and SDL enum!");
-	static_assert(static_cast<uint32_t>(MouseButton::EXTRA1) == SDL_BUTTON_X1,     "mismatch between VCMI and SDL enum!");
-	static_assert(static_cast<uint32_t>(MouseButton::EXTRA2) == SDL_BUTTON_X2,     "mismatch between VCMI and SDL enum!");
-
-	uint32_t index = static_cast<uint32_t>(button);
-	return mouseButtonsMask & SDL_BUTTON(index);
+	return mouseHandler->isMouseButtonPressed(button) || fingerHandler->isMouseButtonPressed(button);
 }
 
 void InputHandler::pushUserEvent(EUserEvent usercode, void * userdata)

+ 5 - 3
client/eventsSDL/InputHandler.h

@@ -28,8 +28,6 @@ class InputHandler
 	boost::mutex eventsMutex;
 
 	Point cursorPosition;
-	float pointerSpeedMultiplier;
-	int mouseButtonsMask;
 
 	void preprocessEvent(const SDL_Event & event);
 	void handleCurrentEvent(const SDL_Event & current);
@@ -53,7 +51,11 @@ public:
 	/// returns true if input event has been found
 	bool ignoreEventsUntilInput();
 
-	void fakeMoveCursor(float dx, float dy);
+	/// Moves cursor by specified distance
+	void moveCursorPosition(const Point & distance);
+
+	/// Moves cursor to a specified position
+	void setCursorPosition(const Point & position);
 
 	/// Initiates text input in selected area, potentially creating IME popup (mobile systems only at the moment)
 	void startTextInput(const Rect & where);

+ 19 - 1
client/eventsSDL/InputSourceMouse.cpp

@@ -10,6 +10,7 @@
 
 #include "StdInc.h"
 #include "InputSourceMouse.h"
+#include "InputHandler.h"
 
 #include "../../lib/Point.h"
 #include "../gui/CGuiHandler.h"
@@ -20,7 +21,12 @@
 
 void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motion)
 {
-	GH.events().dispatchMouseMoved(Point(motion.x, motion.y));
+	Point newPosition(motion.x, motion.y);
+
+	GH.input().setCursorPosition(newPosition);
+
+	mouseButtonsMask = motion.state;
+
 }
 
 void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & button)
@@ -70,3 +76,15 @@ void InputSourceMouse::handleEventMouseButtonUp(const SDL_MouseButtonEvent & but
 			break;
 	}
 }
+
+bool InputSourceMouse::isMouseButtonPressed(MouseButton button) const
+{
+	static_assert(static_cast<uint32_t>(MouseButton::LEFT)   == SDL_BUTTON_LEFT,   "mismatch between VCMI and SDL enum!");
+	static_assert(static_cast<uint32_t>(MouseButton::MIDDLE) == SDL_BUTTON_MIDDLE, "mismatch between VCMI and SDL enum!");
+	static_assert(static_cast<uint32_t>(MouseButton::RIGHT)  == SDL_BUTTON_RIGHT,  "mismatch between VCMI and SDL enum!");
+	static_assert(static_cast<uint32_t>(MouseButton::EXTRA1) == SDL_BUTTON_X1,     "mismatch between VCMI and SDL enum!");
+	static_assert(static_cast<uint32_t>(MouseButton::EXTRA2) == SDL_BUTTON_X2,     "mismatch between VCMI and SDL enum!");
+
+	uint32_t index = static_cast<uint32_t>(button);
+	return mouseButtonsMask & SDL_BUTTON(index);
+}

+ 5 - 0
client/eventsSDL/InputSourceMouse.h

@@ -14,12 +14,17 @@ struct SDL_MouseWheelEvent;
 struct SDL_MouseMotionEvent;
 struct SDL_MouseButtonEvent;
 
+enum class MouseButton;
+
 /// Class that handles mouse input from SDL events
 class InputSourceMouse
 {
+	int mouseButtonsMask = 0;
 public:
 	void handleEventMouseMotion(const SDL_MouseMotionEvent & current);
 	void handleEventMouseButtonDown(const SDL_MouseButtonEvent & current);
 	void handleEventMouseWheel(const SDL_MouseWheelEvent & current);
 	void handleEventMouseButtonUp(const SDL_MouseButtonEvent & current);
+
+	bool isMouseButtonPressed(MouseButton button) const;
 };

+ 38 - 52
client/eventsSDL/InputSourceTouch.cpp

@@ -26,6 +26,7 @@
 InputSourceTouch::InputSourceTouch()
 	: multifinger(false)
 	, isPointerRelativeMode(settings["general"]["userRelativePointer"].Bool())
+	, pointerSpeedMultiplier(settings["general"]["relativePointerSpeedMultiplier"].Float())
 {
 	if(isPointerRelativeMode)
 	{
@@ -38,58 +39,73 @@ void InputSourceTouch::handleEventFingerMotion(const SDL_TouchFingerEvent & tfin
 {
 	if(isPointerRelativeMode)
 	{
-		GH.input().fakeMoveCursor(tfinger.dx, tfinger.dy);
+		Point screenSize = GH.screenDimensions();
+
+		Point moveDistance {
+			static_cast<int>(screenSize.x * pointerSpeedMultiplier * tfinger.dx),
+			static_cast<int>(screenSize.y * pointerSpeedMultiplier * tfinger.dy)
+		};
+
+		GH.input().moveCursorPosition(moveDistance);
 	}
 }
 
 void InputSourceTouch::handleEventFingerDown(const SDL_TouchFingerEvent & tfinger)
 {
-	auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
-
-	multifinger = fingerCount > 1;
-
 	if(isPointerRelativeMode)
 	{
 		if(tfinger.x > 0.5)
 		{
 			bool isRightClick = tfinger.y < 0.5;
 
-			fakeMouseButtonEventRelativeMode(true, isRightClick);
+			if (isRightClick)
+				GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, GH.getCursorPosition());
+			else
+				GH.events().dispatchMouseButtonPressed(MouseButton::LEFT, GH.getCursorPosition());
 		}
 	}
 #ifndef VCMI_IOS
-	else if(fingerCount == 2)
+	else
 	{
-		Point position = convertTouchToMouse(tfinger);
+		auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
+		multifinger = fingerCount > 1;
+
+		if(fingerCount == 2)
+		{
+			Point position = convertTouchToMouse(tfinger);
 
-		GH.events().dispatchMouseMoved(position);
-		GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
+			GH.input().setCursorPosition(position);
+			GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
+		}
 	}
 #endif //VCMI_IOS
 }
 
 void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
 {
-#ifndef VCMI_IOS
-	auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
-#endif //VCMI_IOS
-
 	if(isPointerRelativeMode)
 	{
 		if(tfinger.x > 0.5)
 		{
 			bool isRightClick = tfinger.y < 0.5;
 
-			fakeMouseButtonEventRelativeMode(false, isRightClick);
+			if (isRightClick)
+				GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, GH.getCursorPosition());
+			else
+				GH.events().dispatchMouseButtonReleased(MouseButton::LEFT, GH.getCursorPosition());
 		}
 	}
 #ifndef VCMI_IOS
-	else if(multifinger)
+	else
 	{
-		Point position = convertTouchToMouse(tfinger);
-		GH.events().dispatchMouseMoved(position);
-		GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
-		multifinger = fingerCount != 0;
+		if(multifinger)
+		{
+			auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
+			Point position = convertTouchToMouse(tfinger);
+			GH.input().setCursorPosition(position);
+			GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
+			multifinger = fingerCount != 0;
+		}
 	}
 #endif //VCMI_IOS
 }
@@ -99,37 +115,7 @@ Point InputSourceTouch::convertTouchToMouse(const SDL_TouchFingerEvent & tfinger
 	return Point(tfinger.x * GH.screenDimensions().x, tfinger.y * GH.screenDimensions().y);
 }
 
-void InputSourceTouch::fakeMouseButtonEventRelativeMode(bool down, bool right)
-{
-	SDL_Event event;
-	SDL_MouseButtonEvent sme = {SDL_MOUSEBUTTONDOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-	if(!down)
-	{
-		sme.type = SDL_MOUSEBUTTONUP;
-	}
-
-	sme.button = right ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT;
-
-	sme.x = GH.getCursorPosition().x;
-	sme.y = GH.getCursorPosition().y;
-
-	float xScale, yScale;
-	int w, h, rLogicalWidth, rLogicalHeight;
-
-	SDL_GetWindowSize(mainWindow, &w, &h);
-	SDL_RenderGetLogicalSize(mainRenderer, &rLogicalWidth, &rLogicalHeight);
-	SDL_RenderGetScale(mainRenderer, &xScale, &yScale);
-
-	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
-	moveCursorToPosition(Point((int)(sme.x * xScale) + (w - rLogicalWidth * xScale) / 2, (int)(sme.y * yScale + (h - rLogicalHeight * yScale) / 2)));
-	SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
-
-	event.button = sme;
-	SDL_PushEvent(&event);
-}
-
-void InputSourceTouch::moveCursorToPosition(const Point & position)
+bool InputSourceTouch::isMouseButtonPressed(MouseButton button) const
 {
-	SDL_WarpMouseInWindow(mainWindow, position.x, position.y);
+	return false;
 }

+ 4 - 2
client/eventsSDL/InputSourceTouch.h

@@ -14,16 +14,16 @@ VCMI_LIB_NAMESPACE_BEGIN
 class Point;
 VCMI_LIB_NAMESPACE_END
 
+enum class MouseButton;
 struct SDL_TouchFingerEvent;
 
 /// Class that handles touchscreen input from SDL events
 class InputSourceTouch
 {
+	double pointerSpeedMultiplier;
 	bool multifinger;
 	bool isPointerRelativeMode;
 
-	/// moves mouse pointer into specified position inside vcmi window
-	void moveCursorToPosition(const Point & position);
 	Point convertTouchToMouse(const SDL_TouchFingerEvent & current);
 
 	void fakeMouseButtonEventRelativeMode(bool down, bool right);
@@ -34,4 +34,6 @@ public:
 	void handleEventFingerMotion(const SDL_TouchFingerEvent & current);
 	void handleEventFingerDown(const SDL_TouchFingerEvent & current);
 	void handleEventFingerUp(const SDL_TouchFingerEvent & current);
+
+	bool isMouseButtonPressed(MouseButton button) const;
 };

+ 4 - 0
client/eventsSDL/UserEventHandler.cpp

@@ -18,6 +18,7 @@
 #include "../gui/WindowHandler.h"
 #include "../mainmenu/CMainMenu.h"
 #include "../mainmenu/CPrologEpilogVideo.h"
+#include "../gui/EventDispatcher.h"
 
 #include <SDL_events.h>
 
@@ -80,6 +81,9 @@ void UserEventHandler::handleUserEvent(const SDL_UserEvent & user)
 			GH.onScreenResize();
 			break;
 		}
+		case EUserEvent::FAKE_MOUSE_MOVE:
+			GH.events().dispatchMouseMoved(GH.getCursorPosition());
+			break;
 		default:
 			logGlobal->error("Unknown user event. Code %d", user.code);
 			break;

+ 1 - 1
client/gui/CGuiHandler.cpp

@@ -87,7 +87,7 @@ void CGuiHandler::handleEvents()
 
 void CGuiHandler::fakeMouseMove()
 {
-	input().fakeMoveCursor(0, 0);
+	pushUserEvent(EUserEvent::FAKE_MOUSE_MOVE);
 }
 
 void CGuiHandler::startTextInput(const Rect & whereInput)

+ 1 - 0
client/gui/CGuiHandler.h

@@ -36,6 +36,7 @@ enum class EUserEvent
 	FULLSCREEN_TOGGLED,
 	CAMPAIGN_START_SCENARIO,
 	FORCE_QUIT,
+	FAKE_MOUSE_MOVE,
 };
 
 // Handles GUI logic and drawing