浏览代码

SDL event handling is now done exclusively in input handler

Ivan Savenko 2 年之前
父节点
当前提交
0e70f2998f

+ 1 - 11
client/CMT.cpp

@@ -45,8 +45,6 @@
 #undef main
 #endif
 
-extern boost::mutex eventsM;
-
 namespace po = boost::program_options;
 namespace po_style = boost::program_options::command_line_style;
 namespace bfs = boost::filesystem;
@@ -528,15 +526,7 @@ void handleQuit(bool ask)
 	if(CSH->client && LOCPLINT && ask)
 	{
 		CCS->curh->set(Cursor::Map::POINTER);
-		LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], [](){
-			// Workaround for assertion failure on exit:
-			// handleQuit() is alway called during SDL event processing
-			// during which, eventsM is kept locked
-			// this leads to assertion failure if boost::mutex is in locked state
-			eventsM.unlock();
-
-			quitApplication();
-		}, nullptr);
+		LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], quitApplication, nullptr);
 	}
 	else
 	{

+ 5 - 29
client/CPlayerInterface.cpp

@@ -22,6 +22,7 @@
 #include "battle/BattleWindow.h"
 #include "../CCallback.h"
 #include "windows/CCastleInterface.h"
+#include "eventsSDL/InputHandler.h"
 #include "gui/CursorHandler.h"
 #include "windows/CKingdomInterface.h"
 #include "CGameInfo.h"
@@ -77,8 +78,6 @@
 #include "eventsSDL/NotificationHandler.h"
 #include "adventureMap/CInGameConsole.h"
 
-#include <SDL_events.h>
-
 // The macro below is used to mark functions that are called by client when game state changes.
 // They all assume that CPlayerInterface::pim mutex is locked.
 #define EVENT_HANDLER_CALLED_BY_CLIENT
@@ -96,8 +95,6 @@
 		return;						\
 	RETURN_IF_QUICK_COMBAT
 
-extern std::queue<SDL_Event> SDLEventsQueue;
-extern boost::mutex eventsM;
 boost::recursive_mutex * CPlayerInterface::pim = new boost::recursive_mutex;
 
 CPlayerInterface * LOCPLINT;
@@ -206,7 +203,7 @@ void CPlayerInterface::performAutosave()
 	}
 	else if(frequency > 0 && cb->getDate() % frequency == 0)
 	{
-		LOCPLINT->cb->save("Saves/" + prefix + "Autosave_" + std::to_string(autosaveCount++ + 1));
+		cb->save("Saves/" + prefix + "Autosave_" + std::to_string(autosaveCount++ + 1));
 		autosaveCount %= 5;
 	}
 }
@@ -215,8 +212,6 @@ void CPlayerInterface::yourTurn()
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	{
-		boost::unique_lock<boost::mutex> lock(eventsM); //block handling events until interface is ready
-
 		LOCPLINT = this;
 		GH.curInt = this;
 
@@ -372,22 +367,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
 
 	//check if user cancelled movement
 	{
-		boost::unique_lock<boost::mutex> un(eventsM);
-		while(!SDLEventsQueue.empty())
-		{
-			SDL_Event ev = SDLEventsQueue.front();
-			SDLEventsQueue.pop();
-			switch(ev.type)
-			{
-			case SDL_MOUSEBUTTONDOWN:
-				stillMoveHero.setn(STOP_MOVE);
-				break;
-			case SDL_KEYDOWN:
-				if (ev.key.keysym.sym < SDLK_F1  ||  ev.key.keysym.sym > SDLK_F15)
-					stillMoveHero.setn(STOP_MOVE);
-				break;
-			}
-		}
+		if (GH.input().ignoreEventsUntilInput())
+			stillMoveHero.setn(STOP_MOVE);
 	}
 
 	if (stillMoveHero.get() == WAITING_MOVE)
@@ -1478,7 +1459,6 @@ void CPlayerInterface::playerBlocked(int reason, bool start)
 		if(CSH->howManyPlayerInterfaces() > 1 && LOCPLINT != this && LOCPLINT->makingTurn == false)
 		{
 			//one of our players who isn't last in order got attacked not by our another player (happens for example in hotseat mode)
-			boost::unique_lock<boost::mutex> lock(eventsM); //TODO: copied from yourTurn, no idea if it's needed
 			LOCPLINT = this;
 			GH.curInt = this;
 			adventureInt->onCurrentPlayerChanged(playerID);
@@ -1875,11 +1855,7 @@ bool CPlayerInterface::capturedAllEvents()
 
 	if (ignoreEvents || needToLockAdventureMap || isAutoFightOn)
 	{
-		boost::unique_lock<boost::mutex> un(eventsM);
-		while(!SDLEventsQueue.empty())
-		{
-			SDLEventsQueue.pop();
-		}
+		GH.input().ignoreEventsUntilInput();
 		return true;
 	}
 

+ 4 - 16
client/CVideoHandler.cpp

@@ -12,15 +12,13 @@
 
 #include "CMT.h"
 #include "gui/CGuiHandler.h"
+#include "eventsSDL/InputHandler.h"
 #include "gui/FramerateManager.h"
 #include "renderSDL/SDL_Extensions.h"
 #include "CPlayerInterface.h"
 #include "../lib/filesystem/Filesystem.h"
 
 #include <SDL_render.h>
-#include <SDL_events.h>
-
-extern CGuiHandler GH; //global gui handler
 
 #ifndef DISABLE_VIDEO
 
@@ -31,18 +29,6 @@ extern "C" {
 #include <libswscale/swscale.h>
 }
 
-//reads events and returns true on key down
-static bool keyDown()
-{
-	SDL_Event ev;
-	while(SDL_PollEvent(&ev))
-	{
-		if(ev.type == SDL_KEYDOWN || ev.type == SDL_MOUSEBUTTONDOWN)
-			return true;
-	}
-	return false;
-}
-
 #ifdef _MSC_VER
 #pragma comment(lib, "avcodec.lib")
 #pragma comment(lib, "avutil.lib")
@@ -455,7 +441,9 @@ bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey)
 
 	while(nextFrame())
 	{
-		if(stopOnKey && keyDown())
+		GH.input().fetchEvents();
+
+		if(stopOnKey && GH.input().ignoreEventsUntilInput())
 			return false;
 
 		SDL_Rect rect = CSDL_Ext::toSDL(pos);

+ 1 - 0
client/adventureMap/CMinimap.cpp

@@ -17,6 +17,7 @@
 #include "../CGameInfo.h"
 #include "../CPlayerInterface.h"
 #include "../gui/CGuiHandler.h"
+#include "../gui/MouseButton.h"
 #include "../gui/WindowHandler.h"
 #include "../render/Colors.h"
 #include "../renderSDL/SDL_Extensions.h"

+ 1 - 0
client/battle/BattleInterfaceClasses.cpp

@@ -25,6 +25,7 @@
 #include "../gui/CursorHandler.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/Shortcut.h"
+#include "../gui/MouseButton.h"
 #include "../gui/WindowHandler.h"
 #include "../render/Canvas.h"
 #include "../render/IImage.h"

+ 24 - 3
client/eventsSDL/InputHandler.cpp

@@ -21,6 +21,7 @@
 #include "../gui/CGuiHandler.h"
 #include "../gui/CursorHandler.h"
 #include "../gui/EventDispatcher.h"
+#include "../gui/MouseButton.h"
 #include "../CMT.h"
 #include "../CPlayerInterface.h"
 #include "../CGameInfo.h"
@@ -29,8 +30,6 @@
 
 #include <SDL_events.h>
 
-std::queue<SDL_Event> SDLEventsQueue;
-boost::mutex eventsM;
 
 InputHandler::InputHandler()
 	: mouseHandler(std::make_unique<InputSourceMouse>())
@@ -100,6 +99,27 @@ void InputHandler::processEvents()
 	}
 }
 
+bool InputHandler::ignoreEventsUntilInput()
+{
+	bool inputFound = false;
+
+	boost::unique_lock<boost::mutex> lock(eventsM);
+	while(!SDLEventsQueue.empty())
+	{
+		SDL_Event ev = SDLEventsQueue.front();
+		SDLEventsQueue.pop();
+		switch(ev.type)
+		{
+			case SDL_MOUSEBUTTONDOWN:
+			case SDL_FINGERDOWN:
+			case SDL_KEYDOWN:
+				inputFound = true;
+		}
+	}
+
+	return inputFound;
+}
+
 void InputHandler::preprocessEvent(const SDL_Event & ev)
 {
 	if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
@@ -154,7 +174,8 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
 	//preprocessing
 	if(ev.type == SDL_MOUSEMOTION)
 	{
-		CCS->curh->cursorMove(ev.motion.x, ev.motion.y);
+		if (CCS && CCS->curh)
+			CCS->curh->cursorMove(ev.motion.x, ev.motion.y);
 	}
 
 	{

+ 7 - 0
client/eventsSDL/InputHandler.h

@@ -24,6 +24,9 @@ class UserEventHandler;
 
 class InputHandler
 {
+	std::queue<SDL_Event> SDLEventsQueue;
+	boost::mutex eventsM;
+
 	Point cursorPosition;
 	float pointerSpeedMultiplier;
 	int mouseButtonsMask;
@@ -44,6 +47,10 @@ public:
 	void fetchEvents();
 	void processEvents();
 
+	/// drops all incoming events without processing them
+	/// returns true if input event has been found
+	bool ignoreEventsUntilInput();
+
 	void fakeMoveCursor(float dx, float dy);
 	void startTextInput(const Rect & where);
 	void stopTextInput();

+ 1 - 0
client/eventsSDL/InputSourceTouch.cpp

@@ -17,6 +17,7 @@
 #include "../CMT.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/EventDispatcher.h"
+#include "../gui/MouseButton.h"
 
 #include <SDL_events.h>
 #include <SDL_render.h>

+ 0 - 8
client/gui/CGuiHandler.cpp

@@ -34,9 +34,6 @@
 
 CGuiHandler GH;
 
-extern std::queue<SDL_Event> SDLEventsQueue;
-extern boost::mutex eventsM;
-
 boost::thread_specific_ptr<bool> inGuiThread;
 
 SObjectConstruction::SObjectConstruction(CIntObject *obj)
@@ -198,11 +195,6 @@ Point CGuiHandler::screenDimensions() const
 	return Point(screen->w, screen->h);
 }
 
-bool CGuiHandler::isMouseButtonPressed() const
-{
-	return isMouseButtonPressed(MouseButton::LEFT) || isMouseButtonPressed(MouseButton::MIDDLE) || isMouseButtonPressed(MouseButton::RIGHT);
-}
-
 bool CGuiHandler::isMouseButtonPressed(MouseButton button) const
 {
 	return inputHandlerInstance->isMouseButtonPressed(button);

+ 2 - 11
client/gui/CGuiHandler.h

@@ -9,19 +9,13 @@
  */
 #pragma once
 
-#include "MouseButton.h"
-#include "../../lib/Point.h"
-
 VCMI_LIB_NAMESPACE_BEGIN
-
 template <typename T> struct CondSh;
+class Point;
 class Rect;
-
 VCMI_LIB_NAMESPACE_END
 
-union SDL_Event;
-struct SDL_MouseMotionEvent;
-
+enum class MouseButton;
 class ShortcutHandler;
 class FramerateManager;
 class IStatusBar;
@@ -75,9 +69,6 @@ public:
 	/// May not match size of window if user has UI scaling different from 100%
 	Point screenDimensions() const;
 
-	/// returns true if at least one mouse button is pressed
-	bool isMouseButtonPressed() const;
-
 	/// returns true if specified mouse button is pressed
 	bool isMouseButtonPressed(MouseButton button) const;
 

+ 3 - 0
client/gui/EventDispatcher.cpp

@@ -13,6 +13,9 @@
 #include "EventsReceiver.h"
 #include "FramerateManager.h"
 #include "CGuiHandler.h"
+#include "MouseButton.h"
+
+#include "../../lib/Point.h"
 
 void EventDispatcher::allowEventHandling(bool enable)
 {

+ 1 - 0
client/lobby/RandomMapTab.cpp

@@ -15,6 +15,7 @@
 #include "../CGameInfo.h"
 #include "../CServerHandler.h"
 #include "../gui/CGuiHandler.h"
+#include "../gui/MouseButton.h"
 #include "../gui/WindowHandler.h"
 #include "../widgets/CComponent.h"
 #include "../widgets/Buttons.h"

+ 1 - 0
client/mapView/MapViewActions.cpp

@@ -18,6 +18,7 @@
 #include "../adventureMap/AdventureMapInterface.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/CursorHandler.h"
+#include "../gui/MouseButton.h"
 
 #include "../../lib/CConfigHandler.h"
 

+ 1 - 0
client/widgets/Buttons.cpp

@@ -19,6 +19,7 @@
 #include "../battle/BattleInterface.h"
 #include "../battle/BattleInterfaceClasses.h"
 #include "../gui/CGuiHandler.h"
+#include "../gui/MouseButton.h"
 #include "../gui/Shortcut.h"
 #include "../windows/InfoWindows.h"
 #include "../render/CAnimation.h"