Explorar el Código

Input: better stringification for key input with no text representation

This is mainly for special keys, for which Qt's QKeySequence will
essentially produce garbage text.

Try to avoid such strings, and produce a numeric key code instead. This
should not affect normal keys, for which we (and users) have hardcoded
key names in input maps.

Using QKeyEvent::nativeVirtualKey() is probably the best way to get
something numeric and that isn't completely arbitrary. But it can return
0, in which case we fall back to hex dumping the Qt potential-garbage
string. The suffix to the numbers ("V" and "Q") is supposed to
disambiguate and distinguish them.
Vincent Lang hace 8 años
padre
commit
47c96c11d4
Se han modificado 2 ficheros con 36 adiciones y 7 borrados
  1. 2 2
      src/input/InputKeyboard.h
  2. 34 5
      src/ui/EventFilter.cpp

+ 2 - 2
src/input/InputKeyboard.h

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

+ 34 - 5
src/ui/EventFilter.cpp

@@ -19,6 +19,37 @@ static QStringList desktopWhiteListedKeys = { "Media Play",
                                               "Media Rewind",
                                               "Media FastForward" };
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+static QString keyEventToKeyString(QKeyEvent *kevent)
+{
+  // We ignore the KeypadModifier here since it's practically useless
+  QKeySequence modifiers(kevent->modifiers() &= ~Qt::KeypadModifier);
+
+  QKeySequence keySeq(kevent->key());
+  QString key = keySeq.toString();
+
+  // Qt tends to make up something weird for keys which don't cleanly map to text.
+  // See e.g. QKeySequencePrivate::keyName() in the Qt sources.
+  // We can't really know for sure which names are "good" or "bad", so we simply
+  // allow printable latin1 characters, and mangle everything else.
+  if ((key.size() > 0 && (key[0].unicode() < 32 || key[0].unicode() > 255)))
+  {
+    if (kevent->nativeVirtualKey() != 0)
+    {
+      key = "0x" + QString::number(kevent->nativeVirtualKey(), 16) + "V";
+    }
+    else
+    {
+      QString properKey;
+      for (int n = 0; n < key.size(); n++)
+        properKey += QString(n > 0 ? "+" : "") + "0x" + QString::number(key[n].unicode(), 16) + "Q";
+      key = properKey;
+    }
+  }
+
+  return modifiers.toString() + key;
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 bool EventFilter::eventFilter(QObject* watched, QEvent* event)
 {
@@ -43,8 +74,8 @@ bool EventFilter::eventFilter(QObject* watched, QEvent* event)
         else
           keystatus = InputBase::KeyUp;
 
-        QKeySequence seq(key->key() | (key->modifiers() &= ~Qt::KeypadModifier));
-        if (desktopWhiteListedKeys.contains(seq.toString()))
+        QString seq = keyEventToKeyString(key);
+        if (desktopWhiteListedKeys.contains(seq))
         {
           InputKeyboard::Get().keyPress(seq, keystatus);
           return true;
@@ -96,9 +127,7 @@ bool EventFilter::eventFilter(QObject* watched, QEvent* event)
       system.setCursorVisibility(false);
       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, keystatus);
+        InputKeyboard::Get().keyPress(keyEventToKeyString(kevent), keystatus);
         return true;
       }
     }