EventFilter.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //
  2. // Created by Tobias Hieta on 07/03/16.
  3. //
  4. #include "EventFilter.h"
  5. #include "system/SystemComponent.h"
  6. #include "settings/SettingsComponent.h"
  7. #include "input/InputKeyboard.h"
  8. #include "KonvergoWindow.h"
  9. #include <QKeyEvent>
  10. #include <QObject>
  11. static QStringList desktopWhiteListedKeys = { "Media Play",
  12. "Media Pause",
  13. "Media Stop",
  14. "Media Next",
  15. "Media Previous",
  16. "Media Rewind",
  17. "Media FastForward",
  18. "Back"};
  19. // These just happen to be mostly the same.
  20. static QStringList win32AppcommandBlackListedKeys = desktopWhiteListedKeys;
  21. ///////////////////////////////////////////////////////////////////////////////////////////////////
  22. static QString keyEventToKeyString(QKeyEvent *kevent)
  23. {
  24. // We ignore the KeypadModifier here since it's practically useless
  25. QKeySequence modifiers(kevent->modifiers() &= ~Qt::KeypadModifier);
  26. QKeySequence keySeq(kevent->key());
  27. QString key = keySeq.toString();
  28. // Qt tends to make up something weird for keys which don't cleanly map to text.
  29. // See e.g. QKeySequencePrivate::keyName() in the Qt sources.
  30. // We can't really know for sure which names are "good" or "bad", so we simply
  31. // allow printable latin1 characters, and mangle everything else.
  32. if ((key.size() > 0 && (key[0].unicode() < 32 || key[0].unicode() > 255)))
  33. {
  34. if (kevent->nativeVirtualKey() != 0)
  35. {
  36. key = "0x" + QString::number(kevent->nativeVirtualKey(), 16) + "V";
  37. }
  38. else
  39. {
  40. QString properKey;
  41. for (int n = 0; n < key.size(); n++)
  42. properKey += QString(n > 0 ? "+" : "") + "0x" + QString::number(key[n].unicode(), 16) + "Q";
  43. key = properKey;
  44. }
  45. }
  46. return modifiers.toString() + key;
  47. }
  48. ///////////////////////////////////////////////////////////////////////////////////////////////////
  49. bool EventFilter::eventFilter(QObject* watched, QEvent* event)
  50. {
  51. KonvergoWindow* window = qobject_cast<KonvergoWindow*>(parent());
  52. if (window && window->property("webDesktopMode").toBool())
  53. {
  54. // For desktop mode we don't want fullblown keyboard handling in
  55. // the host yet. We just want to handle some specific keyboard
  56. // events.
  57. //
  58. if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease || event->type() == QEvent::ShortcutOverride)
  59. {
  60. QKeyEvent* key = dynamic_cast<QKeyEvent*>(event);
  61. if (key)
  62. {
  63. InputBase::InputkeyState keystatus;
  64. if (event->type() == QEvent::KeyPress)
  65. keystatus = InputBase::KeyDown;
  66. else
  67. keystatus = InputBase::KeyUp;
  68. QString seq = keyEventToKeyString(key);
  69. if (desktopWhiteListedKeys.contains(seq))
  70. {
  71. InputKeyboard::Get().keyPress(seq, keystatus);
  72. return true;
  73. }
  74. }
  75. }
  76. return QObject::eventFilter(watched, event);
  77. }
  78. SystemComponent& system = SystemComponent::Get();
  79. // ignore mouse events if mouse is disabled
  80. if (SettingsComponent::Get().value(SETTINGS_SECTION_MAIN, "disablemouse").toBool() &&
  81. ((event->type() == QEvent::MouseMove) ||
  82. (event->type() == QEvent::MouseButtonPress) ||
  83. (event->type() == QEvent::MouseButtonRelease) ||
  84. (event->type() == QEvent::MouseButtonDblClick)))
  85. {
  86. return true;
  87. }
  88. if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
  89. {
  90. // In konvergo we intercept all keyboard events and translate them
  91. // into web client actions. We need to do this so that we can remap
  92. // keyboard buttons to different events.
  93. //
  94. InputBase::InputkeyState keystatus;
  95. if (event->type() == QEvent::KeyPress)
  96. keystatus = InputBase::KeyDown;
  97. else
  98. keystatus = InputBase::KeyUp;
  99. QKeyEvent* kevent = dynamic_cast<QKeyEvent*>(event);
  100. if (!kevent)
  101. return QObject::eventFilter(watched, event);
  102. QString keyName = keyEventToKeyString(kevent);
  103. #ifdef Q_OS_WIN32
  104. // On Windows, we get some media keys twice. This is because Windows supports both
  105. // normal key events and APPCOMMAND_ messages for media keys. To avoid getting two
  106. // key events per key press, filter out non-APPCOMMAND media keys by using the fact
  107. // that APPCOMMAND media keys won't have a key code.
  108. if (win32AppcommandBlackListedKeys.contains(keyName) && kevent->nativeVirtualKey())
  109. return QObject::eventFilter(watched, event);
  110. #endif
  111. if (keystatus == InputBase::KeyDown)
  112. {
  113. // Swallow auto-repeated keys (isAutoRepeat doesn't always work - QTBUG-57335)
  114. // Do this only for non-modifier keys (QKeyEvent::text serves as a heuristic
  115. // to distinguish them from normal key presses)
  116. if (kevent->text().size())
  117. {
  118. if (m_currentKeyDown)
  119. return true;
  120. m_currentKeyDown = true;
  121. }
  122. }
  123. else
  124. m_currentKeyDown = false;
  125. system.setCursorVisibility(false);
  126. if (kevent->spontaneous() && !kevent->isAutoRepeat())
  127. {
  128. InputKeyboard::Get().keyPress(keyName, keystatus);
  129. return true;
  130. }
  131. }
  132. else if (event->type() == QEvent::MouseMove)
  133. {
  134. system.setCursorVisibility(true);
  135. }
  136. else if (event->type() == QEvent::Wheel)
  137. {
  138. return true;
  139. }
  140. else if (event->type() == QEvent::MouseButtonPress)
  141. {
  142. // ignore right clicks that would show context menu
  143. QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
  144. if ((mouseEvent) && (mouseEvent->button() == Qt::RightButton))
  145. return true;
  146. }
  147. else if (event->type() == QEvent::Drop)
  148. {
  149. // QtWebEngine would accept the drop and unload web-client.
  150. return true;
  151. }
  152. return QObject::eventFilter(watched, event);
  153. }