Fix hold key presses in lists. #1170

Merged
merged 2 commits into from Aug 1, 2012
View
@@ -2478,10 +2478,23 @@ bool CApplication::OnKey(const CKey& key)
if (!key.IsAnalogButton())
CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
- // Play a sound based on the action
- g_audioManager.PlayActionSound(action);
+ bool bResult = false;
- return OnAction(action);
+ // play sound before the action unless the button is held,
+ // where we execute after the action as held actions aren't fired every time.
+ if(action.GetHoldTime())
+ {
+ bResult = OnAction(action);
+ if(bResult)
+ g_audioManager.PlayActionSound(action);
+ }
+ else
+ {
+ g_audioManager.PlayActionSound(action);
+ bResult = OnAction(action);
+ }
+
+ return bResult;
}
// OnAppCommand is called in response to a XBMC_APPCOMMAND event.
@@ -3308,8 +3321,23 @@ bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKe
if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange))
{
CAction action(actionID, fAmount, 0.0f, actionName, holdTime);
- g_audioManager.PlayActionSound(action);
- return OnAction(action);
+ bool bResult = false;
+
+ // play sound before the action unless the button is held,
+ // where we execute after the action as held actions aren't fired every time.
+ if(action.GetHoldTime())
+ {
+ bResult = OnAction(action);
+ if(bResult)
+ g_audioManager.PlayActionSound(action);
+ }
+ else
+ {
+ g_audioManager.PlayActionSound(action);
+ bResult = OnAction(action);
+ }
+
+ return bResult;
}
else
{
@@ -59,6 +59,7 @@ CGUIBaseContainer::CGUIBaseContainer(int parentID, int controlID, float posX, fl
m_layout = NULL;
m_focusedLayout = NULL;
m_cacheItems = preloadItems;
+ m_scrollItemsPerFrame = 0.0f;
}
CGUIBaseContainer::~CGUIBaseContainer(void)
@@ -294,24 +295,33 @@ bool CGUIBaseContainer::OnAction(const CAction &action)
case ACTION_NAV_BACK:
{
if (!HasFocus()) return false;
+
if (action.GetHoldTime() > HOLD_TIME_START &&
((m_orientation == VERTICAL && (action.GetID() == ACTION_MOVE_UP || action.GetID() == ACTION_MOVE_DOWN)) ||
(m_orientation == HORIZONTAL && (action.GetID() == ACTION_MOVE_LEFT || action.GetID() == ACTION_MOVE_RIGHT))))
{ // action is held down - repeat a number of times
float speed = std::min(1.0f, (float)(action.GetHoldTime() - HOLD_TIME_START) / (HOLD_TIME_END - HOLD_TIME_START));
- unsigned int itemsPerFrame = 1;
- if (m_lastHoldTime) // number of rows/10 items/second max speed
- itemsPerFrame = std::max((unsigned int)1, (unsigned int)(speed * 0.0001f * GetRows() * (CTimeUtils::GetFrameTime() - m_lastHoldTime)));
+ unsigned int frameDuration = CTimeUtils::GetFrameTime() - m_lastHoldTime;
+
+ //scrollrate is minimum 4 items/sec and max rows/10 items/sec
+ m_scrollItemsPerFrame += std::max(0.004f*(float)frameDuration, (float)(speed * 0.0001f * GetRows() * frameDuration));
m_lastHoldTime = CTimeUtils::GetFrameTime();
+
+ if(m_scrollItemsPerFrame < 1.0f)//not enough hold time accumulated for one step
+ return false;
+
if (action.GetID() == ACTION_MOVE_LEFT || action.GetID() == ACTION_MOVE_UP)
- while (itemsPerFrame--) MoveUp(false);
+ while (m_scrollItemsPerFrame-- >= 1) MoveUp(false);
else
- while (itemsPerFrame--) MoveDown(false);
+ while (m_scrollItemsPerFrame-- >= 1) MoveDown(false);
return true;
}
else
{
- m_lastHoldTime = 0;
+ //if HOLD_TIME_START is reached we need
+ //a sane initial value for calculating m_scrollItemsPerPage
+ m_lastHoldTime = CTimeUtils::GetFrameTime();
+ m_scrollItemsPerFrame = 0.0f;
return CGUIControl::OnAction(action);
}
}
@@ -208,6 +208,7 @@ class CGUIBaseContainer : public CGUIControl
// letter match searching
CStopWatch m_matchTimer;
CStdString m_match;
+ float m_scrollItemsPerFrame;
static const int letter_match_timeout = 1000;
};