1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

SDL event handling is now done exclusively in input handler

This commit is contained in:
Ivan Savenko
2023-05-18 23:31:05 +03:00
parent 5e86b00dda
commit 0e70f2998f
14 changed files with 52 additions and 78 deletions

View File

@@ -45,8 +45,6 @@
#undef main #undef main
#endif #endif
extern boost::mutex eventsM;
namespace po = boost::program_options; namespace po = boost::program_options;
namespace po_style = boost::program_options::command_line_style; namespace po_style = boost::program_options::command_line_style;
namespace bfs = boost::filesystem; namespace bfs = boost::filesystem;
@@ -528,15 +526,7 @@ void handleQuit(bool ask)
if(CSH->client && LOCPLINT && ask) if(CSH->client && LOCPLINT && ask)
{ {
CCS->curh->set(Cursor::Map::POINTER); CCS->curh->set(Cursor::Map::POINTER);
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], [](){ LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], quitApplication, nullptr);
// 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);
} }
else else
{ {

View File

@@ -22,6 +22,7 @@
#include "battle/BattleWindow.h" #include "battle/BattleWindow.h"
#include "../CCallback.h" #include "../CCallback.h"
#include "windows/CCastleInterface.h" #include "windows/CCastleInterface.h"
#include "eventsSDL/InputHandler.h"
#include "gui/CursorHandler.h" #include "gui/CursorHandler.h"
#include "windows/CKingdomInterface.h" #include "windows/CKingdomInterface.h"
#include "CGameInfo.h" #include "CGameInfo.h"
@@ -77,8 +78,6 @@
#include "eventsSDL/NotificationHandler.h" #include "eventsSDL/NotificationHandler.h"
#include "adventureMap/CInGameConsole.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. // 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. // They all assume that CPlayerInterface::pim mutex is locked.
#define EVENT_HANDLER_CALLED_BY_CLIENT #define EVENT_HANDLER_CALLED_BY_CLIENT
@@ -96,8 +95,6 @@
return; \ return; \
RETURN_IF_QUICK_COMBAT RETURN_IF_QUICK_COMBAT
extern std::queue<SDL_Event> SDLEventsQueue;
extern boost::mutex eventsM;
boost::recursive_mutex * CPlayerInterface::pim = new boost::recursive_mutex; boost::recursive_mutex * CPlayerInterface::pim = new boost::recursive_mutex;
CPlayerInterface * LOCPLINT; CPlayerInterface * LOCPLINT;
@@ -206,7 +203,7 @@ void CPlayerInterface::performAutosave()
} }
else if(frequency > 0 && cb->getDate() % frequency == 0) 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; autosaveCount %= 5;
} }
} }
@@ -215,8 +212,6 @@ void CPlayerInterface::yourTurn()
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
{ {
boost::unique_lock<boost::mutex> lock(eventsM); //block handling events until interface is ready
LOCPLINT = this; LOCPLINT = this;
GH.curInt = this; GH.curInt = this;
@@ -372,22 +367,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
//check if user cancelled movement //check if user cancelled movement
{ {
boost::unique_lock<boost::mutex> un(eventsM); if (GH.input().ignoreEventsUntilInput())
while(!SDLEventsQueue.empty()) stillMoveHero.setn(STOP_MOVE);
{
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 (stillMoveHero.get() == WAITING_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) 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) //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; LOCPLINT = this;
GH.curInt = this; GH.curInt = this;
adventureInt->onCurrentPlayerChanged(playerID); adventureInt->onCurrentPlayerChanged(playerID);
@@ -1875,11 +1855,7 @@ bool CPlayerInterface::capturedAllEvents()
if (ignoreEvents || needToLockAdventureMap || isAutoFightOn) if (ignoreEvents || needToLockAdventureMap || isAutoFightOn)
{ {
boost::unique_lock<boost::mutex> un(eventsM); GH.input().ignoreEventsUntilInput();
while(!SDLEventsQueue.empty())
{
SDLEventsQueue.pop();
}
return true; return true;
} }

View File

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

View File

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

View File

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

View File

@@ -21,6 +21,7 @@
#include "../gui/CGuiHandler.h" #include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h" #include "../gui/CursorHandler.h"
#include "../gui/EventDispatcher.h" #include "../gui/EventDispatcher.h"
#include "../gui/MouseButton.h"
#include "../CMT.h" #include "../CMT.h"
#include "../CPlayerInterface.h" #include "../CPlayerInterface.h"
#include "../CGameInfo.h" #include "../CGameInfo.h"
@@ -29,8 +30,6 @@
#include <SDL_events.h> #include <SDL_events.h>
std::queue<SDL_Event> SDLEventsQueue;
boost::mutex eventsM;
InputHandler::InputHandler() InputHandler::InputHandler()
: mouseHandler(std::make_unique<InputSourceMouse>()) : 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) 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))) 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 //preprocessing
if(ev.type == SDL_MOUSEMOTION) 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);
} }
{ {

View File

@@ -24,6 +24,9 @@ class UserEventHandler;
class InputHandler class InputHandler
{ {
std::queue<SDL_Event> SDLEventsQueue;
boost::mutex eventsM;
Point cursorPosition; Point cursorPosition;
float pointerSpeedMultiplier; float pointerSpeedMultiplier;
int mouseButtonsMask; int mouseButtonsMask;
@@ -44,6 +47,10 @@ public:
void fetchEvents(); void fetchEvents();
void processEvents(); 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 fakeMoveCursor(float dx, float dy);
void startTextInput(const Rect & where); void startTextInput(const Rect & where);
void stopTextInput(); void stopTextInput();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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