EventFilter.cpp 5.7 KB

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