mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 11:55:35 +08:00
Add alternative method to poll keyboard state on Windows
It seems that Windows is frequently disconnecting the keyboard hook (eventually if swift was too busy processing messages) and caused all hotkeys to be unreliable. Instead use a polling mechanism. The previous method is kept in code for testing, but is disabled by compile time switch.
This commit is contained in:
committed by
Klaus Basan
parent
324e16121e
commit
89ab1a0138
@@ -68,7 +68,9 @@ namespace BlackInput
|
||||
CKeyboardWindows::CKeyboardWindows(QObject *parent) :
|
||||
IKeyboard(parent),
|
||||
m_keyboardHook(nullptr)
|
||||
{ }
|
||||
{
|
||||
connect(&m_pollTimer, &QTimer::timeout, this, &CKeyboardWindows::pollKeyboardState);
|
||||
}
|
||||
|
||||
CKeyboardWindows::~CKeyboardWindows()
|
||||
{
|
||||
@@ -77,9 +79,17 @@ namespace BlackInput
|
||||
|
||||
bool CKeyboardWindows::init()
|
||||
{
|
||||
Q_ASSERT_X(g_keyboardWindows == nullptr, "CKeyboardWindows::init", "Windows supports only one keyboard instance. Cannot initialize a second one!");
|
||||
g_keyboardWindows = this;
|
||||
m_keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, CKeyboardWindows::keyboardProc, GetModuleHandle(nullptr), 0);
|
||||
if (useWindowsHook)
|
||||
{
|
||||
Q_ASSERT_X(g_keyboardWindows == nullptr, "CKeyboardWindows::init", "Windows supports only one keyboard instance. Cannot initialize a second one!");
|
||||
g_keyboardWindows = this;
|
||||
HMODULE module;
|
||||
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast<LPCTSTR>(&CKeyboardWindows::keyboardProc), &module);
|
||||
m_keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, CKeyboardWindows::keyboardProc, module, 0);
|
||||
}
|
||||
{
|
||||
m_pollTimer.start(50);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -105,6 +115,36 @@ namespace BlackInput
|
||||
}
|
||||
}
|
||||
|
||||
void CKeyboardWindows::pollKeyboardState()
|
||||
{
|
||||
BlackMisc::Input::CHotkeyCombination oldCombination(m_keyCombination);
|
||||
QList<int> vkeys = keyMapping().keys();
|
||||
for (int vkey : vkeys)
|
||||
{
|
||||
if ((GetKeyState(vkey) & 0x8000) && !m_pressedKeys.contains(vkey))
|
||||
{
|
||||
// key down
|
||||
auto key = keyMapping().value(vkey);
|
||||
if (key == Key_Unknown) { return; }
|
||||
m_pressedKeys.push_back(vkey);
|
||||
m_keyCombination.addKeyboardKey(CKeyboardKey(key));
|
||||
}
|
||||
else if (!(GetKeyState(vkey) & 0x8000) && m_pressedKeys.contains(vkey))
|
||||
{
|
||||
// key up
|
||||
auto key = keyMapping().value(vkey);
|
||||
if (key == Key_Unknown) { return; }
|
||||
m_pressedKeys.removeAll(vkey);
|
||||
m_keyCombination.removeKeyboardKey(CKeyboardKey(key));
|
||||
}
|
||||
}
|
||||
|
||||
if (oldCombination != m_keyCombination)
|
||||
{
|
||||
emit keyCombinationChanged(m_keyCombination);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK CKeyboardWindows::keyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (nCode == HC_ACTION)
|
||||
@@ -113,6 +153,6 @@ namespace BlackInput
|
||||
DWORD vkCode = keyboardEvent->vkCode;
|
||||
g_keyboardWindows->processKeyEvent(vkCode, wParam);
|
||||
}
|
||||
return CallNextHookEx(g_keyboardWindows->keyboardHook(), nCode, wParam, lParam);
|
||||
return CallNextHookEx(g_keyboardWindows->m_keyboardHook, nCode, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "blackmisc/input/keyboardkey.h"
|
||||
#include "blackmisc/input/keyboardkeylist.h"
|
||||
#include <QHash>
|
||||
#include <QTimer>
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
@@ -41,9 +42,6 @@ namespace BlackInput
|
||||
//! Destructor
|
||||
virtual ~CKeyboardWindows() override;
|
||||
|
||||
//! Keyboard hook handle
|
||||
HHOOK keyboardHook() const { return m_keyboardHook; }
|
||||
|
||||
protected:
|
||||
//! \copydoc IKeyboard::init()
|
||||
virtual bool init() override;
|
||||
@@ -57,12 +55,17 @@ namespace BlackInput
|
||||
void addKey(WPARAM vkcode);
|
||||
void removeKey(WPARAM vkcode);
|
||||
void processKeyEvent(DWORD vkCode, WPARAM event);
|
||||
void pollKeyboardState();
|
||||
|
||||
const bool useWindowsHook = false;
|
||||
|
||||
//! Keyboard hook procedure
|
||||
static LRESULT CALLBACK keyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
BlackMisc::Input::CHotkeyCombination m_keyCombination; //!< Set of virtual keys pressed in the last cycle
|
||||
HHOOK m_keyboardHook; //!< Keyboard hook handle
|
||||
QTimer m_pollTimer;
|
||||
QVector<int> m_pressedKeys;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user