aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Brown <themagnificentmrb@gmail.com>2018-09-25 09:06:04 +0200
committerGarrett Brown <themagnificentmrb@gmail.com>2018-09-27 08:59:15 +0300
commit8174c9412519400e941c09595b954587b7a6114e (patch)
treec52a3a318e65f8dded3b503f9cbb889fa354cb69
parent5ff20e64e82ff57a8dd23a7763442c913793b8eb (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.cpp21
-rw-r--r--xbmc/input/Action.h15
-rw-r--r--xbmc/input/joysticks/keymaps/KeyHandler.cpp58
-rw-r--r--xbmc/input/joysticks/keymaps/KeyHandler.h37
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;
};
}
}