diff options
author | Garrett Brown <themagnificentmrb@gmail.com> | 2018-09-25 09:06:04 +0200 |
---|---|---|
committer | Garrett Brown <themagnificentmrb@gmail.com> | 2018-09-27 08:59:15 +0300 |
commit | 8174c9412519400e941c09595b954587b7a6114e (patch) | |
tree | c52a3a318e65f8dded3b503f9cbb889fa354cb69 | |
parent | 5ff20e64e82ff57a8dd23a7763442c913793b8eb (diff) |
Joysticks: Send release event when button combo hotkey is released
This fixes the game getting stuck in rewind or fast-forward when the
Select key is released before the trigger.
-rw-r--r-- | xbmc/input/Action.cpp | 21 | ||||
-rw-r--r-- | xbmc/input/Action.h | 15 | ||||
-rw-r--r-- | xbmc/input/joysticks/keymaps/KeyHandler.cpp | 58 | ||||
-rw-r--r-- | xbmc/input/joysticks/keymaps/KeyHandler.h | 37 |
4 files changed, 95 insertions, 36 deletions
diff --git a/xbmc/input/Action.cpp b/xbmc/input/Action.cpp index 9c76796dbc..c45e8ad99c 100644 --- a/xbmc/input/Action.cpp +++ b/xbmc/input/Action.cpp @@ -11,13 +11,16 @@ #include "ActionTranslator.h" #include "Key.h" +CAction::CAction() : + m_id(ACTION_NONE) +{ +} + CAction::CAction(int actionID, float amount1 /* = 1.0f */, float amount2 /* = 0.0f */, const std::string &name /* = "" */, unsigned int holdTime /*= 0*/) { m_id = actionID; m_amount[0] = amount1; m_amount[1] = amount2; - for (unsigned int i = 2; i < max_amounts; i++) - m_amount[i] = 0; m_name = name; m_repeat = 0; m_buttonCode = 0; @@ -35,8 +38,6 @@ CAction::CAction(int actionID, unsigned int state, float posX, float posY, float m_amount[3] = offsetY; m_amount[4] = velocityX; m_amount[5] = velocityY; - for (unsigned int i = 6; i < max_amounts; i++) - m_amount[i] = 0; m_repeat = 0; m_buttonCode = 0; m_unicode = 0; @@ -46,8 +47,6 @@ CAction::CAction(int actionID, unsigned int state, float posX, float posY, float CAction::CAction(int actionID, wchar_t unicode) { m_id = actionID; - for (float& amount : m_amount) - amount = 0; m_repeat = 0; m_buttonCode = 0; m_unicode = unicode; @@ -59,8 +58,6 @@ CAction::CAction(int actionID, const std::string &name, const CKey &key): { m_id = actionID; m_amount[0] = 1; // digital button (could change this for repeat acceleration) - for (unsigned int i = 1; i < max_amounts; i++) - m_amount[i] = 0; m_repeat = key.GetRepeat(); m_buttonCode = key.GetButtonCode(); m_unicode = key.GetUnicode(); @@ -102,8 +99,6 @@ CAction::CAction(int actionID, const std::string &name): m_name(name) { m_id = actionID; - for (float& amount : m_amount) - amount = 0; m_repeat = 0; m_buttonCode = 0; m_unicode = 0; @@ -127,6 +122,12 @@ CAction& CAction::operator=(const CAction& rhs) return *this; } +void CAction::ClearAmount() +{ + for (float& amount : m_amount) + amount = 0; +} + bool CAction::IsMouse() const { return (m_id >= ACTION_MOUSE_START && m_id <= ACTION_MOUSE_END); diff --git a/xbmc/input/Action.h b/xbmc/input/Action.h index 9214c995b2..78d96bb042 100644 --- a/xbmc/input/Action.h +++ b/xbmc/input/Action.h @@ -21,6 +21,7 @@ class CKey; class CAction { public: + CAction(); CAction(int actionID, float amount1 = 1.0f, float amount2 = 0.0f, const std::string &name = "", unsigned int holdTime = 0); CAction(int actionID, wchar_t unicode); CAction(int actionID, unsigned int state, float posX, float posY, float offsetX, float offsetY, float velocityX = 0.0f, float velocityY = 0.0f, const std::string &name = ""); @@ -63,6 +64,10 @@ public: */ float GetAmount(unsigned int index = 0) const { return (index < max_amounts) ? m_amount[index] : 0; }; + /*! \brief Reset all amount values to zero + */ + void ClearAmount(); + /*! \brief Unicode value associated with this action \return unicode value associated with this action, for keyboard input. */ @@ -90,12 +95,12 @@ private: std::string m_name; static const unsigned int max_amounts = 6; // Must be at least 6 - float m_amount[max_amounts]; + float m_amount[max_amounts] = {}; - float m_repeat; - unsigned int m_holdTime; - unsigned int m_buttonCode; - wchar_t m_unicode; + float m_repeat = 0.0f; + unsigned int m_holdTime = 0; + unsigned int m_buttonCode = 0; + wchar_t m_unicode = 0; std::string m_text; }; diff --git a/xbmc/input/joysticks/keymaps/KeyHandler.cpp b/xbmc/input/joysticks/keymaps/KeyHandler.cpp index 92dde870dc..0be51467a6 100644 --- a/xbmc/input/joysticks/keymaps/KeyHandler.cpp +++ b/xbmc/input/joysticks/keymaps/KeyHandler.cpp @@ -9,7 +9,7 @@ #include "KeyHandler.h" #include "input/joysticks/interfaces/IKeymapHandler.h" #include "input/joysticks/JoystickUtils.h" -#include "input/Action.h" +#include "input/ActionIDs.h" #include "input/ActionTranslator.h" #include "input/IKeymap.h" #include "input/IKeymapEnvironment.h" @@ -48,6 +48,7 @@ void CKeyHandler::Reset() m_bActionSent = false; m_lastActionMs = 0; m_activeWindowId = -1; + m_lastAction = CAction(); } bool CKeyHandler::OnDigitalMotion(bool bPressed, unsigned int holdTimeMs) @@ -97,28 +98,49 @@ bool CKeyHandler::OnAnalogMotion(float magnitude, unsigned int motionTimeMs) actionsWithHotkeys.emplace_back(&action); } - bool bHandled = HandleActions(std::move(actionsWithHotkeys), windowId, magnitude, holdTimeMs); + CAction dispatchAction = ProcessActions(std::move(actionsWithHotkeys), windowId, magnitude, holdTimeMs); // If that failed, try again with all actions - if (!bHandled) + if (dispatchAction.GetID() == ACTION_NONE) { std::vector<const KeymapAction*> allActions; for (const auto &action : actions) allActions.emplace_back(&action); - bHandled = HandleActions(std::move(allActions), windowId, magnitude, holdTimeMs); + dispatchAction = ProcessActions(std::move(allActions), windowId, magnitude, holdTimeMs); + } + + // If specific action was sent last frame but not this one, send a release event + if (dispatchAction.GetID() != m_lastAction.GetID()) + { + if (CActionTranslator::IsAnalog(m_lastAction.GetID()) && m_lastAction.GetAmount() > 0.0f) + { + m_lastAction.ClearAmount(); + m_actionHandler->OnAction(m_lastAction); + } + } + + // Dispatch action + bool bHandled = false; + if (dispatchAction.GetID() != ACTION_NONE) + { + m_actionHandler->OnAction(dispatchAction); + bHandled = true; } m_bHeld = bPressed; m_magnitude = magnitude; m_lastHoldTimeMs = holdTimeMs; + m_lastAction = dispatchAction; return bHandled; } -bool CKeyHandler::HandleActions(std::vector<const KeymapAction*> actions, int windowId, float magnitude, unsigned int holdTimeMs) +CAction CKeyHandler::ProcessActions(std::vector<const KeymapAction*> actions, int windowId, float magnitude, unsigned int holdTimeMs) { + CAction dispatchAction; + // Filter out actions without pressed hotkeys actions.erase(std::remove_if(actions.begin(), actions.end(), [this](const KeymapAction *action) @@ -129,8 +151,6 @@ bool CKeyHandler::HandleActions(std::vector<const KeymapAction*> actions, int wi if (actions.empty()) return false; - bool bHandled = false; - // Actions are sorted by holdtime, so the final action is the one with the // greatest holdtime const KeymapAction& finalAction = **actions.rbegin(); @@ -139,7 +159,7 @@ bool CKeyHandler::HandleActions(std::vector<const KeymapAction*> actions, int wi const bool bHasDelay = (maxHoldTimeMs > 0); if (!bHasDelay) { - bHandled = HandleAction(finalAction, windowId, magnitude, holdTimeMs); + dispatchAction = ProcessAction(finalAction, windowId, magnitude, holdTimeMs); } else { @@ -152,7 +172,7 @@ bool CKeyHandler::HandleActions(std::vector<const KeymapAction*> actions, int wi else holdTimeMs -= finalAction.holdTimeMs; - bHandled = HandleAction(finalAction, windowId, magnitude, holdTimeMs); + dispatchAction = ProcessAction(finalAction, windowId, magnitude, holdTimeMs); } else { @@ -162,16 +182,16 @@ bool CKeyHandler::HandleActions(std::vector<const KeymapAction*> actions, int wi // If button was just released, send a release action if (bJustReleased) - bHandled = HandleRelease(actions, windowId); + dispatchAction = ProcessRelease(actions, windowId); } } - return bHandled; + return dispatchAction; } -bool CKeyHandler::HandleRelease(std::vector<const KeymapAction*> actions, int windowId) +CAction CKeyHandler::ProcessRelease(std::vector<const KeymapAction*> actions, int windowId) { - bool bHandled = false; + CAction dispatchAction; // Use previous holdtime from before button release const unsigned int holdTimeMs = m_lastHoldTimeMs; @@ -191,16 +211,18 @@ bool CKeyHandler::HandleRelease(std::vector<const KeymapAction*> actions, int wi if (thisHoldTime <= holdTimeMs && holdTimeMs < nextHoldTime) { - bHandled = HandleAction(action, windowId, 1.0f, 0); + dispatchAction = ProcessAction(action, windowId, 1.0f, 0); break; } } - return bHandled; + return dispatchAction; } -bool CKeyHandler::HandleAction(const KeymapAction& action, int windowId, float magnitude, unsigned int holdTimeMs) +CAction CKeyHandler::ProcessAction(const KeymapAction& action, int windowId, float magnitude, unsigned int holdTimeMs) { + CAction dispatchAction; + bool bSendAction = false; if (windowId != m_activeWindowId) @@ -223,13 +245,13 @@ bool CKeyHandler::HandleAction(const KeymapAction& action, int windowId, float m if (bSendAction) { const CAction guiAction(action.actionId, magnitude, 0.0f, action.actionString, holdTimeMs); - m_actionHandler->OnAction(guiAction); m_keymapHandler->OnPress(m_keyName); m_bActionSent = true; m_lastActionMs = holdTimeMs; + dispatchAction = guiAction; } - return m_bActionSent; + return dispatchAction; } bool CKeyHandler::SendRepeatAction(unsigned int holdTimeMs) diff --git a/xbmc/input/joysticks/keymaps/KeyHandler.h b/xbmc/input/joysticks/keymaps/KeyHandler.h index 498a0c427d..336dba7507 100644 --- a/xbmc/input/joysticks/keymaps/KeyHandler.h +++ b/xbmc/input/joysticks/keymaps/KeyHandler.h @@ -10,6 +10,7 @@ #include "input/joysticks/interfaces/IKeyHandler.h" #include "input/joysticks/JoystickTypes.h" +#include "input/Action.h" #include <map> #include <string> @@ -44,10 +45,39 @@ namespace JOYSTICK private: void Reset(); - bool HandleActions(std::vector<const KeymapAction*> actions, int windowId, float magnitude, unsigned int holdTimeMs); - bool HandleRelease(std::vector<const KeymapAction*> actions, int windowId); + /*! + * \brief Process actions to see if an action should be dispatched + * + * \param actions All actions from the keymap defined for the current window + * \param windowId The current window ID + * \param magnitude The magnitude or distance of the feature being handled + * \param holdTimeMs The time which the feature has been past the hold threshold + * + * \return The action to dispatch, or action with ID ACTION_NONE if no action should be dispatched + */ + CAction ProcessActions(std::vector<const KeymapAction*> actions, int windowId, float magnitude, unsigned int holdTimeMs); - bool HandleAction(const KeymapAction& action, int windowId, float magnitude, unsigned int holdTimeMs); + /*! + * \brief Process actions after release event to see if an action should be dispatched + * + * \param actions All actions from the keymap defined for the current window + * \param windowId The current window ID + * + * \return The action to dispatch, or action with ID ACTION_NONE if no action should be dispatched + */ + CAction ProcessRelease(std::vector<const KeymapAction*> actions, int windowId); + + /*! + * \brief Process an action to see if it should be dispatched + * + * \param action The action chosen to be dispatched + * \param windowId The current window ID + * \param magnitude The magnitude or distance of the feature being handled + * \param holdTimeMs The time which the feature has been past the hold threshold + * + * \return The action to dispatch, or action with ID ACTION_NONE if no action should be dispatched + */ + CAction ProcessAction(const KeymapAction& action, int windowId, float magnitude, unsigned int holdTimeMs); // Check criteria for sending a repeat action bool SendRepeatAction(unsigned int holdTimeMs); @@ -69,6 +99,7 @@ namespace JOYSTICK bool m_bActionSent; unsigned int m_lastActionMs; int m_activeWindowId = -1; // Window that activated the key + CAction m_lastAction; }; } } |