6 using namespace swift::misc::input;
10 static const auto &keyMapping()
49 { VK_LSHIFT, Key_ShiftLeft },
50 { VK_RSHIFT, Key_ShiftRight },
51 { VK_LCONTROL, Key_ControlLeft },
52 { VK_RCONTROL, Key_ControlRight },
53 { VK_LMENU, Key_AltLeft },
54 { VK_RMENU, Key_AltRight },
56 { VK_OEM_PLUS, Key_Plus },
57 { VK_SUBTRACT, Key_Minus },
58 { VK_OEM_MINUS, Key_Minus },
59 { VK_OEM_PERIOD, Key_Period },
60 { VK_DIVIDE, Key_Divide },
61 { VK_BACK, Key_Back },
63 { VK_ESCAPE, Key_Esc },
64 { VK_SPACE, Key_Space },
65 { VK_INSERT, Key_Insert },
66 { VK_DELETE, Key_Delete },
67 { VK_HOME, Key_Home },
69 { VK_PRIOR, Key_PageUp },
70 { VK_NEXT, Key_PageDown },
71 { VK_CAPITAL, Key_CapsLock },
72 { VK_RETURN, Key_Enter },
73 { VK_MULTIPLY, Key_Multiply },
74 { VK_SUBTRACT, Key_NumpadMinus },
75 { VK_ADD, Key_NumpadPlus },
76 { VK_DECIMAL, Key_NumpadDelete },
77 { VK_NUMPAD0, Key_Numpad0 },
78 { VK_NUMPAD1, Key_Numpad1 },
79 { VK_NUMPAD2, Key_Numpad2 },
80 { VK_NUMPAD3, Key_Numpad3 },
81 { VK_NUMPAD4, Key_Numpad4 },
82 { VK_NUMPAD5, Key_Numpad5 },
83 { VK_NUMPAD6, Key_Numpad6 },
84 { VK_NUMPAD7, Key_Numpad7 },
85 { VK_NUMPAD8, Key_Numpad8 },
86 { VK_NUMPAD9, Key_Numpad9 },
87 { VK_OEM_NEC_EQUAL, Key_NumpadEqual },
88 { VK_OEM_COMMA, Key_Comma },
89 { VK_OEM_1, Key_OEM1 },
90 { VK_OEM_2, Key_OEM2 },
91 { VK_OEM_3, Key_OEM3 },
92 { VK_OEM_4, Key_OEM4 },
93 { VK_OEM_5, Key_OEM5 },
94 { VK_OEM_6, Key_OEM6 },
95 { VK_OEM_7, Key_OEM7 },
96 { VK_OEM_8, Key_OEM8 },
97 { VK_OEM_102, Key_OEM102 },
98 { VK_F1, Key_Function1 },
99 { VK_F2, Key_Function2 },
100 { VK_F3, Key_Function3 },
101 { VK_F4, Key_Function4 },
102 { VK_F5, Key_Function5 },
103 { VK_F6, Key_Function6 },
104 { VK_F7, Key_Function7 },
105 { VK_F8, Key_Function8 },
106 { VK_F9, Key_Function9 },
107 { VK_F10, Key_Function10 },
108 { VK_F11, Key_Function11 },
109 { VK_F12, Key_Function12 },
110 { VK_F13, Key_Function13 },
111 { VK_F14, Key_Function14 },
112 { VK_F15, Key_Function15 },
113 { VK_F16, Key_Function16 },
114 { VK_F17, Key_Function17 },
115 { VK_F18, Key_Function18 },
116 { VK_F19, Key_Function19 },
117 { VK_F20, Key_Function20 },
118 { VK_F21, Key_Function21 },
119 { VK_F22, Key_Function22 },
120 { VK_F23, Key_Function23 },
121 { VK_F24, Key_Function24 },
126 static CKeyboardWindows *g_keyboardWindows =
nullptr;
128 CKeyboardWindows::CKeyboardWindows(QObject *parent) : IKeyboard(parent), m_keyboardHook(nullptr)
130 connect(&m_pollTimer, &QTimer::timeout,
this, &CKeyboardWindows::pollKeyboardState);
133 CKeyboardWindows::~CKeyboardWindows()
135 if (m_keyboardHook) { UnhookWindowsHookEx(m_keyboardHook); }
138 bool CKeyboardWindows::init()
142 Q_ASSERT_X(g_keyboardWindows ==
nullptr,
"CKeyboardWindows::init",
143 "Windows supports only one keyboard instance. Cannot initialize a second one!");
144 g_keyboardWindows =
this;
146 GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
147 reinterpret_cast<LPCTSTR
>(&CKeyboardWindows::keyboardProc), &module);
148 m_keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, CKeyboardWindows::keyboardProc, module, 0);
151 m_pollTimer.start(50);
156 void CKeyboardWindows::processKeyEvent(
DWORD vkcode, WPARAM event)
159 if ((event == WM_KEYDOWN) || (event == WM_SYSKEYDOWN))
161 auto key = keyMapping().value(
static_cast<int>(vkcode));
162 if (key == Key_Unknown) {
return; }
165 else if ((event == WM_KEYUP) || (event == WM_SYSKEYUP))
167 auto key = keyMapping().value(
static_cast<int>(vkcode));
168 if (key == Key_Unknown) {
return; }
172 if (oldCombination != m_keyCombination) { emit keyCombinationChanged(m_keyCombination); }
175 void CKeyboardWindows::pollKeyboardState()
178 QList<int> vkeys = keyMapping().keys();
179 for (
int vkey : vkeys)
181 if ((GetKeyState(vkey) & 0x8000) && !m_pressedKeys.contains(vkey))
184 auto key = keyMapping().value(vkey);
185 if (key == Key_Unknown) {
return; }
186 m_pressedKeys.push_back(vkey);
189 else if (!(GetKeyState(vkey) & 0x8000) && m_pressedKeys.contains(vkey))
192 auto key = keyMapping().value(vkey);
193 if (key == Key_Unknown) {
return; }
194 m_pressedKeys.removeAll(vkey);
199 if (oldCombination != m_keyCombination) { emit keyCombinationChanged(m_keyCombination); }
202 LRESULT CALLBACK CKeyboardWindows::keyboardProc(
int nCode, WPARAM wParam, LPARAM lParam)
204 if (nCode == HC_ACTION)
206 KBDLLHOOKSTRUCT *keyboardEvent =
reinterpret_cast<KBDLLHOOKSTRUCT *
>(lParam);
207 DWORD vkCode = keyboardEvent->vkCode;
208 g_keyboardWindows->processKeyEvent(vkCode, wParam);
210 return CallNextHookEx(g_keyboardWindows->m_keyboardHook, nCode, wParam, lParam);
unsigned long DWORD
Fake Windows DWORD.