Parcourir la source

Refactor the handling of button presses and handle autorepeat internally

This commit refactors the way we handle button presses in our input
component, we now expect a button down and button up event. This is so
that we can internally handle auto-repeat instead of relying on the
input to handle it themselves.

This also lays the ground for long press detection and sequences.
Tobias Hieta il y a 9 ans
Parent
commit
8e664be211

+ 3 - 3
src/input/InputCEC.cpp

@@ -185,9 +185,9 @@ void InputCECWorker::checkAdapter()
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-void InputCECWorker::sendReceivedInput(const QString &source, const QString &keycode, float amount)
+void InputCECWorker::sendReceivedInput(const QString &source, const QString &keycode, bool pressDown)
 {
-  emit receivedInput(source, keycode, amount);
+  emit receivedInput(source, keycode, true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -417,4 +417,4 @@ int InputCECWorker::CecAlert(void *cbParam, const libcec_alert type, const libce
   }
 
   return 0;
-}
+}

+ 4 - 6
src/input/InputCEC.h

@@ -20,10 +20,8 @@ class InputCEC : public InputBase
 public:
   InputCEC(QObject* parent);
 
-  virtual const char* inputName()
-  { return CEC_INPUT_NAME; }
-
-  virtual bool initInput();
+  virtual const char* inputName() override { return CEC_INPUT_NAME; }
+  virtual bool initInput() override;
 
 private:
   QThread* m_cecThread;
@@ -42,7 +40,7 @@ public:
   ~InputCECWorker();
 
   Q_SLOT bool init();
-  Q_SIGNAL void receivedInput(const QString& source, const QString& keycode, float amount);
+  Q_SIGNAL void receivedInput(const QString& source, const QString& keycode, bool pressDown);
 
 public slots:
   void checkAdapter();
@@ -54,7 +52,7 @@ private:
   void closeAdapter();
 
   QString getCommandString(cec_user_control_code code, unsigned int duration);
-  void sendReceivedInput(const QString& source, const QString& keycode, float amount = 1.0);
+  void sendReceivedInput(const QString& source, const QString& keycode, bool pressDown = true);
   QString getCommandParamsList(cec_command command);
 
   // libcec callbacks

+ 31 - 4
src/input/InputComponent.cpp

@@ -26,7 +26,7 @@
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-InputComponent::InputComponent(QObject* parent) : ComponentBase(parent)
+InputComponent::InputComponent(QObject* parent) : ComponentBase(parent), m_currentActionCount(0)
 {
   m_mappings = new InputMapping(this);
 }
@@ -47,6 +47,22 @@ bool InputComponent::addInput(InputBase* base)
   // needs to be remaped in remapInput and then finally send it out to JS land.
   //
   connect(base, &InputBase::receivedInput, this, &InputComponent::remapInput);
+
+
+  // for auto-repeating inputs
+  //
+  m_autoRepeatTimer = new QTimer(this);
+  connect(m_autoRepeatTimer, &QTimer::timeout, [=]()
+  {
+    if (!m_currentAction.isEmpty())
+    {
+      m_currentActionCount ++;
+      emit receivedAction(m_currentAction);
+    }
+
+    qint32 multiplier = qMin(5, qMax(1, m_currentActionCount / 5));
+    m_autoRepeatTimer->setInterval(100 / multiplier);
+  });
   
   return true;
 }
@@ -80,13 +96,21 @@ bool InputComponent::componentInitialize()
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-void InputComponent::remapInput(const QString &source, const QString &keycode, float amount)
+void InputComponent::remapInput(const QString &source, const QString &keycode, bool pressDown)
 {
+  QLOG_DEBUG() << "Input received: source:" << source << "keycode:" << keycode << "pressed:" << (pressDown ? "down" : "release");
+
+  if (!pressDown)
+  {
+    m_autoRepeatTimer->stop();
+    m_currentAction.clear();
+    m_currentActionCount = 0;
+    return;
+  }
+
   // hide mouse if it's visible.
   SystemComponent::Get().setCursorVisibility(false);
 
-  QLOG_DEBUG() << "Input received: source:" << source << "keycode:" << keycode;
-
   QString action = m_mappings->mapToAction(source, keycode);
   if (!action.isEmpty())
   {
@@ -123,7 +147,10 @@ void InputComponent::remapInput(const QString &source, const QString &keycode, f
     }
     else
     {
+      m_currentAction = action;
       emit receivedAction(action);
+
+      m_autoRepeatTimer->start(500);
     }
   }
   else

+ 6 - 2
src/input/InputComponent.h

@@ -3,6 +3,7 @@
 
 #include <QThread>
 #include <QVariantMap>
+#include <QTimer>
 #include "ComponentManager.h"
 #include "InputMapping.h"
 
@@ -15,7 +16,7 @@ public:
   virtual const char* inputName() = 0;
   
 signals:
-  void receivedInput(const QString& source, const QString& keycode, float amount = 1.0);
+  void receivedInput(const QString& source, const QString& keycode, bool pressDown = true);
 };
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -89,7 +90,7 @@ signals:
   void receivedAction(const QString& action);
 
 private Q_SLOTS:
-  void remapInput(const QString& source, const QString& keycode, float amount = 1.0);
+  void remapInput(const QString& source, const QString& keycode, bool pressDown = true);
   
 private:
   InputComponent(QObject *parent = 0);
@@ -98,6 +99,9 @@ private:
   QHash<QString, ReceiverSlot*> m_hostCommands;
   QList<InputBase*> m_inputs;
   InputMapping* m_mappings;
+  QTimer* m_autoRepeatTimer;
+  QString m_currentAction;
+  qint32 m_currentActionCount;
 };
 
 #endif // INPUTADAPTER_H

+ 2 - 2
src/input/InputKeyboard.h

@@ -18,9 +18,9 @@ public:
   virtual bool initInput() { return true; }
   virtual const char* inputName() { return "Keyboard"; }
 
-  void keyPress(const QKeySequence& sequence)
+  void keyPress(const QKeySequence& sequence, bool press)
   {
-    emit receivedInput("Keyboard", sequence.toString());
+    emit receivedInput("Keyboard", sequence.toString(), press);
   }
 
 private:

+ 1 - 1
src/input/InputSDL.h

@@ -40,7 +40,7 @@ public slots:
   void close();
 
 signals:
-  void receivedInput(const QString& source, const QString& keycode, float amount = 1.0);
+  void receivedInput(const QString& source, const QString& keycode, bool pressDown = true);
 
 private:
   void refreshJoystickList();

+ 6 - 3
src/ui/EventFilter.cpp

@@ -24,21 +24,24 @@ bool EventFilter::eventFilter(QObject* watched, QEvent* event)
     return true;
   }
 
-  if (event->type() == QEvent::KeyPress)
+  if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
   {
     // In konvergo we intercept all keyboard events and translate them
     // into web client actions. We need to do this so that we can remap
     // keyboard buttons to different events.
     //
+
+    bool pressed = event->type() == QEvent::KeyPress;
+
     QKeyEvent* kevent = dynamic_cast<QKeyEvent*>(event);
     if (kevent)
     {
       system.setCursorVisibility(false);
-      if (kevent->spontaneous())
+      if (kevent->spontaneous() && !kevent->isAutoRepeat())
       {
         // We ignore the KeypadModifier here since it's practically useless
         QKeySequence key(kevent->key() | (kevent->modifiers() &= ~Qt::KeypadModifier));
-        InputKeyboard::Get().keyPress(key);
+        InputKeyboard::Get().keyPress(key, pressed);
         return true;
       }
     }