Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwindowskeymapper.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qwindowskeymapper.h"
5#include "qwindowscontext.h"
7#include "qwindowswindow.h"
9
10#include <QtGui/qguiapplication.h>
11#include <QtGui/qwindow.h>
12#include <qpa/qwindowsysteminterface.h>
13#include <private/qguiapplication_p.h>
14#include <private/qhighdpiscaling_p.h>
15#include <QtGui/qevent.h>
16#include <QtGui/private/qwindowsguieventdispatcher_p.h>
17#include <QtCore/private/qdebug_p.h>
18#include <QtCore/private/qtools_p.h>
19
20#if defined(WM_APPCOMMAND)
21# ifndef FAPPCOMMAND_MOUSE
22# define FAPPCOMMAND_MOUSE 0x8000
23# endif
24# ifndef FAPPCOMMAND_KEY
25# define FAPPCOMMAND_KEY 0
26# endif
27# ifndef FAPPCOMMAND_OEM
28# define FAPPCOMMAND_OEM 0x1000
29# endif
30# ifndef FAPPCOMMAND_MASK
31# define FAPPCOMMAND_MASK 0xF000
32# endif
33# ifndef GET_APPCOMMAND_LPARAM
34# define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
35# endif
36# ifndef GET_DEVICE_LPARAM
37# define GET_DEVICE_LPARAM(lParam) ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK))
38# endif
39# ifndef GET_MOUSEORKEY_LPARAM
40# define GET_MOUSEORKEY_LPARAM GET_DEVICE_LPARAM
41# endif
42# ifndef GET_FLAGS_LPARAM
43# define GET_FLAGS_LPARAM(lParam) (LOWORD(lParam))
44# endif
45# ifndef GET_KEYSTATE_LPARAM
46# define GET_KEYSTATE_LPARAM(lParam) GET_FLAGS_LPARAM(lParam)
47# endif
48#endif
49
51
62
64 : m_useRTLExtensions(false), m_keyGrabber(nullptr)
65{
66 memset(keyLayout, 0, sizeof(keyLayout));
67 auto *app = static_cast<QGuiApplication *>(QGuiApplication::instance());
71}
72
74
75#ifndef LANG_PASHTO
76#define LANG_PASHTO 0x63
77#endif
78#ifndef LANG_SYRIAC
79#define LANG_SYRIAC 0x5a
80#endif
81#ifndef LANG_DIVEHI
82#define LANG_DIVEHI 0x65
83#endif
84#ifndef VK_OEM_PLUS
85#define VK_OEM_PLUS 0xBB
86#endif
87#ifndef VK_OEM_3
88#define VK_OEM_3 0xC0
89#endif
90
91// Get scancode from the given message
92static constexpr quint32 getScancode(const MSG &msg)
93{
94 const auto keyFlags = HIWORD(msg.lParam);
95 quint32 scancode = LOBYTE(keyFlags);
96 // if extended-key flag is on, the scan code consists of a sequence of two bytes,
97 // where the first byte has a value of 0xe0.
98 if ((keyFlags & KF_EXTENDED) != 0)
99 scancode |= 0xE000;
100 return scancode;
101}
102
103// Key recorder ------------------------------------------------------------------------[ start ] --
104struct KeyRecord {
105 KeyRecord(int c, int a, int s, const QString &t) : code(c), ascii(a), state(s), text(t) {}
107
108 int code;
109 int ascii;
110 int state;
112};
113
114// We need to record the pressed keys in order to decide, whether the key event is an autorepeat
115// event. As soon as its state changes, the chain of autorepeat events will be broken.
116static const int QT_MAX_KEY_RECORDINGS = 64; // User has LOTS of fingers...
118{
119 inline KeyRecord *findKey(int code, bool remove);
120 inline void storeKey(int code, int ascii, int state, const QString& text);
121 inline void clearKeys();
122
123 int nrecs = 0;
124 KeyRecord deleted_record; // A copy of last entry removed from records[]
126};
128
134
136{
137 KeyRecord *result = nullptr;
138 for (int i = 0; i < nrecs; ++i) {
139 if (records[i].code == code) {
140 if (remove) {
142 // Move rest down, and decrease count
143 while (i + 1 < nrecs) {
144 records[i] = records[i + 1];
145 ++i;
146 }
147 --nrecs;
149 } else {
150 result = &records[i];
151 }
152 break;
153 }
154 }
155 return result;
156}
157
158void KeyRecorder::storeKey(int code, int ascii, int state, const QString& text)
159{
161 "Internal KeyRecorder",
162 "Keyboard recorder buffer overflow, consider increasing QT_MAX_KEY_RECORDINGS");
163
165 qWarning("Qt: Internal keyboard buffer overflow");
166 return;
167 }
168 records[nrecs++] = KeyRecord(code,ascii,state,text);
169}
170
172{
173 nrecs = 0;
174}
175// Key recorder --------------------------------------------------------------------------[ end ] --
176
177
178// Key translation ---------------------------------------------------------------------[ start ] --
179// Meaning of values:
180// 0 = Character output key, needs keyboard driver mapping
181// Key_unknown = Unknown Virtual Key, no translation possible, ignore
182static const uint KeyTbl[] = { // Keyboard mapping table
183 // Dec | Hex | Windows Virtual key
184 Qt::Key_unknown, // 0 0x00
185 Qt::Key_unknown, // 1 0x01 VK_LBUTTON | Left mouse button
186 Qt::Key_unknown, // 2 0x02 VK_RBUTTON | Right mouse button
187 Qt::Key_Cancel, // 3 0x03 VK_CANCEL | Control-Break processing
188 Qt::Key_unknown, // 4 0x04 VK_MBUTTON | Middle mouse button
189 Qt::Key_unknown, // 5 0x05 VK_XBUTTON1 | X1 mouse button
190 Qt::Key_unknown, // 6 0x06 VK_XBUTTON2 | X2 mouse button
191 Qt::Key_unknown, // 7 0x07 -- unassigned --
192 Qt::Key_Backspace, // 8 0x08 VK_BACK | BackSpace key
193 Qt::Key_Tab, // 9 0x09 VK_TAB | Tab key
194 Qt::Key_unknown, // 10 0x0A -- reserved --
195 Qt::Key_unknown, // 11 0x0B -- reserved --
196 Qt::Key_Clear, // 12 0x0C VK_CLEAR | Clear key
197 Qt::Key_Return, // 13 0x0D VK_RETURN | Enter key
198 Qt::Key_unknown, // 14 0x0E -- unassigned --
199 Qt::Key_unknown, // 15 0x0F -- unassigned --
200 Qt::Key_Shift, // 16 0x10 VK_SHIFT | Shift key
201 Qt::Key_Control, // 17 0x11 VK_CONTROL | Ctrl key
202 Qt::Key_Alt, // 18 0x12 VK_MENU | Alt key
203 Qt::Key_Pause, // 19 0x13 VK_PAUSE | Pause key
204 Qt::Key_CapsLock, // 20 0x14 VK_CAPITAL | Caps-Lock
205 Qt::Key_unknown, // 21 0x15 VK_KANA / VK_HANGUL | IME Kana or Hangul mode
206 Qt::Key_unknown, // 22 0x16 -- unassigned --
207 Qt::Key_unknown, // 23 0x17 VK_JUNJA | IME Junja mode
208 Qt::Key_unknown, // 24 0x18 VK_FINAL | IME final mode
209 Qt::Key_unknown, // 25 0x19 VK_HANJA / VK_KANJI | IME Hanja or Kanji mode
210 Qt::Key_unknown, // 26 0x1A -- unassigned --
211 Qt::Key_Escape, // 27 0x1B VK_ESCAPE | Esc key
212 Qt::Key_unknown, // 28 0x1C VK_CONVERT | IME convert
213 Qt::Key_unknown, // 29 0x1D VK_NONCONVERT | IME non-convert
214 Qt::Key_unknown, // 30 0x1E VK_ACCEPT | IME accept
215 Qt::Key_Mode_switch,// 31 0x1F VK_MODECHANGE | IME mode change request
216 Qt::Key_Space, // 32 0x20 VK_SPACE | Spacebar
217 Qt::Key_PageUp, // 33 0x21 VK_PRIOR | Page Up key
218 Qt::Key_PageDown, // 34 0x22 VK_NEXT | Page Down key
219 Qt::Key_End, // 35 0x23 VK_END | End key
220 Qt::Key_Home, // 36 0x24 VK_HOME | Home key
221 Qt::Key_Left, // 37 0x25 VK_LEFT | Left arrow key
222 Qt::Key_Up, // 38 0x26 VK_UP | Up arrow key
223 Qt::Key_Right, // 39 0x27 VK_RIGHT | Right arrow key
224 Qt::Key_Down, // 40 0x28 VK_DOWN | Down arrow key
225 Qt::Key_Select, // 41 0x29 VK_SELECT | Select key
226 Qt::Key_Printer, // 42 0x2A VK_PRINT | Print key
227 Qt::Key_Execute, // 43 0x2B VK_EXECUTE | Execute key
228 Qt::Key_Print, // 44 0x2C VK_SNAPSHOT | Print Screen key
229 Qt::Key_Insert, // 45 0x2D VK_INSERT | Ins key
230 Qt::Key_Delete, // 46 0x2E VK_DELETE | Del key
231 Qt::Key_Help, // 47 0x2F VK_HELP | Help key
232 0, // 48 0x30 (VK_0) | 0 key
233 0, // 49 0x31 (VK_1) | 1 key
234 0, // 50 0x32 (VK_2) | 2 key
235 0, // 51 0x33 (VK_3) | 3 key
236 0, // 52 0x34 (VK_4) | 4 key
237 0, // 53 0x35 (VK_5) | 5 key
238 0, // 54 0x36 (VK_6) | 6 key
239 0, // 55 0x37 (VK_7) | 7 key
240 0, // 56 0x38 (VK_8) | 8 key
241 0, // 57 0x39 (VK_9) | 9 key
242 Qt::Key_unknown, // 58 0x3A -- unassigned --
243 Qt::Key_unknown, // 59 0x3B -- unassigned --
244 Qt::Key_unknown, // 60 0x3C -- unassigned --
245 Qt::Key_unknown, // 61 0x3D -- unassigned --
246 Qt::Key_unknown, // 62 0x3E -- unassigned --
247 Qt::Key_unknown, // 63 0x3F -- unassigned --
248 Qt::Key_unknown, // 64 0x40 -- unassigned --
249 0, // 65 0x41 (VK_A) | A key
250 0, // 66 0x42 (VK_B) | B key
251 0, // 67 0x43 (VK_C) | C key
252 0, // 68 0x44 (VK_D) | D key
253 0, // 69 0x45 (VK_E) | E key
254 0, // 70 0x46 (VK_F) | F key
255 0, // 71 0x47 (VK_G) | G key
256 0, // 72 0x48 (VK_H) | H key
257 0, // 73 0x49 (VK_I) | I key
258 0, // 74 0x4A (VK_J) | J key
259 0, // 75 0x4B (VK_K) | K key
260 0, // 76 0x4C (VK_L) | L key
261 0, // 77 0x4D (VK_M) | M key
262 0, // 78 0x4E (VK_N) | N key
263 0, // 79 0x4F (VK_O) | O key
264 0, // 80 0x50 (VK_P) | P key
265 0, // 81 0x51 (VK_Q) | Q key
266 0, // 82 0x52 (VK_R) | R key
267 0, // 83 0x53 (VK_S) | S key
268 0, // 84 0x54 (VK_T) | T key
269 0, // 85 0x55 (VK_U) | U key
270 0, // 86 0x56 (VK_V) | V key
271 0, // 87 0x57 (VK_W) | W key
272 0, // 88 0x58 (VK_X) | X key
273 0, // 89 0x59 (VK_Y) | Y key
274 0, // 90 0x5A (VK_Z) | Z key
275 Qt::Key_Meta, // 91 0x5B VK_LWIN | Left Windows - MS Natural kbd
276 Qt::Key_Meta, // 92 0x5C VK_RWIN | Right Windows - MS Natural kbd
277 Qt::Key_Menu, // 93 0x5D VK_APPS | Application key-MS Natural kbd
278 Qt::Key_unknown, // 94 0x5E -- reserved --
279 Qt::Key_Sleep, // 95 0x5F VK_SLEEP
280 Qt::Key_0, // 96 0x60 VK_NUMPAD0 | Numeric keypad 0 key
281 Qt::Key_1, // 97 0x61 VK_NUMPAD1 | Numeric keypad 1 key
282 Qt::Key_2, // 98 0x62 VK_NUMPAD2 | Numeric keypad 2 key
283 Qt::Key_3, // 99 0x63 VK_NUMPAD3 | Numeric keypad 3 key
284 Qt::Key_4, // 100 0x64 VK_NUMPAD4 | Numeric keypad 4 key
285 Qt::Key_5, // 101 0x65 VK_NUMPAD5 | Numeric keypad 5 key
286 Qt::Key_6, // 102 0x66 VK_NUMPAD6 | Numeric keypad 6 key
287 Qt::Key_7, // 103 0x67 VK_NUMPAD7 | Numeric keypad 7 key
288 Qt::Key_8, // 104 0x68 VK_NUMPAD8 | Numeric keypad 8 key
289 Qt::Key_9, // 105 0x69 VK_NUMPAD9 | Numeric keypad 9 key
290 Qt::Key_Asterisk, // 106 0x6A VK_MULTIPLY | Multiply key
291 Qt::Key_Plus, // 107 0x6B VK_ADD | Add key
292 Qt::Key_unknown, // 108 0x6C VK_SEPARATOR | Separator key (locale-dependent)
293 Qt::Key_Minus, // 109 0x6D VK_SUBTRACT | Subtract key
294 Qt::Key_unknown, // 110 0x6E VK_DECIMAL | Decimal key (locale-dependent)
295 Qt::Key_Slash, // 111 0x6F VK_DIVIDE | Divide key
296 Qt::Key_F1, // 112 0x70 VK_F1 | F1 key
297 Qt::Key_F2, // 113 0x71 VK_F2 | F2 key
298 Qt::Key_F3, // 114 0x72 VK_F3 | F3 key
299 Qt::Key_F4, // 115 0x73 VK_F4 | F4 key
300 Qt::Key_F5, // 116 0x74 VK_F5 | F5 key
301 Qt::Key_F6, // 117 0x75 VK_F6 | F6 key
302 Qt::Key_F7, // 118 0x76 VK_F7 | F7 key
303 Qt::Key_F8, // 119 0x77 VK_F8 | F8 key
304 Qt::Key_F9, // 120 0x78 VK_F9 | F9 key
305 Qt::Key_F10, // 121 0x79 VK_F10 | F10 key
306 Qt::Key_F11, // 122 0x7A VK_F11 | F11 key
307 Qt::Key_F12, // 123 0x7B VK_F12 | F12 key
308 Qt::Key_F13, // 124 0x7C VK_F13 | F13 key
309 Qt::Key_F14, // 125 0x7D VK_F14 | F14 key
310 Qt::Key_F15, // 126 0x7E VK_F15 | F15 key
311 Qt::Key_F16, // 127 0x7F VK_F16 | F16 key
312 Qt::Key_F17, // 128 0x80 VK_F17 | F17 key
313 Qt::Key_F18, // 129 0x81 VK_F18 | F18 key
314 Qt::Key_F19, // 130 0x82 VK_F19 | F19 key
315 Qt::Key_F20, // 131 0x83 VK_F20 | F20 key
316 Qt::Key_F21, // 132 0x84 VK_F21 | F21 key
317 Qt::Key_F22, // 133 0x85 VK_F22 | F22 key
318 Qt::Key_F23, // 134 0x86 VK_F23 | F23 key
319 Qt::Key_F24, // 135 0x87 VK_F24 | F24 key
320 Qt::Key_unknown, // 136 0x88 -- unassigned --
321 Qt::Key_unknown, // 137 0x89 -- unassigned --
322 Qt::Key_unknown, // 138 0x8A -- unassigned --
323 Qt::Key_unknown, // 139 0x8B -- unassigned --
324 Qt::Key_unknown, // 140 0x8C -- unassigned --
325 Qt::Key_unknown, // 141 0x8D -- unassigned --
326 Qt::Key_unknown, // 142 0x8E -- unassigned --
327 Qt::Key_unknown, // 143 0x8F -- unassigned --
328 Qt::Key_NumLock, // 144 0x90 VK_NUMLOCK | Num Lock key
329 Qt::Key_ScrollLock, // 145 0x91 VK_SCROLL | Scroll Lock key
330 // Fujitsu/OASYS kbd --------------------
331 0, //Qt::Key_Jisho, // 146 0x92 VK_OEM_FJ_JISHO | 'Dictionary' key /
332 // VK_OEM_NEC_EQUAL = key on numpad on NEC PC-9800 kbd
333 Qt::Key_Massyo, // 147 0x93 VK_OEM_FJ_MASSHOU | 'Unregister word' key
334 Qt::Key_Touroku, // 148 0x94 VK_OEM_FJ_TOUROKU | 'Register word' key
335 0, //Qt::Key_Oyayubi_Left,//149 0x95 VK_OEM_FJ_LOYA | 'Left OYAYUBI' key
336 0, //Qt::Key_Oyayubi_Right,//150 0x96 VK_OEM_FJ_ROYA | 'Right OYAYUBI' key
337 Qt::Key_unknown, // 151 0x97 -- unassigned --
338 Qt::Key_unknown, // 152 0x98 -- unassigned --
339 Qt::Key_unknown, // 153 0x99 -- unassigned --
340 Qt::Key_unknown, // 154 0x9A -- unassigned --
341 Qt::Key_unknown, // 155 0x9B -- unassigned --
342 Qt::Key_unknown, // 156 0x9C -- unassigned --
343 Qt::Key_unknown, // 157 0x9D -- unassigned --
344 Qt::Key_unknown, // 158 0x9E -- unassigned --
345 Qt::Key_unknown, // 159 0x9F -- unassigned --
346 Qt::Key_Shift, // 160 0xA0 VK_LSHIFT | Left Shift key
347 Qt::Key_Shift, // 161 0xA1 VK_RSHIFT | Right Shift key
348 Qt::Key_Control, // 162 0xA2 VK_LCONTROL | Left Ctrl key
349 Qt::Key_Control, // 163 0xA3 VK_RCONTROL | Right Ctrl key
350 Qt::Key_Alt, // 164 0xA4 VK_LMENU | Left Menu key
351 Qt::Key_Alt, // 165 0xA5 VK_RMENU | Right Menu key
352 Qt::Key_Back, // 166 0xA6 VK_BROWSER_BACK | Browser Back key
353 Qt::Key_Forward, // 167 0xA7 VK_BROWSER_FORWARD | Browser Forward key
354 Qt::Key_Refresh, // 168 0xA8 VK_BROWSER_REFRESH | Browser Refresh key
355 Qt::Key_Stop, // 169 0xA9 VK_BROWSER_STOP | Browser Stop key
356 Qt::Key_Search, // 170 0xAA VK_BROWSER_SEARCH | Browser Search key
357 Qt::Key_Favorites, // 171 0xAB VK_BROWSER_FAVORITES| Browser Favorites key
358 Qt::Key_HomePage, // 172 0xAC VK_BROWSER_HOME | Browser Start and Home key
359 Qt::Key_VolumeMute, // 173 0xAD VK_VOLUME_MUTE | Volume Mute key
360 Qt::Key_VolumeDown, // 174 0xAE VK_VOLUME_DOWN | Volume Down key
361 Qt::Key_VolumeUp, // 175 0xAF VK_VOLUME_UP | Volume Up key
362 Qt::Key_MediaNext, // 176 0xB0 VK_MEDIA_NEXT_TRACK | Next Track key
363 Qt::Key_MediaPrevious, //177 0xB1 VK_MEDIA_PREV_TRACK | Previous Track key
364 Qt::Key_MediaStop, // 178 0xB2 VK_MEDIA_STOP | Stop Media key
366 // 179 0xB3 VK_MEDIA_PLAY_PAUSE | Play/Pause Media key
367 Qt::Key_LaunchMail, // 180 0xB4 VK_LAUNCH_MAIL | Start Mail key
368 Qt::Key_LaunchMedia,// 181 0xB5 VK_LAUNCH_MEDIA_SELECT Select Media key
369 Qt::Key_Launch0, // 182 0xB6 VK_LAUNCH_APP1 | Start Application 1 key
370 Qt::Key_Launch1, // 183 0xB7 VK_LAUNCH_APP2 | Start Application 2 key
371 Qt::Key_unknown, // 184 0xB8 -- reserved --
372 Qt::Key_unknown, // 185 0xB9 -- reserved --
373 0, // 186 0xBA VK_OEM_1 | ';:' for US
374 0, // 187 0xBB VK_OEM_PLUS | '+' any country
375 0, // 188 0xBC VK_OEM_COMMA | ',' any country
376 0, // 189 0xBD VK_OEM_MINUS | '-' any country
377 0, // 190 0xBE VK_OEM_PERIOD | '.' any country
378 0, // 191 0xBF VK_OEM_2 | '/?' for US
379 0, // 192 0xC0 VK_OEM_3 | '`~' for US
380 Qt::Key_unknown, // 193 0xC1 -- reserved --
381 Qt::Key_unknown, // 194 0xC2 -- reserved --
382 Qt::Key_unknown, // 195 0xC3 -- reserved --
383 Qt::Key_unknown, // 196 0xC4 -- reserved --
384 Qt::Key_unknown, // 197 0xC5 -- reserved --
385 Qt::Key_unknown, // 198 0xC6 -- reserved --
386 Qt::Key_unknown, // 199 0xC7 -- reserved --
387 Qt::Key_unknown, // 200 0xC8 -- reserved --
388 Qt::Key_unknown, // 201 0xC9 -- reserved --
389 Qt::Key_unknown, // 202 0xCA -- reserved --
390 Qt::Key_unknown, // 203 0xCB -- reserved --
391 Qt::Key_unknown, // 204 0xCC -- reserved --
392 Qt::Key_unknown, // 205 0xCD -- reserved --
393 Qt::Key_unknown, // 206 0xCE -- reserved --
394 Qt::Key_unknown, // 207 0xCF -- reserved --
395 Qt::Key_unknown, // 208 0xD0 -- reserved --
396 Qt::Key_unknown, // 209 0xD1 -- reserved --
397 Qt::Key_unknown, // 210 0xD2 -- reserved --
398 Qt::Key_unknown, // 211 0xD3 -- reserved --
399 Qt::Key_unknown, // 212 0xD4 -- reserved --
400 Qt::Key_unknown, // 213 0xD5 -- reserved --
401 Qt::Key_unknown, // 214 0xD6 -- reserved --
402 Qt::Key_unknown, // 215 0xD7 -- reserved --
403 Qt::Key_unknown, // 216 0xD8 -- unassigned --
404 Qt::Key_unknown, // 217 0xD9 -- unassigned --
405 Qt::Key_unknown, // 218 0xDA -- unassigned --
406 0, // 219 0xDB VK_OEM_4 | '[{' for US
407 0, // 220 0xDC VK_OEM_5 | '\|' for US
408 0, // 221 0xDD VK_OEM_6 | ']}' for US
409 0, // 222 0xDE VK_OEM_7 | ''"' for US
410 0, // 223 0xDF VK_OEM_8
411 Qt::Key_unknown, // 224 0xE0 -- reserved --
412 Qt::Key_unknown, // 225 0xE1 VK_OEM_AX | 'AX' key on Japanese AX kbd
413 Qt::Key_unknown, // 226 0xE2 VK_OEM_102 | "<>" or "\|" on RT 102-key kbd
414 Qt::Key_unknown, // 227 0xE3 VK_ICO_HELP | Help key on ICO
415 Qt::Key_unknown, // 228 0xE4 VK_ICO_00 | 00 key on ICO
416 Qt::Key_unknown, // 229 0xE5 VK_PROCESSKEY | IME Process key
417 Qt::Key_unknown, // 230 0xE6 VK_ICO_CLEAR |
418 Qt::Key_unknown, // 231 0xE7 VK_PACKET | Unicode char as keystrokes
419 Qt::Key_unknown, // 232 0xE8 -- unassigned --
420 // Nokia/Ericsson definitions ---------------
421 Qt::Key_unknown, // 233 0xE9 VK_OEM_RESET
422 Qt::Key_unknown, // 234 0xEA VK_OEM_JUMP
423 Qt::Key_unknown, // 235 0xEB VK_OEM_PA1
424 Qt::Key_unknown, // 236 0xEC VK_OEM_PA2
425 Qt::Key_unknown, // 237 0xED VK_OEM_PA3
426 Qt::Key_unknown, // 238 0xEE VK_OEM_WSCTRL
427 Qt::Key_unknown, // 239 0xEF VK_OEM_CUSEL
428 Qt::Key_unknown, // 240 0xF0 VK_OEM_ATTN
429 Qt::Key_unknown, // 241 0xF1 VK_OEM_FINISH
430 Qt::Key_unknown, // 242 0xF2 VK_OEM_COPY
431 Qt::Key_unknown, // 243 0xF3 VK_OEM_AUTO
432 Qt::Key_unknown, // 244 0xF4 VK_OEM_ENLW
433 Qt::Key_unknown, // 245 0xF5 VK_OEM_BACKTAB
434 Qt::Key_unknown, // 246 0xF6 VK_ATTN | Attn key
435 Qt::Key_unknown, // 247 0xF7 VK_CRSEL | CrSel key
436 Qt::Key_unknown, // 248 0xF8 VK_EXSEL | ExSel key
437 Qt::Key_unknown, // 249 0xF9 VK_EREOF | Erase EOF key
438 Qt::Key_Play, // 250 0xFA VK_PLAY | Play key
439 Qt::Key_Zoom, // 251 0xFB VK_ZOOM | Zoom key
440 Qt::Key_unknown, // 252 0xFC VK_NONAME | Reserved
441 Qt::Key_unknown, // 253 0xFD VK_PA1 | PA1 key
442 Qt::Key_Clear, // 254 0xFE VK_OEM_CLEAR | Clear key
443 0
444};
445
446static const uint CmdTbl[] = { // Multimedia keys mapping table
447 // Dec | Hex | AppCommand
448 Qt::Key_unknown, // 0 0x00
449 Qt::Key_Back, // 1 0x01 APPCOMMAND_BROWSER_BACKWARD
450 Qt::Key_Forward, // 2 0x02 APPCOMMAND_BROWSER_FORWARD
451 Qt::Key_Refresh, // 3 0x03 APPCOMMAND_BROWSER_REFRESH
452 Qt::Key_Stop, // 4 0x04 APPCOMMAND_BROWSER_STOP
453 Qt::Key_Search, // 5 0x05 APPCOMMAND_BROWSER_SEARCH
454 Qt::Key_Favorites, // 6 0x06 APPCOMMAND_BROWSER_FAVORITES
455 Qt::Key_Home, // 7 0x07 APPCOMMAND_BROWSER_HOME
456 Qt::Key_VolumeMute, // 8 0x08 APPCOMMAND_VOLUME_MUTE
457 Qt::Key_VolumeDown, // 9 0x09 APPCOMMAND_VOLUME_DOWN
458 Qt::Key_VolumeUp, // 10 0x0a APPCOMMAND_VOLUME_UP
459 Qt::Key_MediaNext, // 11 0x0b APPCOMMAND_MEDIA_NEXTTRACK
460 Qt::Key_MediaPrevious, // 12 0x0c APPCOMMAND_MEDIA_PREVIOUSTRACK
461 Qt::Key_MediaStop, // 13 0x0d APPCOMMAND_MEDIA_STOP
462 Qt::Key_MediaTogglePlayPause, // 14 0x0e APPCOMMAND_MEDIA_PLAYPAUSE
463 Qt::Key_LaunchMail, // 15 0x0f APPCOMMAND_LAUNCH_MAIL
464 Qt::Key_LaunchMedia, // 16 0x10 APPCOMMAND_LAUNCH_MEDIA_SELECT
465 Qt::Key_Launch0, // 17 0x11 APPCOMMAND_LAUNCH_APP1
466 Qt::Key_Launch1, // 18 0x12 APPCOMMAND_LAUNCH_APP2
467 Qt::Key_BassDown, // 19 0x13 APPCOMMAND_BASS_DOWN
468 Qt::Key_BassBoost, // 20 0x14 APPCOMMAND_BASS_BOOST
469 Qt::Key_BassUp, // 21 0x15 APPCOMMAND_BASS_UP
470 Qt::Key_TrebleDown, // 22 0x16 APPCOMMAND_TREBLE_DOWN
471 Qt::Key_TrebleUp, // 23 0x17 APPCOMMAND_TREBLE_UP
472 Qt::Key_MicMute, // 24 0x18 APPCOMMAND_MICROPHONE_VOLUME_MUTE
473 Qt::Key_MicVolumeDown, // 25 0x19 APPCOMMAND_MICROPHONE_VOLUME_DOWN
474 Qt::Key_MicVolumeUp, // 26 0x1a APPCOMMAND_MICROPHONE_VOLUME_UP
475 Qt::Key_Help, // 27 0x1b APPCOMMAND_HELP
476 Qt::Key_Find, // 28 0x1c APPCOMMAND_FIND
477 Qt::Key_New, // 29 0x1d APPCOMMAND_NEW
478 Qt::Key_Open, // 30 0x1e APPCOMMAND_OPEN
479 Qt::Key_Close, // 31 0x1f APPCOMMAND_CLOSE
480 Qt::Key_Save, // 32 0x20 APPCOMMAND_SAVE
481 Qt::Key_Printer, // 33 0x21 APPCOMMAND_PRINT
482 Qt::Key_Undo, // 34 0x22 APPCOMMAND_UNDO
483 Qt::Key_Redo, // 35 0x23 APPCOMMAND_REDO
484 Qt::Key_Copy, // 36 0x24 APPCOMMAND_COPY
485 Qt::Key_Cut, // 37 0x25 APPCOMMAND_CUT
486 Qt::Key_Paste, // 38 0x26 APPCOMMAND_PASTE
487 Qt::Key_Reply, // 39 0x27 APPCOMMAND_REPLY_TO_MAIL
488 Qt::Key_MailForward, // 40 0x28 APPCOMMAND_FORWARD_MAIL
489 Qt::Key_Send, // 41 0x29 APPCOMMAND_SEND_MAIL
490 Qt::Key_Spell, // 42 0x2a APPCOMMAND_SPELL_CHECK
491 Qt::Key_unknown, // 43 0x2b APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE
492 Qt::Key_unknown, // 44 0x2c APPCOMMAND_MIC_ON_OFF_TOGGLE
493 Qt::Key_unknown, // 45 0x2d APPCOMMAND_CORRECTION_LIST
494 Qt::Key_MediaPlay, // 46 0x2e APPCOMMAND_MEDIA_PLAY
495 Qt::Key_MediaPause, // 47 0x2f APPCOMMAND_MEDIA_PAUSE
496 Qt::Key_MediaRecord, // 48 0x30 APPCOMMAND_MEDIA_RECORD
497 Qt::Key_AudioForward, // 49 0x31 APPCOMMAND_MEDIA_FAST_FORWARD
498 Qt::Key_AudioRewind, // 50 0x32 APPCOMMAND_MEDIA_REWIND
499 Qt::Key_ChannelDown, // 51 0x33 APPCOMMAND_MEDIA_CHANNEL_DOWN
500 Qt::Key_ChannelUp // 52 0x34 APPCOMMAND_MEDIA_CHANNEL_UP
501};
502
503// Possible modifier states.
504// NOTE: The order of these states match the order in QWindowsKeyMapper::updatePossibleKeyCodes()!
505static const Qt::KeyboardModifiers ModsTbl[] = {
506 Qt::NoModifier, // 0
510 Qt::AltModifier, // 4
514 Qt::NoModifier, // Fall-back to raw Key_*
515};
516static const size_t NumMods = sizeof ModsTbl / sizeof *ModsTbl;
517static_assert((NumMods == KeyboardLayoutItem::NumQtKeys));
518
519#ifndef QT_NO_DEBUG_STREAM
521{
522 QDebugStateSaver saver(d);
523 d.nospace();
524 d << "KeyboardLayoutItem(";
525 if (k.exists) {
526 for (size_t i = 0; i < NumMods; ++i) {
527 if (const quint32 qtKey = k.qtKey[i]) {
528 d << '[' << i << ' ';
530 d << ' ' << Qt::hex << Qt::showbase << qtKey << Qt::dec << Qt::noshowbase << ' ';
532 if (qtKey >= 32 && qtKey < 128)
533 d << " '" << char(qtKey) << '\'';
534 if (k.deadkeys & (1<<i))
535 d << " deadkey";
536 d << "] ";
537 }
538 }
539 }
540 d << ')';
541 return d;
542}
543#endif // QT_NO_DEBUG_STREAM
544
549{
550 return KeyTbl[keyCode];
551}
552
553// Translate a VK into a Qt key code, or unicode character
554static inline quint32 toKeyOrUnicode(quint32 vk, quint32 scancode, unsigned char *kbdBuffer, bool *isDeadkey = nullptr)
555{
556 Q_ASSERT(vk > 0 && vk < 256);
557 quint32 code = 0;
558 QChar unicodeBuffer[5];
559 int res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);
560 // When Ctrl modifier is used ToUnicode does not return correct values. In order to assign the
561 // right key the control modifier is removed for just that function if the previous call failed.
562 if (res == 0 && kbdBuffer[VK_CONTROL]) {
563 const unsigned char controlState = kbdBuffer[VK_CONTROL];
564 kbdBuffer[VK_CONTROL] = 0;
565 res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);
566 kbdBuffer[VK_CONTROL] = controlState;
567 }
568 if (res)
569 code = unicodeBuffer[0].toUpper().unicode();
570
571 // Qt::Key_*'s are not encoded below 0x20, so try again, and DEL keys (0x7f) is encoded with a
572 // proper Qt::Key_ code
573 if (code < 0x20 || code == 0x7f) // Handles res==0 too
574 code = winceKeyBend(vk);
575
576 if (isDeadkey)
577 *isDeadkey = (res == -1);
578
579 return code == Qt::Key_unknown ? 0 : code;
580}
581
582static inline int asciiToKeycode(char a, int state)
583{
585 if ((state & Qt::ControlModifier) != 0) {
586 if (a >= 0 && a <= 31) // Ctrl+@..Ctrl+A..CTRL+Z..Ctrl+_
587 a += '@'; // to @..A..Z.._
588 }
589 return a & 0xff;
590}
591
592// Key translation -----------------------------------------------------------------------[ end ]---
593
594
595// Keyboard map private ----------------------------------------------------------------[ start ]---
596
597void QWindowsKeyMapper::deleteLayouts()
598{
599 for (KeyboardLayoutItem &k : keyLayout)
600 k.exists = false;
601}
602
604{
605 deleteLayouts();
606
607 /* MAKELCID()'s first argument is a WORD, and GetKeyboardLayout()
608 * returns a DWORD. */
609
610 LCID newLCID = MAKELCID(quintptr(GetKeyboardLayout(0)), SORT_DEFAULT);
611// keyboardInputLocale = qt_localeFromLCID(newLCID);
612
613 bool bidi = false;
614 wchar_t LCIDFontSig[16];
615 if (GetLocaleInfo(newLCID, LOCALE_FONTSIGNATURE, LCIDFontSig, sizeof(LCIDFontSig) / sizeof(wchar_t))
616 && (LCIDFontSig[7] & wchar_t(0x0800)))
617 bidi = true;
618
619 keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight;
620 m_seenAltGr = false;
621}
622
623// Helper function that is used when obtaining the list of characters that can be produced by one key and
624// every possible combination of modifiers
625inline void setKbdState(unsigned char *kbd, bool shift, bool ctrl, bool alt)
626{
627 kbd[VK_LSHIFT ] = (shift ? 0x80 : 0);
628 kbd[VK_SHIFT ] = (shift ? 0x80 : 0);
629 kbd[VK_LCONTROL] = (ctrl ? 0x80 : 0);
630 kbd[VK_CONTROL ] = (ctrl ? 0x80 : 0);
631 kbd[VK_RMENU ] = (alt ? 0x80 : 0);
632 kbd[VK_MENU ] = (alt ? 0x80 : 0);
633}
634
635// Adds the msg's key to keyLayout if it is not yet present there
636void QWindowsKeyMapper::updateKeyMap(const MSG &msg)
637{
638 unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
639 GetKeyboardState(kbdBuffer);
640 const quint32 scancode = getScancode(msg);
641 updatePossibleKeyCodes(kbdBuffer, scancode, quint32(msg.wParam));
642}
643
644// Fills keyLayout for that vk_key. Values are all characters one can type using that key
645// (in connection with every combination of modifiers) and whether these "characters" are
646// dead keys.
647void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode,
648 quint32 vk_key)
649{
650 if (!vk_key || (keyLayout[vk_key].exists && !keyLayout[vk_key].dirty))
651 return;
652
653 // Copy keyboard state, so we can modify and query output for each possible permutation
654 unsigned char buffer[256];
655 memcpy(buffer, kbdBuffer, sizeof(buffer));
656 // Always 0, as Windows doesn't treat these as modifiers;
657 buffer[VK_LWIN ] = 0;
658 buffer[VK_RWIN ] = 0;
659 buffer[VK_CAPITAL ] = 0;
660 buffer[VK_NUMLOCK ] = 0;
661 buffer[VK_SCROLL ] = 0;
662 // Always 0, since we'll only change the other versions
663 buffer[VK_RSHIFT ] = 0;
664 buffer[VK_RCONTROL] = 0;
665 buffer[VK_LMENU ] = 0; // Use right Alt, since left Ctrl + right Alt is considered AltGraph
666
667 // keyLayout contains the actual characters which can be written using the vk_key together with the
668 // different modifiers. '2' together with shift will for example cause the character
669 // to be @ for a US key layout (thus keyLayout[vk_key].qtKey[1] will be @). In addition to that
670 // it stores whether the resulting key is a dead key as these keys have to be handled later.
671 bool isDeadKey = false;
672 keyLayout[vk_key].deadkeys = 0;
673 keyLayout[vk_key].dirty = false;
674 keyLayout[vk_key].exists = true;
675 setKbdState(buffer, false, false, false);
676 keyLayout[vk_key].qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
677 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x01 : 0;
678 setKbdState(buffer, true, false, false);
679 keyLayout[vk_key].qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
680 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x02 : 0;
681 setKbdState(buffer, false, true, false);
682 keyLayout[vk_key].qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
683 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x04 : 0;
684 setKbdState(buffer, true, true, false);
685 keyLayout[vk_key].qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
686 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x08 : 0;
687 setKbdState(buffer, false, false, true);
688 keyLayout[vk_key].qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
689 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x10 : 0;
690 setKbdState(buffer, true, false, true);
691 keyLayout[vk_key].qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
692 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x20 : 0;
693 setKbdState(buffer, false, true, true);
694 keyLayout[vk_key].qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
695 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x40 : 0;
696 setKbdState(buffer, true, true, true);
697 keyLayout[vk_key].qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
698 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x80 : 0;
699 // Add a fall back key for layouts which don't do composition and show non-latin1 characters
700 quint32 fallbackKey = winceKeyBend(vk_key);
701 if (!fallbackKey || fallbackKey == Qt::Key_unknown) {
702 fallbackKey = 0;
703 if (vk_key != keyLayout[vk_key].qtKey[0] && vk_key != keyLayout[vk_key].qtKey[1]
704 && vk_key < 0x5B && vk_key > 0x2F)
705 fallbackKey = vk_key;
706 }
707 keyLayout[vk_key].qtKey[8] = fallbackKey;
708
709 // If one of the values inserted into the keyLayout above, can be considered a dead key, we have
710 // to run the workaround below.
711 if (keyLayout[vk_key].deadkeys) {
712 // Push a Space, then the original key through the low-level ToAscii functions.
713 // We do this because these functions (ToAscii / ToUnicode) will alter the internal state of
714 // the keyboard driver By doing the following, we set the keyboard driver state back to what
715 // it was before we wrecked it with the code above.
716 // We need to push the space with an empty keystate map, since the driver checks the map for
717 // transitions in modifiers, so this helps us capture all possible deadkeys.
718 unsigned char emptyBuffer[256];
719 memset(emptyBuffer, 0, sizeof(emptyBuffer));
720 ::ToAscii(VK_SPACE, 0, emptyBuffer, reinterpret_cast<LPWORD>(&buffer), 0);
721 ::ToAscii(vk_key, scancode, kbdBuffer, reinterpret_cast<LPWORD>(&buffer), 0);
722 }
723 qCDebug(lcQpaEvents) << __FUNCTION__ << "for virtual key="
724 << Qt::hex << Qt::showbase << vk_key << Qt::dec << Qt::noshowbase << keyLayout[vk_key];
725}
726
727static inline QString messageKeyText(const MSG &msg)
728{
729 const QChar ch = QChar(ushort(msg.wParam));
730 return ch.isNull() ? QString() : QString(ch);
731}
732
733[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
734{
735 const UINT dpi = GetDpiForWindow(hwnd);
736 const int captionHeight = GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
737 if (IsZoomed(hwnd))
738 return captionHeight;
739 // The frame height should also be taken into account if the window
740 // is not maximized.
741 const int frameHeight = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
742 + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
743 return captionHeight + frameHeight;
744}
745
746[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
747{
748 static constexpr const Qt::WindowFlags titleBarHints =
750 return (flags & Qt::WindowSystemMenuHint) && (flags & Qt::WindowTitleHint) && !(flags & titleBarHints)
752}
753
755{
757 HWND topLevelHwnd = QWindowsWindow::handleOf(topLevel);
758 HMENU menu = GetSystemMenu(topLevelHwnd, FALSE);
759 if (!menu)
760 return; // no menu for this window
761
762#define enabled (MF_BYCOMMAND | MFS_ENABLED)
763#define disabled (MF_BYCOMMAND | MFS_GRAYED)
764
765 EnableMenuItem(menu, SC_MINIMIZE, (topLevel->flags() & Qt::WindowMinimizeButtonHint) ? enabled : disabled);
766 const bool maximized = IsZoomed(topLevelHwnd);
767
768 EnableMenuItem(menu, SC_MAXIMIZE, !(topLevel->flags() & Qt::WindowMaximizeButtonHint) || maximized ? disabled : enabled);
769
770 // We should _not_ check with the setFixedSize(x,y) case here, since Windows is not able to check
771 // this and our menu here would be out-of-sync with the menu produced by mouse-click on the
772 // System Menu, or right-click on the title bar.
773 EnableMenuItem(menu, SC_SIZE, (topLevel->flags() & Qt::MSWindowsFixedSizeDialogHint) || maximized ? disabled : enabled);
774 EnableMenuItem(menu, SC_MOVE, maximized ? disabled : enabled);
775 EnableMenuItem(menu, SC_CLOSE, enabled);
776 EnableMenuItem(menu, SC_RESTORE, maximized ? enabled : disabled);
777
778 // Highlight the first entry in the menu, this is what native Win32 applications usually do.
779 HiliteMenuItem(topLevelHwnd, menu, SC_RESTORE, MF_BYCOMMAND | MFS_HILITE);
780
781 // Set bold on close menu item
782 SetMenuDefaultItem(menu, SC_CLOSE, FALSE);
783
784#undef enabled
785#undef disabled
786
787 const QPoint pos = QHighDpi::toNativePixels(topLevel->geometry().topLeft(), topLevel);
788 const int titleBarOffset = isSystemMenuOffsetNeeded(topLevel->flags()) ? getTitleBarHeight(topLevelHwnd) : 0;
789 const int ret = TrackPopupMenuEx(menu,
790 TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
791 pos.x(), pos.y() + titleBarOffset,
792 topLevelHwnd,
793 nullptr);
794
795 // Remove the highlight of the restore menu item, otherwise when the user right-clicks
796 // on the title bar, the popuped system menu will also highlight the restore item, which
797 // is not appropriate, it should only be highlighted if the menu is brought up by keyboard.
798 HiliteMenuItem(topLevelHwnd, menu, SC_RESTORE, MF_BYCOMMAND | MFS_UNHILITE);
799
800 if (ret)
801 qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, WPARAM(ret), 0);
802}
803
804static inline void sendExtendedPressRelease(QWindow *w, unsigned long timestamp, int k,
805 Qt::KeyboardModifiers mods,
806 quint32 nativeScanCode,
807 quint32 nativeVirtualKey,
808 quint32 nativeModifiers,
809 const QString & text = QString(),
810 bool autorep = false,
811 ushort count = 1)
812{
813 QWindowSystemInterface::handleExtendedKeyEvent(w, timestamp, QEvent::KeyPress, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
814 QWindowSystemInterface::handleExtendedKeyEvent(w, timestamp, QEvent::KeyRelease, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
815}
816
822 const MSG &msg, LRESULT *result)
823{
824 *result = 0;
825
826 // Reset layout map when system keyboard layout is changed
827 if (msg.message == WM_INPUTLANGCHANGE) {
829 return true;
830 }
831
832#if defined(WM_APPCOMMAND)
833 if (msg.message == WM_APPCOMMAND)
834 return translateMultimediaKeyEventInternal(widget, msg);
835#endif
836
837 // WM_(IME_)CHAR messages already contain the character in question so there is
838 // no need to fiddle with our key map. In any other case add this key to the
839 // keymap if it is not present yet.
840 if (msg.message != WM_CHAR && msg.message != WM_IME_CHAR)
841 updateKeyMap(msg);
842
843 MSG peekedMsg;
844 // consume dead chars?(for example, typing '`','a' resulting in a-accent).
845 if (PeekMessage(&peekedMsg, hwnd, 0, 0, PM_NOREMOVE) && peekedMsg.message == WM_DEADCHAR)
846 return true;
847
848 return translateKeyEventInternal(widget, msg, false, result);
849}
850
851bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, const MSG &msg)
852{
853#if defined(WM_APPCOMMAND)
854 const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
855 // QTBUG-57198, do not send mouse-synthesized commands as key events in addition
856 bool skipPressRelease = false;
857 switch (GET_DEVICE_LPARAM(msg.lParam)) {
858 case FAPPCOMMAND_MOUSE:
859 return false;
860 case FAPPCOMMAND_KEY:
861 // QTBUG-62838, use WM_KEYDOWN/WM_KEYUP for commands that are reflected
862 // in VK(s) like VK_MEDIA_NEXT_TRACK, to get correct codes and autorepeat.
863 // Don't do that for APPCOMMAND_BROWSER_HOME as that one does not trigger two events.
864 if (cmd != APPCOMMAND_BROWSER_HOME)
865 skipPressRelease = true;
866 break;
867 }
868
869 const int dwKeys = GET_KEYSTATE_LPARAM(msg.lParam);
870 int state = 0;
871 state |= (dwKeys & MK_SHIFT ? int(Qt::ShiftModifier) : 0);
872 state |= (dwKeys & MK_CONTROL ? int(Qt::ControlModifier) : 0);
873
874 QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
875
876 if (cmd < 0 || cmd > 52)
877 return false;
878
879 const int qtKey = int(CmdTbl[cmd]);
880 if (!skipPressRelease)
881 sendExtendedPressRelease(receiver, msg.time, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
882 // QTBUG-43343: Make sure to return false if Qt does not handle the key, otherwise,
883 // the keys are not passed to the active media player.
884# if QT_CONFIG(shortcut)
885 const QKeySequence sequence(Qt::Modifier(state) | Qt::Key(qtKey));
886 return QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(sequence);
887# else
888 return false;
889# endif
890#else
891 Q_UNREACHABLE();
892 return false;
893#endif
894}
895
896// QTBUG-69317: Check for AltGr found on some keyboards
897// which is a sequence of left Ctrl (SYSKEY) + right Menu (Alt).
898static bool isAltGr(MSG *msg)
899{
900 enum : LONG_PTR { RightFlag = 0x1000000 };
901 if (msg->wParam != VK_CONTROL || (msg->lParam & RightFlag) != 0
902 || (msg->message != WM_KEYDOWN && msg->message != WM_SYSKEYUP)) {
903 return false;
904 }
905 const UINT expectedMessage = msg->message == WM_SYSKEYUP
906 ? WM_KEYUP : msg->message;
907 MSG peekedMsg;
908 if (PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_NOREMOVE) == FALSE
909 || peekedMsg.message != expectedMessage || peekedMsg.wParam != VK_MENU
910 || (peekedMsg.lParam & RightFlag) == 0) {
911 return false;
912 }
913 *msg = peekedMsg;
914 PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_REMOVE);
915 return true;
916}
917
918bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
919 bool /* grab */, LRESULT *lResult)
920{
921 const bool altGr = m_detectAltGrModifier && isAltGr(&msg);
922 if (altGr)
923 m_seenAltGr = true;
924 const UINT msgType = msg.message;
925
926 const quint32 scancode = getScancode(msg);
927 auto vk_key = quint32(msg.wParam);
928 quint32 nModifiers = 0;
929
930 QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
931
932 // Map native modifiers to some bit representation
933 nModifiers |= (GetKeyState(VK_LSHIFT ) & 0x80 ? ShiftLeft : 0);
934 nModifiers |= (GetKeyState(VK_RSHIFT ) & 0x80 ? ShiftRight : 0);
935 nModifiers |= (GetKeyState(VK_LCONTROL) & 0x80 ? ControlLeft : 0);
936 nModifiers |= (GetKeyState(VK_RCONTROL) & 0x80 ? ControlRight : 0);
937 nModifiers |= (GetKeyState(VK_LMENU ) & 0x80 ? AltLeft : 0);
938 nModifiers |= (GetKeyState(VK_RMENU ) & 0x80 ? AltRight : 0);
939 nModifiers |= (GetKeyState(VK_LWIN ) & 0x80 ? MetaLeft : 0);
940 nModifiers |= (GetKeyState(VK_RWIN ) & 0x80 ? MetaRight : 0);
941 // Add Lock keys to the same bits
942 nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0);
943 nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0);
944 nModifiers |= (GetKeyState(VK_SCROLL ) & 0x01 ? ScrollLock : 0);
945
946 if (msg.lParam & ExtendedKey)
947 nModifiers |= msg.lParam & ExtendedKey;
948
949 // Get the modifier states (may be altered later, depending on key code)
950 int state = 0;
951 state |= (nModifiers & ShiftAny ? int(Qt::ShiftModifier) : 0);
952 state |= (nModifiers & AltLeft ? int(Qt::AltModifier) : 0);
953 if ((nModifiers & AltRight) != 0)
955 if ((nModifiers & ControlAny) != 0 && (state & Qt::GroupSwitchModifier) == 0)
957 state |= (nModifiers & MetaAny ? int(Qt::MetaModifier) : 0);
958 // A multi-character key or a Input method character
959 // not found by our look-ahead
960 if (msgType == WM_CHAR || msgType == WM_IME_CHAR) {
961 sendExtendedPressRelease(receiver, msg.time, 0, Qt::KeyboardModifier(state), scancode, 0, nModifiers, messageKeyText(msg), false);
962 return true;
963 }
964
965 // Enable Alt accelerators ("&File") on menus
966 if (msgType == WM_SYSKEYDOWN && (nModifiers & AltAny) != 0 && GetMenu(msg.hwnd) != nullptr)
967 return false;
968 if (msgType == WM_SYSKEYUP && nModifiers == 0 && GetMenu(msg.hwnd) != nullptr)
969 return false;
970
971 bool result = false;
972 // handle Directionality changes (BiDi) with RTL extensions
973 if (m_useRTLExtensions) {
974 static int dirStatus = 0;
975 if (!dirStatus && state == Qt::ControlModifier
976 && msg.wParam == VK_CONTROL
977 && msgType == WM_KEYDOWN) {
978 if (GetKeyState(VK_LCONTROL) < 0)
979 dirStatus = VK_LCONTROL;
980 else if (GetKeyState(VK_RCONTROL) < 0)
981 dirStatus = VK_RCONTROL;
982 } else if (dirStatus) {
983 if (msgType == WM_KEYDOWN) {
984 if (msg.wParam == VK_SHIFT) {
985 if (dirStatus == VK_LCONTROL && GetKeyState(VK_LSHIFT) < 0)
986 dirStatus = VK_LSHIFT;
987 else if (dirStatus == VK_RCONTROL && GetKeyState(VK_RSHIFT) < 0)
988 dirStatus = VK_RSHIFT;
989 } else {
990 dirStatus = 0;
991 }
992 } else if (msgType == WM_KEYUP) {
993 if (dirStatus == VK_LSHIFT
994 && ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL))
995 || (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) {
996 sendExtendedPressRelease(receiver, msg.time, Qt::Key_Direction_L, {},
997 scancode, vk_key, nModifiers, QString(), false);
998 result = true;
999 dirStatus = 0;
1000 } else if (dirStatus == VK_RSHIFT
1001 && ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL))
1002 || (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) {
1003 sendExtendedPressRelease(receiver, msg.time, Qt::Key_Direction_R, {},
1004 scancode, vk_key, nModifiers, QString(), false);
1005 result = true;
1006 dirStatus = 0;
1007 } else {
1008 dirStatus = 0;
1009 }
1010 } else {
1011 dirStatus = 0;
1012 }
1013 }
1014 } // RTL
1015
1016 // IME will process these keys, so simply return
1017 if (msg.wParam == VK_PROCESSKEY)
1018 return true;
1019
1020 // Ignore invalid virtual keycodes (see bugs 127424, QTBUG-3630)
1021 if (msg.wParam == 0 || msg.wParam == 0xFF)
1022 return true;
1023
1024 // Translate VK_* (native) -> Key_* (Qt) keys
1025 int modifiersIndex = 0;
1026 modifiersIndex |= (nModifiers & ShiftAny ? 0x1 : 0);
1027 modifiersIndex |= (nModifiers & ControlAny ? 0x2 : 0);
1028 modifiersIndex |= (nModifiers & AltAny ? 0x4 : 0);
1029
1030 // Note: For the resulting key, AltGr is equivalent to Alt + Ctrl (as
1031 // opposed to Linux); hence no entry in KeyboardLayoutItem is required
1032 int code = keyLayout[vk_key].qtKey[modifiersIndex];
1033
1034 // If the bit 24 of lParm is set you received a enter,
1035 // otherwise a Return. (This is the extended key bit)
1036 if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000))
1038 else if (altGr)
1040
1041 // Invert state logic:
1042 // If the key actually pressed is a modifier key, then we remove its modifier key from the
1043 // state, since a modifier-key can't have itself as a modifier
1044 if (code == Qt::Key_Control)
1046 else if (code == Qt::Key_Shift)
1048 else if (code == Qt::Key_Alt)
1050 else if (code == Qt::Key_AltGr)
1052
1053 // All cursor keys without extended bit
1054 if (!(msg.lParam & 0x1000000)) {
1055 switch (code) {
1056 case Qt::Key_Left:
1057 case Qt::Key_Right:
1058 case Qt::Key_Up:
1059 case Qt::Key_Down:
1060 case Qt::Key_PageUp:
1061 case Qt::Key_PageDown:
1062 case Qt::Key_Home:
1063 case Qt::Key_End:
1064 case Qt::Key_Insert:
1065 case Qt::Key_Delete:
1066 case Qt::Key_Asterisk:
1067 case Qt::Key_Plus:
1068 case Qt::Key_Minus:
1069 case Qt::Key_Period:
1070 case Qt::Key_Comma:
1071 case Qt::Key_0:
1072 case Qt::Key_1:
1073 case Qt::Key_2:
1074 case Qt::Key_3:
1075 case Qt::Key_4:
1076 case Qt::Key_5:
1077 case Qt::Key_6:
1078 case Qt::Key_7:
1079 case Qt::Key_8:
1080 case Qt::Key_9:
1081 state |= ((msg.wParam >= '0' && msg.wParam <= '9')
1082 || (msg.wParam >= VK_OEM_PLUS && msg.wParam <= VK_OEM_3))
1083 ? 0 : int(Qt::KeypadModifier);
1084 Q_FALLTHROUGH();
1085 default:
1086 if (uint(msg.lParam) == 0x004c0001 || uint(msg.lParam) == 0xc04c0001)
1088 break;
1089 }
1090 }
1091 // Other keys with with extended bit
1092 else {
1093 switch (code) {
1094 case Qt::Key_Enter:
1095 case Qt::Key_Slash:
1096 case Qt::Key_NumLock:
1098 break;
1099 default:
1100 break;
1101 }
1102 }
1103
1104 // KEYDOWN ---------------------------------------------------------------------------------
1105 if (msgType == WM_KEYDOWN || msgType == WM_IME_KEYDOWN || msgType == WM_SYSKEYDOWN) {
1106 // Get the last record of this key press, so we can validate the current state
1107 // The record is not removed from the list
1108 KeyRecord *rec = key_recorder.findKey(int(msg.wParam), false);
1109
1110 // If rec's state doesn't match the current state, something has changed behind our back
1111 // (Consumed by modal widget is one possibility) So, remove the record from the list
1112 // This will stop the auto-repeat of the key, should a modifier change, for example
1113 if (rec && rec->state != state) {
1114 key_recorder.findKey(int(msg.wParam), true);
1115 rec = nullptr;
1116 }
1117
1118 // Find unicode character from Windows Message Queue
1119 MSG wm_char;
1120 UINT charType = (msgType == WM_KEYDOWN
1121 ? WM_CHAR
1122 : msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR);
1123
1124 QChar uch;
1125 if (PeekMessage(&wm_char, nullptr, charType, charType, PM_REMOVE)) {
1126 if (QWindowsContext::filterNativeEvent(&wm_char, lResult))
1127 return true;
1128 if (receiver && QWindowsContext::filterNativeEvent(receiver, &wm_char, lResult))
1129 return true;
1130 // Found a ?_CHAR
1131 uch = QChar(ushort(wm_char.wParam));
1132 if (uch.isHighSurrogate()) {
1133 m_lastHighSurrogate = uch;
1134 return true;
1135 }
1136 if (uch.isLowSurrogate() && !m_lastHighSurrogate.isNull()) {
1137 if (QObject *focusObject = QGuiApplication::focusObject()) {
1138 const QChar chars[2] = {m_lastHighSurrogate, uch};
1140 event.setCommitString(QString(chars, 2));
1141 QCoreApplication::sendEvent(focusObject, &event);
1142 }
1143 m_lastHighSurrogate = QChar();
1144 return true;
1145 } else {
1146 m_lastHighSurrogate = QChar();
1147 }
1148 if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN))
1149 uch = uch.toLower(); // (See doc of WM_SYSCHAR) Alt-letter
1150 if (!code && !uch.row())
1151 code = asciiToKeycode(char(uch.cell()), state);
1152 }
1153
1154 // Special handling for the WM_IME_KEYDOWN message. Microsoft IME (Korean) will not
1155 // generate a WM_IME_CHAR message corresponding to this message. We might get wrong
1156 // results, if we map this virtual key-code directly (for eg '?' US layouts). So try
1157 // to find the correct key using the current message parameters & keyboard state.
1158 if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
1159 const auto *windowsInputContext =
1160 qobject_cast<const QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
1161 if (!(windowsInputContext && windowsInputContext->isComposing()))
1162 vk_key = ImmGetVirtualKey(reinterpret_cast<HWND>(window->winId()));
1163 BYTE keyState[256];
1164 wchar_t newKey[3] = {0};
1165 GetKeyboardState(keyState);
1166 int val = ToUnicode(vk_key, scancode, keyState, newKey, 2, 0);
1167 if (val == 1) {
1168 uch = QChar(newKey[0]);
1169 } else {
1170 // If we are still not able to find a unicode key, pass the WM_IME_KEYDOWN
1171 // message to DefWindowProc() for generating a proper WM_KEYDOWN.
1172 return false;
1173 }
1174 }
1175
1176 // If no ?_CHAR was found in the queue; deduct character from the ?_KEYDOWN parameters
1177 if (uch.isNull()) {
1178 if (msg.wParam == VK_DELETE) {
1179 uch = QChar(QLatin1Char(0x7f)); // Windows doesn't know this one.
1180 } else {
1181 if (msgType != WM_SYSKEYDOWN || !code) {
1182 UINT map = MapVirtualKey(UINT(msg.wParam), 2);
1183 // If the high bit of the return value is set, it's a deadkey
1184 if (!(map & 0x80000000))
1185 uch = QChar(ushort(map));
1186 }
1187 }
1188 if (!code && !uch.row())
1189 code = asciiToKeycode(char(uch.cell()), state);
1190 }
1191
1192 // Special handling of global Windows hotkeys
1193 if (state == Qt::AltModifier) {
1194 switch (code) {
1195 case Qt::Key_Escape:
1196 case Qt::Key_Tab:
1197 case Qt::Key_F4:
1198 return false; // Send the event on to Windows
1199 case Qt::Key_Space:
1200 // do not pass this key to windows, we will process it ourselves
1201 showSystemMenu(receiver);
1202 return true;
1203 default:
1204 break;
1205 }
1206 }
1207
1208 // Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation
1211
1212 // If we have a record, it means that the key is already pressed, the state is the same
1213 // so, we have an auto-repeating key
1214 if (rec) {
1215 if (code < Qt::Key_Shift || code > Qt::Key_ScrollLock) {
1217 Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text, true);
1219 Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text, true);
1220 result = true;
1221 }
1222 }
1223 // No record of the key being previous pressed, so we now send a QEvent::KeyPress event,
1224 // and store the key data into our records.
1225 else {
1226 const QString text = uch.isNull() ? QString() : QString(uch);
1227 const char a = uch.row() ? char(0) : char(uch.cell());
1228 const Qt::KeyboardModifiers modifiers(state);
1229#ifndef QT_NO_SHORTCUT
1230 // Is Qt interested in the context menu key?
1231 if (modifiers == Qt::SHIFT && code == Qt::Key_F10
1232 && !QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(QKeySequence(Qt::SHIFT | Qt::Key_F10))) {
1233 return false;
1234 }
1235#endif // !QT_NO_SHORTCUT
1236 key_recorder.storeKey(int(msg.wParam), a, state, text);
1237
1238 // QTBUG-71210
1239 // VK_PACKET specifies multiple characters. The system only sends the first
1240 // character of this sequence for each.
1241 if (msg.wParam == VK_PACKET)
1242 code = asciiToKeycode(char(uch.cell()), state);
1243
1245 modifiers, scancode, quint32(msg.wParam), nModifiers, text, false);
1246 result =true;
1247 bool store = true;
1248 // Alt+<alphanumerical> go to the Win32 menu system if unhandled by Qt
1249 if (msgType == WM_SYSKEYDOWN && !result && a) {
1250 HWND parent = GetParent(QWindowsWindow::handleOf(receiver));
1251 while (parent) {
1252 if (GetMenu(parent)) {
1253 SendMessage(parent, WM_SYSCOMMAND, SC_KEYMENU, a);
1254 store = false;
1255 result = true;
1256 break;
1257 }
1258 parent = GetParent(parent);
1259 }
1260 }
1261 if (!store)
1262 key_recorder.findKey(int(msg.wParam), true);
1263 }
1264 }
1265
1266 // KEYUP -----------------------------------------------------------------------------------
1267 else {
1268 // Try to locate the key in our records, and remove it if it exists.
1269 // The key may not be in our records if, for example, the down event was handled by
1270 // win32 natively, or our window gets focus while a key is already press, but now gets
1271 // the key release event.
1272 const KeyRecord *rec = key_recorder.findKey(int(msg.wParam), true);
1273 if (!rec && !(code == Qt::Key_Shift
1274 || code == Qt::Key_Control
1275 || code == Qt::Key_Meta
1276 || code == Qt::Key_Alt)) {
1277
1278 // Workaround for QTBUG-77153:
1279 // The Surface Pen eraser button generates Meta+F18/19/20 keystrokes,
1280 // but when it is not touching the screen the Fn Down is eaten and only
1281 // a Fn Up with the previous state as "not pressed" is generated, which
1282 // would be ignored. We detect this case and synthesize the expected events.
1283 if ((msg.lParam & 0x40000000) == 0 &&
1285 ((code == Qt::Key_F18) || (code == Qt::Key_F19) || (code == Qt::Key_F20))) {
1287 Qt::MetaModifier, scancode,
1288 quint32(msg.wParam), MetaLeft);
1290 Qt::NoModifier, scancode,
1291 quint32(msg.wParam), 0);
1292 result = true;
1293 }
1294 } else {
1295 if (!code)
1296 code = asciiToKeycode(rec->ascii ? char(rec->ascii) : char(msg.wParam), state);
1297
1298 // Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation
1302 Qt::KeyboardModifier(state), scancode, quint32(msg.wParam),
1303 nModifiers,
1304 (rec ? rec->text : QString()), false);
1305 result = true;
1306 // don't pass Alt to Windows unless we are embedded in a non-Qt window
1307 if (code == Qt::Key_Alt) {
1309 HWND parent = GetParent(QWindowsWindow::handleOf(receiver));
1310 while (parent) {
1311 if (!context->findPlatformWindow(parent) && GetMenu(parent)) {
1312 result = false;
1313 break;
1314 }
1315 parent = GetParent(parent);
1316 }
1317 }
1318 }
1319 }
1320 return result;
1321}
1322
1324{
1325 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
1326 if (GetKeyState(VK_SHIFT) < 0)
1328 if (GetKeyState(VK_CONTROL) < 0)
1330 if (GetKeyState(VK_MENU) < 0)
1332 if (GetKeyState(VK_LWIN) < 0 || GetKeyState(VK_RWIN) < 0)
1334 return modifiers;
1335}
1336
1337QList<QKeyCombination> QWindowsKeyMapper::possibleKeyCombinations(const QKeyEvent *e) const
1338{
1339 QList<QKeyCombination> result;
1340
1341
1342 const quint32 nativeVirtualKey = e->nativeVirtualKey();
1343 if (nativeVirtualKey > 255)
1344 return result;
1345
1346 const KeyboardLayoutItem &kbItem = keyLayout[nativeVirtualKey];
1347 if (!kbItem.exists)
1348 return result;
1349
1350 quint32 baseKey = kbItem.qtKey[0];
1351 Qt::KeyboardModifiers keyMods = e->modifiers();
1352 if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
1353 result << (Qt::Key_Enter | keyMods);
1354 return result;
1355 }
1356
1357 // The base key is _always_ valid, of course
1358 result << QKeyCombination::fromCombined(int(baseKey) + int(keyMods));
1359
1360 for (size_t i = 1; i < NumMods; ++i) {
1361 Qt::KeyboardModifiers neededMods = ModsTbl[i];
1362 quint32 key = kbItem.qtKey[i];
1363 if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
1364 const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods;
1365 const auto matchedKey = QKeyCombination::fromCombined(int(key) + int(missingMods));
1366 const auto it = std::find_if(result.begin(), result.end(),
1367 [key](auto keyCombination) {
1368 return keyCombination.key() == key;
1369 });
1370 // QTBUG-67200: Use the match with the least modifiers (prefer
1371 // Shift+9 over Alt + Shift + 9) resulting in more missing modifiers.
1372 if (it == result.end())
1373 result << matchedKey;
1374 else if (missingMods > it->keyboardModifiers())
1375 *it = matchedKey;
1376 }
1377 }
1378 qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey="
1380 << e->modifiers() << kbItem << "\n returns" << result;
1381 return result;
1382}
1383
\inmodule QtCore
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
\inmodule QtCore
\inmodule QtCore
@ KeyRelease
Definition qcoreevent.h:65
@ KeyPress
Definition qcoreevent.h:64
static QGuiApplicationPrivate * instance()
\macro qGuiApp
static QObject * focusObject()
Returns the QObject in currently active window that will be final receiver of events tied to focus,...
void applicationStateChanged(Qt::ApplicationState state)
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:625
static constexpr QKeyCombination fromCombined(int combined)
The QKeyEvent class describes a key event.
Definition qevent.h:424
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
Definition qevent.cpp:1468
quint32 nativeVirtualKey() const
Definition qevent.h:448
quint32 nativeModifiers() const
Definition qevent.h:449
The QKeySequence class encapsulates a key sequence as used by shortcuts.
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
iterator end()
Definition qset.h:140
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:994
QString toUpper() const &
Definition qstring.h:439
const QChar * unicode() const
Returns a Unicode representation of the string.
Definition qstring.h:1230
int x
the x coordinate of the widget relative to its parent including any window frame
Definition qwidget.h:109
static bool handleExtendedKeyEvent(QWindow *window, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString &text=QString(), bool autorep=false, ushort count=1)
\inmodule QtGui
Definition qwindow.h:63
Qt::WindowFlags flags
the window flags of the window
Definition qwindow.h:79
static HWND handleOf(const QWindow *w)
Singleton container for all relevant information.
static QWindowsContext * instance()
static bool filterNativeEvent(MSG *msg, LRESULT *result)
static QWindowsIntegration * instance()
bool translateKeyEvent(QWindow *widget, HWND hwnd, const MSG &msg, LRESULT *result)
To be called from the window procedure.
Qt::KeyboardModifiers queryKeyboardModifiers() const override
QList< QKeyCombination > possibleKeyCombinations(const QKeyEvent *e) const override
static QWindow * topLevelOf(QWindow *w)
EGLImageKHR int int EGLuint64KHR * modifiers
QOpenGLWidget * widget
[1]
QMap< QString, QString > map
[6]
QString text
QSet< QString >::iterator it
else opt state
[0]
T toNativePixels(const T &value, const C *context)
Combined button and popup list for selecting options.
static void formatQEnum(QDebug &debug, QEnum value)
Definition qdebug_p.h:59
static void formatQFlags(QDebug &debug, const QFlags< Enum > &value)
Definition qdebug_p.h:79
constexpr char toAsciiUpper(char ch) noexcept
Definition qtools_p.h:92
Definition qcompare.h:63
@ SHIFT
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
QTextStream & showbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::ShowBase) on stream and r...
@ LeftToRight
@ RightToLeft
QTextStream & noshowbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ShowBase) on stream and ...
@ Key_Escape
Definition qnamespace.h:663
@ Key_BassBoost
Definition qnamespace.h:853
@ Key_AltGr
Definition qnamespace.h:739
@ Key_Favorites
Definition qnamespace.h:866
@ Key_Copy
Definition qnamespace.h:917
@ Key_F20
Definition qnamespace.h:709
@ Key_MediaPrevious
Definition qnamespace.h:860
@ Key_Tab
Definition qnamespace.h:664
@ Key_LaunchMail
Definition qnamespace.h:870
@ Key_Select
@ Key_MailForward
Definition qnamespace.h:961
@ Key_Plus
Definition qnamespace.h:525
@ Key_Shift
Definition qnamespace.h:683
@ Key_Return
Definition qnamespace.h:667
@ Key_9
Definition qnamespace.h:539
@ Key_Right
Definition qnamespace.h:679
@ Key_Enter
Definition qnamespace.h:668
@ Key_F7
Definition qnamespace.h:696
@ Key_PageUp
Definition qnamespace.h:681
@ Key_Printer
@ Key_F22
Definition qnamespace.h:711
@ Key_Execute
@ Key_F23
Definition qnamespace.h:712
@ Key_Cancel
@ Key_Space
Definition qnamespace.h:513
@ Key_ChannelDown
Definition qnamespace.h:997
@ Key_MediaTogglePlayPause
Definition qnamespace.h:864
@ Key_4
Definition qnamespace.h:534
@ Key_2
Definition qnamespace.h:532
@ Key_F24
Definition qnamespace.h:713
@ Key_F17
Definition qnamespace.h:706
@ Key_F21
Definition qnamespace.h:710
@ Key_Open
@ Key_7
Definition qnamespace.h:537
@ Key_Undo
@ Key_8
Definition qnamespace.h:538
@ Key_Backspace
Definition qnamespace.h:666
@ Key_VolumeUp
Definition qnamespace.h:852
@ Key_Backtab
Definition qnamespace.h:665
@ Key_Direction_L
Definition qnamespace.h:731
@ Key_F6
Definition qnamespace.h:695
@ Key_VolumeDown
Definition qnamespace.h:850
@ Key_HomePage
Definition qnamespace.h:865
@ Key_Insert
Definition qnamespace.h:669
@ Key_New
@ Key_Touroku
Definition qnamespace.h:762
@ Key_Left
Definition qnamespace.h:677
@ Key_Cut
Definition qnamespace.h:918
@ Key_MicVolumeDown
@ Key_0
Definition qnamespace.h:530
@ Key_Control
Definition qnamespace.h:684
@ Key_F9
Definition qnamespace.h:698
@ Key_Redo
@ Key_AudioRewind
Definition qnamespace.h:907
@ Key_Alt
Definition qnamespace.h:686
@ Key_VolumeMute
Definition qnamespace.h:851
@ Key_Find
@ Key_F11
Definition qnamespace.h:700
@ Key_ChannelUp
Definition qnamespace.h:996
@ Key_Print
Definition qnamespace.h:672
@ Key_Pause
Definition qnamespace.h:671
@ Key_1
Definition qnamespace.h:531
@ Key_MicVolumeUp
@ Key_Up
Definition qnamespace.h:678
@ Key_Minus
Definition qnamespace.h:527
@ Key_TrebleUp
Definition qnamespace.h:856
@ Key_TrebleDown
Definition qnamespace.h:857
@ Key_F3
Definition qnamespace.h:692
@ Key_F16
Definition qnamespace.h:705
@ Key_Down
Definition qnamespace.h:680
@ Key_F18
Definition qnamespace.h:707
@ Key_LaunchMedia
Definition qnamespace.h:871
@ Key_6
Definition qnamespace.h:536
@ Key_Close
Definition qnamespace.h:916
@ Key_F4
Definition qnamespace.h:693
@ Key_MediaPause
Definition qnamespace.h:863
@ Key_Refresh
Definition qnamespace.h:849
@ Key_Spell
Definition qnamespace.h:946
@ Key_Save
Definition qnamespace.h:944
@ Key_BassUp
Definition qnamespace.h:854
@ Key_F2
Definition qnamespace.h:691
@ Key_Delete
Definition qnamespace.h:670
@ Key_NumLock
Definition qnamespace.h:688
@ Key_Meta
Definition qnamespace.h:685
@ Key_Forward
Definition qnamespace.h:847
@ Key_Launch0
Definition qnamespace.h:872
@ Key_Help
Definition qnamespace.h:730
@ Key_ScrollLock
Definition qnamespace.h:689
@ Key_Send
Definition qnamespace.h:945
@ Key_Sleep
@ Key_MediaRecord
Definition qnamespace.h:862
@ Key_F1
Definition qnamespace.h:690
@ Key_Direction_R
Definition qnamespace.h:732
@ Key_Play
@ Key_3
Definition qnamespace.h:533
@ Key_F14
Definition qnamespace.h:703
@ Key_Slash
Definition qnamespace.h:529
@ Key_Period
Definition qnamespace.h:528
@ Key_Menu
Definition qnamespace.h:727
@ Key_BassDown
Definition qnamespace.h:855
@ Key_PageDown
Definition qnamespace.h:682
@ Key_F19
Definition qnamespace.h:708
@ Key_Launch1
Definition qnamespace.h:873
@ Key_F5
Definition qnamespace.h:694
@ Key_Back
Definition qnamespace.h:846
@ Key_Home
Definition qnamespace.h:675
@ Key_F10
Definition qnamespace.h:699
@ Key_Clear
Definition qnamespace.h:674
@ Key_Massyo
Definition qnamespace.h:763
@ Key_Mode_switch
Definition qnamespace.h:747
@ Key_Comma
Definition qnamespace.h:526
@ Key_MediaStop
Definition qnamespace.h:859
@ Key_F8
Definition qnamespace.h:697
@ Key_F13
Definition qnamespace.h:702
@ Key_CapsLock
Definition qnamespace.h:687
@ Key_Zoom
@ Key_MicMute
Definition qnamespace.h:989
@ Key_MediaPlay
Definition qnamespace.h:858
@ Key_Search
Definition qnamespace.h:867
@ Key_Paste
Definition qnamespace.h:936
@ Key_Asterisk
Definition qnamespace.h:524
@ Key_Stop
Definition qnamespace.h:848
@ Key_5
Definition qnamespace.h:535
@ Key_F12
Definition qnamespace.h:701
@ Key_unknown
@ Key_Reply
Definition qnamespace.h:939
@ Key_F15
Definition qnamespace.h:704
@ Key_AudioForward
Definition qnamespace.h:968
@ Key_MediaNext
Definition qnamespace.h:861
@ Key_End
Definition qnamespace.h:676
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
KeyboardModifier
@ ShiftModifier
@ ControlModifier
@ MetaModifier
@ GroupSwitchModifier
@ KeypadModifier
@ NoModifier
@ AltModifier
ApplicationState
Definition qnamespace.h:262
@ ApplicationInactive
Definition qnamespace.h:265
@ CustomizeWindowHint
Definition qnamespace.h:239
@ FramelessWindowHint
Definition qnamespace.h:225
@ WindowContextHelpButtonHint
Definition qnamespace.h:231
@ MSWindowsFixedSizeDialogHint
Definition qnamespace.h:221
@ WindowMaximizeButtonHint
Definition qnamespace.h:229
@ WindowMinimizeButtonHint
Definition qnamespace.h:228
@ WindowMinMaxButtonsHint
Definition qnamespace.h:230
@ WindowTitleHint
Definition qnamespace.h:226
@ WindowSystemMenuHint
Definition qnamespace.h:227
@ WindowCloseButtonHint
Definition qnamespace.h:241
static void * context
static QT_WARNING_DISABLE_FLOAT_COMPARE ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
Definition qbezier.cpp:207
#define Q_FALLTHROUGH()
#define qWarning
Definition qlogging.h:166
#define qCDebug(category,...)
return ret
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLuint buffer
GLbitfield flags
struct _cl_event * event
GLdouble s
[6]
Definition qopenglext.h:235
GLuint res
const GLubyte * c
GLuint GLfloat * val
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
static QString qtKey(CFStringRef cfkey)
unsigned int quint32
Definition qtypes.h:50
size_t quintptr
Definition qtypes.h:167
unsigned int uint
Definition qtypes.h:34
unsigned short ushort
Definition qtypes.h:33
struct tagMSG MSG
static QWindowsInputContext * windowsInputContext()
LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND, UINT, WPARAM, LPARAM)
static const size_t NumMods
#define enabled
static const uint CmdTbl[]
static bool isAltGr(MSG *msg)
static constexpr quint32 getScancode(const MSG &msg)
static KeyRecorder key_recorder
static int asciiToKeycode(char a, int state)
static const uint KeyTbl[]
#define disabled
#define VK_OEM_PLUS
static int getTitleBarHeight(const HWND hwnd)
QDebug operator<<(QDebug d, const KeyboardLayoutItem &k)
quint32 winceKeyBend(quint32 keyCode)
static void sendExtendedPressRelease(QWindow *w, unsigned long timestamp, int k, Qt::KeyboardModifiers mods, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString &text=QString(), bool autorep=false, ushort count=1)
static QString messageKeyText(const MSG &msg)
static const int QT_MAX_KEY_RECORDINGS
void setKbdState(unsigned char *kbd, bool shift, bool ctrl, bool alt)
static quint32 toKeyOrUnicode(quint32 vk, quint32 scancode, unsigned char *kbdBuffer, bool *isDeadkey=nullptr)
static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state)
static bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
static void showSystemMenu(QWindow *w)
static const Qt::KeyboardModifiers ModsTbl[]
#define VK_OEM_3
@ ScrollLock
@ ExtendedKey
@ ShiftRight
@ AltLeft
@ ShiftLeft
@ MetaRight
@ MetaLeft
@ MetaAny
@ AltRight
@ ControlLeft
@ ControlRight
@ CapsLock
@ NumLock
@ ShiftAny
@ ControlAny
static const Qt::KeyboardModifiers ModsTbl[]
settings remove("monkey")
QObject::connect nullptr
QApplication app(argc, argv)
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QMenu menu
[5]
KeyRecord(int c, int a, int s, const QString &t)
KeyRecord records[QT_MAX_KEY_RECORDINGS]
void storeKey(int code, int ascii, int state, const QString &text)
KeyRecord deleted_record
KeyRecord * findKey(int code, bool remove)
quint32 qtKey[NumQtKeys]
static const size_t NumQtKeys
\inmodule QtCore \reentrant
Definition qchar.h:18