11#include <QtGui/qguiapplication.h>
12#include <QtGui/qwindow.h>
13#include <qpa/qwindowsysteminterface.h>
14#include <private/qguiapplication_p.h>
15#include <private/qhighdpiscaling_p.h>
16#include <QtGui/qevent.h>
17#include <QtGui/private/qwindowsguieventdispatcher_p.h>
18#include <QtCore/private/qdebug_p.h>
19#include <QtCore/private/qtools_p.h>
21#if defined(WM_APPCOMMAND)
22# ifndef FAPPCOMMAND_MOUSE
23# define FAPPCOMMAND_MOUSE 0x8000
25# ifndef FAPPCOMMAND_KEY
26# define FAPPCOMMAND_KEY 0
28# ifndef FAPPCOMMAND_OEM
29# define FAPPCOMMAND_OEM 0x1000
31# ifndef FAPPCOMMAND_MASK
32# define FAPPCOMMAND_MASK 0xF000
34# ifndef GET_APPCOMMAND_LPARAM
35# define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
37# ifndef GET_DEVICE_LPARAM
38# define GET_DEVICE_LPARAM(lParam) ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK))
40# ifndef GET_MOUSEORKEY_LPARAM
41# define GET_MOUSEORKEY_LPARAM GET_DEVICE_LPARAM
43# ifndef GET_FLAGS_LPARAM
44# define GET_FLAGS_LPARAM(lParam) (LOWORD(lParam))
46# ifndef GET_KEYSTATE_LPARAM
47# define GET_KEYSTATE_LPARAM(lParam) GET_FLAGS_LPARAM(lParam)
54
55
56
57
58
59
60
65 : m_useRTLExtensions(
false), m_keyGrabber(
nullptr)
67 memset(keyLayout, 0,
sizeof(keyLayout));
68 auto *app =
static_cast<QGuiApplication *>(QGuiApplication::instance());
69 QObject::connect(app, &QGuiApplication::applicationStateChanged,
70 app, clearKeyRecorderOnApplicationInActive);
77#define LANG_PASHTO 0x63
80#define LANG_SYRIAC 0x5a
83#define LANG_DIVEHI 0x65
86#define VK_OEM_PLUS 0xBB
95 const auto keyFlags = HIWORD(msg.lParam);
96 quint32 scancode = LOBYTE(keyFlags);
99 if ((keyFlags & KF_EXTENDED) != 0)
121 inline void storeKey(
int code,
int ascii,
int state,
const QString& text);
132 if (state == Qt::ApplicationInactive)
139 for (
int i = 0; i <
nrecs; ++i) {
140 if (records[i].code == code) {
142 deleted_record = records[i];
144 while (i + 1 <
nrecs) {
145 records[i] = records[i + 1];
149 result = &deleted_record;
151 result = &records[i];
162 "Internal KeyRecorder",
163 "Keyboard recorder buffer overflow, consider increasing QT_MAX_KEY_RECORDINGS");
166 qWarning(
"Qt: Internal keyboard buffer overflow");
169 records[nrecs++] = KeyRecord(code,ascii,state,text);
364 Qt::Key_MediaPrevious,
366 Qt::Key_MediaTogglePlayPause,
461 Qt::Key_MediaPrevious,
463 Qt::Key_MediaTogglePlayPause,
474 Qt::Key_MicVolumeDown,
498 Qt::Key_AudioForward,
510 Qt::ControlModifier | Qt::ShiftModifier,
512 Qt::AltModifier | Qt::ShiftModifier,
513 Qt::AltModifier | Qt::ControlModifier,
514 Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier,
518static_assert((
NumMods == KeyboardLayoutItem::NumQtKeys));
520#ifndef QT_NO_DEBUG_STREAM
523 QDebugStateSaver saver(d);
525 d <<
"KeyboardLayoutItem(";
527 for (size_t i = 0; i < NumMods; ++i) {
528 if (
const quint32 qtKey = k.qtKey[i]) {
529 d <<
'[' << i <<
' ';
530 QtDebugUtils::formatQFlags(d, ModsTbl[i]);
531 d <<
' ' << Qt::hex << Qt::showbase << qtKey << Qt::dec << Qt::noshowbase <<
' ';
532 QtDebugUtils::formatQEnum(d, Qt::Key(qtKey));
533 if (qtKey >= 32 && qtKey < 128)
534 d <<
" '" <<
char(qtKey) <<
'\'';
535 if (k.deadkeys & (1<<i))
547
548
551 return KeyTbl[keyCode];
555static inline quint32 toKeyOrUnicode(quint32 vk, quint32 scancode,
unsigned char *kbdBuffer,
bool *isDeadkey =
nullptr)
557 Q_ASSERT(vk > 0 && vk < 256);
559 QChar unicodeBuffer[5];
560 int res = ToUnicode(vk, scancode, kbdBuffer,
reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);
563 if (res == 0 && kbdBuffer[VK_CONTROL]) {
564 const unsigned char controlState = kbdBuffer[VK_CONTROL];
565 kbdBuffer[VK_CONTROL] = 0;
566 res = ToUnicode(vk, scancode, kbdBuffer,
reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);
567 kbdBuffer[VK_CONTROL] = controlState;
570 code = unicodeBuffer[0].toUpper().unicode();
574 if (code < 0x20 || code == 0x7f)
575 code = winceKeyBend(vk);
578 *isDeadkey = (res == -1);
580 return code == Qt::Key_unknown ? 0 : code;
585 a = QtMiscUtils::toAsciiUpper(a);
586 if ((state & Qt::ControlModifier) != 0) {
587 if (a >= 0 && a <= 31)
600 for (KeyboardLayoutItem &k : keyLayout)
609
611 LCID newLCID = MAKELCID(quintptr(GetKeyboardLayout(0)), SORT_DEFAULT);
615 wchar_t LCIDFontSig[16];
616 if (GetLocaleInfo(newLCID, LOCALE_FONTSIGNATURE, LCIDFontSig,
sizeof(LCIDFontSig) /
sizeof(
wchar_t))
617 && (LCIDFontSig[7] &
wchar_t(0x0800)))
620 keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight;
626inline void setKbdState(
unsigned char *kbd,
bool shift,
bool ctrl,
bool alt)
628 kbd[VK_LSHIFT ] = (shift ? 0x80 : 0);
629 kbd[VK_SHIFT ] = (shift ? 0x80 : 0);
630 kbd[VK_LCONTROL] = (ctrl ? 0x80 : 0);
631 kbd[VK_CONTROL ] = (ctrl ? 0x80 : 0);
632 kbd[VK_RMENU ] = (alt ? 0x80 : 0);
633 kbd[VK_MENU ] = (alt ? 0x80 : 0);
639 unsigned char kbdBuffer[256];
640 GetKeyboardState(kbdBuffer);
641 const quint32 scancode = getScancode(msg);
642 updatePossibleKeyCodes(kbdBuffer, scancode, quint32(msg.wParam));
648void QWindowsKeyMapper::updatePossibleKeyCodes(
unsigned char *kbdBuffer, quint32 scancode,
651 if (!vk_key || (keyLayout[vk_key].exists && !keyLayout[vk_key].dirty))
655 unsigned char buffer[256];
656 memcpy(buffer, kbdBuffer,
sizeof(buffer));
658 buffer[VK_LWIN ] = 0;
659 buffer[VK_RWIN ] = 0;
660 buffer[VK_CAPITAL ] = 0;
661 buffer[VK_NUMLOCK ] = 0;
662 buffer[VK_SCROLL ] = 0;
664 buffer[VK_RSHIFT ] = 0;
665 buffer[VK_RCONTROL] = 0;
666 buffer[VK_LMENU ] = 0;
672 bool isDeadKey =
false;
673 keyLayout[vk_key].deadkeys = 0;
674 keyLayout[vk_key].dirty =
false;
675 keyLayout[vk_key].exists =
true;
677 keyLayout[vk_key].qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
678 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x01 : 0;
680 keyLayout[vk_key].qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
681 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x02 : 0;
683 keyLayout[vk_key].qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
684 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x04 : 0;
686 keyLayout[vk_key].qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
687 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x08 : 0;
689 keyLayout[vk_key].qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
690 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x10 : 0;
692 keyLayout[vk_key].qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
693 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x20 : 0;
695 keyLayout[vk_key].qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
696 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x40 : 0;
698 keyLayout[vk_key].qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
699 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x80 : 0;
701 quint32 fallbackKey = winceKeyBend(vk_key);
702 if (!fallbackKey || fallbackKey == Qt::Key_unknown) {
704 if (vk_key != keyLayout[vk_key].qtKey[0] && vk_key != keyLayout[vk_key].qtKey[1]
705 && vk_key < 0x5B && vk_key > 0x2F)
706 fallbackKey = vk_key;
708 keyLayout[vk_key].qtKey[8] = fallbackKey;
712 if (keyLayout[vk_key].deadkeys) {
719 unsigned char emptyBuffer[256];
720 memset(emptyBuffer, 0,
sizeof(emptyBuffer));
721 ::ToAscii(VK_SPACE, 0, emptyBuffer,
reinterpret_cast<LPWORD>(&buffer), 0);
722 ::ToAscii(vk_key, scancode, kbdBuffer,
reinterpret_cast<LPWORD>(&buffer), 0);
724 qCDebug(lcQpaEvents) <<
__FUNCTION__ <<
"for virtual key="
725 << Qt::hex << Qt::showbase << vk_key << Qt::dec << Qt::noshowbase << keyLayout[vk_key];
730 const QChar ch = QChar(ushort(msg.wParam));
731 return ch.isNull() ? QString() : QString(ch);
736 const UINT dpi = GetDpiForWindow(hwnd);
737 const int captionHeight = GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
739 return captionHeight;
742 const int frameHeight = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
743 + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
744 return captionHeight + frameHeight;
749 static constexpr const Qt::WindowFlags titleBarHints =
750 Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint;
751 return (flags & Qt::WindowSystemMenuHint) && (flags & Qt::WindowTitleHint) && !(flags & titleBarHints)
752 && (flags & (Qt::FramelessWindowHint | Qt::CustomizeWindowHint));
758 HWND topLevelHwnd = QWindowsWindow::handleOf(topLevel);
759 HMENU menu = GetSystemMenu(topLevelHwnd, FALSE);
763#define enabled (MF_BYCOMMAND | MFS_ENABLED)
764#define disabled (MF_BYCOMMAND | MFS_GRAYED)
766 EnableMenuItem(menu, SC_MINIMIZE, (topLevel->flags() & Qt::WindowMinimizeButtonHint) ?
enabled :
disabled);
767 const bool maximized = IsZoomed(topLevelHwnd);
769 EnableMenuItem(menu, SC_MAXIMIZE, !(topLevel->flags() & Qt::WindowMaximizeButtonHint) || maximized ?
disabled :
enabled);
774 EnableMenuItem(menu, SC_SIZE, (topLevel->flags() & Qt::MSWindowsFixedSizeDialogHint) || maximized ?
disabled :
enabled);
776 EnableMenuItem(menu, SC_CLOSE,
enabled);
780 HiliteMenuItem(topLevelHwnd, menu, SC_RESTORE, MF_BYCOMMAND | MFS_HILITE);
783 SetMenuDefaultItem(menu, SC_CLOSE, FALSE);
788 const QPoint pos = QHighDpi::toNativePixels(topLevel->geometry().topLeft(), topLevel);
789 const int titleBarOffset = isSystemMenuOffsetNeeded(topLevel->flags()) ? getTitleBarHeight(topLevelHwnd) : 0;
790 const int ret = TrackPopupMenuEx(menu,
791 TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
792 pos.x(), pos.y() + titleBarOffset,
799 HiliteMenuItem(topLevelHwnd, menu, SC_RESTORE, MF_BYCOMMAND | MFS_UNHILITE);
802 qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, WPARAM(ret), 0);
806 Qt::KeyboardModifiers mods,
807 quint32 nativeScanCode,
808 quint32 nativeVirtualKey,
809 quint32 nativeModifiers,
810 const QString & text = QString(),
811 bool autorep =
false,
814 QWindowSystemInterface::handleExtendedKeyEvent(w, timestamp, QEvent::KeyPress, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
815 QWindowSystemInterface::handleExtendedKeyEvent(w, timestamp, QEvent::KeyRelease, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
819
820
823 const MSG &msg, LRESULT *result)
828 if (msg.message == WM_INPUTLANGCHANGE) {
833#if defined(WM_APPCOMMAND)
834 if (msg.message == WM_APPCOMMAND)
835 return translateMultimediaKeyEventInternal(widget, msg);
841 if (msg.message != WM_CHAR && msg.message != WM_IME_CHAR)
846 if (PeekMessage(&peekedMsg, hwnd, 0, 0, PM_NOREMOVE) && peekedMsg.message == WM_DEADCHAR)
849 return translateKeyEventInternal(widget, msg,
false, result);
852bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window,
const MSG &msg)
854#if defined(WM_APPCOMMAND)
855 const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
857 bool skipPressRelease =
false;
858 switch (GET_DEVICE_LPARAM(msg.lParam)) {
859 case FAPPCOMMAND_MOUSE:
861 case FAPPCOMMAND_KEY:
865 if (cmd != APPCOMMAND_BROWSER_HOME)
866 skipPressRelease =
true;
870 const int dwKeys = GET_KEYSTATE_LPARAM(msg.lParam);
872 state |= (dwKeys & MK_SHIFT ?
int(Qt::ShiftModifier) : 0);
873 state |= (dwKeys & MK_CONTROL ?
int(Qt::ControlModifier) : 0);
875 QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
877 if (cmd < 0 || cmd > 52)
880 const int qtKey =
int(CmdTbl[cmd]);
881 if (!skipPressRelease)
882 sendExtendedPressRelease(receiver, msg.time, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
885# if QT_CONFIG(shortcut)
886 const QKeySequence sequence(Qt::Modifier(state) | Qt::Key(qtKey));
887 return QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(sequence);
901 enum : LONG_PTR { RightFlag = 0x1000000 };
902 if (msg->wParam != VK_CONTROL || (msg->lParam & RightFlag) != 0
903 || (msg->message != WM_KEYDOWN && msg->message != WM_SYSKEYUP)) {
906 const UINT expectedMessage = msg->message == WM_SYSKEYUP
907 ? WM_KEYUP : msg->message;
909 if (PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_NOREMOVE) == FALSE
910 || peekedMsg.message != expectedMessage || peekedMsg.wParam != VK_MENU
911 || (peekedMsg.lParam & RightFlag) == 0) {
915 PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_REMOVE);
920 bool , LRESULT *lResult)
922 const bool altGr = m_detectAltGrModifier && isAltGr(&msg);
925 const UINT msgType = msg.message;
927 const quint32 scancode = getScancode(msg);
928 auto vk_key = quint32(msg.wParam);
929 quint32 nModifiers = 0;
931 QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
934 nModifiers |= (GetKeyState(VK_LSHIFT ) & 0x80 ?
ShiftLeft : 0);
935 nModifiers |= (GetKeyState(VK_RSHIFT ) & 0x80 ?
ShiftRight : 0);
936 nModifiers |= (GetKeyState(VK_LCONTROL) & 0x80 ?
ControlLeft : 0);
937 nModifiers |= (GetKeyState(VK_RCONTROL) & 0x80 ?
ControlRight : 0);
938 nModifiers |= (GetKeyState(VK_LMENU ) & 0x80 ?
AltLeft : 0);
939 nModifiers |= (GetKeyState(VK_RMENU ) & 0x80 ?
AltRight : 0);
940 nModifiers |= (GetKeyState(VK_LWIN ) & 0x80 ?
MetaLeft : 0);
941 nModifiers |= (GetKeyState(VK_RWIN ) & 0x80 ?
MetaRight : 0);
943 nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ?
CapsLock : 0);
944 nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ?
NumLock : 0);
945 nModifiers |= (GetKeyState(VK_SCROLL ) & 0x01 ?
ScrollLock : 0);
952 state |= (nModifiers & ShiftAny ?
int(Qt::ShiftModifier) : 0);
953 state |= (nModifiers & AltLeft ?
int(Qt::AltModifier) : 0);
954 if ((nModifiers & AltRight) != 0)
955 state |= m_seenAltGr ? Qt::GroupSwitchModifier : Qt::AltModifier;
956 if ((nModifiers & ControlAny) != 0 && (state & Qt::GroupSwitchModifier) == 0)
957 state |= Qt::ControlModifier;
958 state |= (nModifiers & MetaAny ?
int(Qt::MetaModifier) : 0);
961 if (msgType == WM_CHAR || msgType == WM_IME_CHAR) {
962 sendExtendedPressRelease(receiver, msg.time, 0, Qt::KeyboardModifier(state), scancode, 0, nModifiers, messageKeyText(msg),
false);
967 if (msgType == WM_SYSKEYDOWN && (nModifiers & AltAny) != 0 && GetMenu(msg.hwnd) !=
nullptr)
969 if (msgType == WM_SYSKEYUP && nModifiers == 0 && GetMenu(msg.hwnd) !=
nullptr)
974 if (m_useRTLExtensions) {
975 static int dirStatus = 0;
976 if (!dirStatus && state == Qt::ControlModifier
977 && msg.wParam == VK_CONTROL
978 && msgType == WM_KEYDOWN) {
979 if (GetKeyState(VK_LCONTROL) < 0)
980 dirStatus = VK_LCONTROL;
981 else if (GetKeyState(VK_RCONTROL) < 0)
982 dirStatus = VK_RCONTROL;
983 }
else if (dirStatus) {
984 if (msgType == WM_KEYDOWN) {
985 if (msg.wParam == VK_SHIFT) {
986 if (dirStatus == VK_LCONTROL && GetKeyState(VK_LSHIFT) < 0)
987 dirStatus = VK_LSHIFT;
988 else if (dirStatus == VK_RCONTROL && GetKeyState(VK_RSHIFT) < 0)
989 dirStatus = VK_RSHIFT;
993 }
else if (msgType == WM_KEYUP) {
994 if (dirStatus == VK_LSHIFT
995 && ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL))
996 || (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) {
997 sendExtendedPressRelease(receiver, msg.time, Qt::Key_Direction_L, {},
998 scancode, vk_key, nModifiers, QString(),
false);
1001 }
else if (dirStatus == VK_RSHIFT
1002 && ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL))
1003 || (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) {
1004 sendExtendedPressRelease(receiver, msg.time, Qt::Key_Direction_R, {},
1005 scancode, vk_key, nModifiers, QString(),
false);
1018 if (msg.wParam == VK_PROCESSKEY)
1022 if (msg.wParam == 0 || msg.wParam == 0xFF)
1026 int modifiersIndex = 0;
1027 modifiersIndex |= (nModifiers &
ShiftAny ? 0x1 : 0);
1028 modifiersIndex |= (nModifiers &
ControlAny ? 0x2 : 0);
1029 modifiersIndex |= (nModifiers &
AltAny ? 0x4 : 0);
1033 int code = keyLayout[vk_key].qtKey[modifiersIndex];
1037 if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000))
1038 code = Qt::Key_Enter;
1040 code = Qt::Key_AltGr;
1045 if (code == Qt::Key_Control)
1046 state = state ^ Qt::ControlModifier;
1047 else if (code == Qt::Key_Shift)
1048 state = state ^ Qt::ShiftModifier;
1049 else if (code == Qt::Key_Alt)
1050 state = state ^ Qt::AltModifier;
1051 else if (code == Qt::Key_AltGr)
1052 state = state ^ Qt::GroupSwitchModifier;
1055 if (!(msg.lParam & 0x1000000)) {
1061 case Qt::Key_PageUp:
1062 case Qt::Key_PageDown:
1065 case Qt::Key_Insert:
1066 case Qt::Key_Delete:
1067 case Qt::Key_Asterisk:
1070 case Qt::Key_Period:
1082 state |= ((msg.wParam >=
'0' && msg.wParam <=
'9')
1084 ? 0 :
int(Qt::KeypadModifier);
1087 if (uint(msg.lParam) == 0x004c0001 || uint(msg.lParam) == 0xc04c0001)
1088 state |= Qt::KeypadModifier;
1097 case Qt::Key_NumLock:
1098 state |= Qt::KeypadModifier;
1106 if (msgType == WM_KEYDOWN || msgType == WM_IME_KEYDOWN || msgType == WM_SYSKEYDOWN) {
1114 if (rec && rec
->state != state) {
1121 UINT charType = (msgType == WM_KEYDOWN
1123 : msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR);
1126 if (PeekMessage(&wm_char,
nullptr, charType, charType, PM_REMOVE)) {
1127 if (QWindowsContext::filterNativeEvent(&wm_char, lResult))
1129 if (receiver && QWindowsContext::filterNativeEvent(receiver, &wm_char, lResult))
1132 uch = QChar(ushort(wm_char.wParam));
1133 if (uch.isHighSurrogate()) {
1134 m_lastHighSurrogate = uch;
1137 if (uch.isLowSurrogate() && !m_lastHighSurrogate.isNull()) {
1138 if (QObject *focusObject = QGuiApplication::focusObject()) {
1139 const QChar chars[2] = {m_lastHighSurrogate, uch};
1140 QInputMethodEvent event;
1141 event.setCommitString(QString(chars, 2));
1142 QCoreApplication::sendEvent(focusObject, &event);
1144 m_lastHighSurrogate = QChar();
1147 m_lastHighSurrogate = QChar();
1149 if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN))
1150 uch = uch.toLower();
1151 if (!code && !uch.row())
1159 if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
1160 const auto *windowsInputContext =
1162 if (!(windowsInputContext && windowsInputContext->isComposing()))
1163 vk_key = ImmGetVirtualKey(
reinterpret_cast<HWND>(window->winId()));
1165 wchar_t newKey[3] = {0};
1166 GetKeyboardState(keyState);
1167 int val = ToUnicode(vk_key, scancode, keyState, newKey, 2, 0);
1169 uch = QChar(newKey[0]);
1179 if (msg.wParam == VK_DELETE) {
1180 uch = QChar(QLatin1Char(0x7f));
1182 if (msgType != WM_SYSKEYDOWN || !code) {
1183 UINT map = MapVirtualKey(UINT(msg.wParam), 2);
1185 if (!(map & 0x80000000))
1186 uch = QChar(ushort(map));
1189 if (!code && !uch.row())
1194 if (state == Qt::AltModifier) {
1196 case Qt::Key_Escape:
1210 if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
1211 code = Qt::Key_Backtab;
1216 if (code < Qt::Key_Shift || code > Qt::Key_ScrollLock) {
1217 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyRelease, code,
1218 Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text,
true);
1219 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyPress, code,
1220 Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text,
true);
1227 const QString text = uch.isNull() ? QString() : QString(uch);
1228 const char a = uch.row() ?
char(0) :
char(uch.cell());
1229 const Qt::KeyboardModifiers modifiers(state);
1230#ifndef QT_NO_SHORTCUT
1232 if (modifiers == Qt::SHIFT && code == Qt::Key_F10
1233 && !QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(QKeySequence(Qt::SHIFT | Qt::Key_F10))) {
1237 key_recorder.storeKey(
int(msg.wParam), a, state, text);
1242 if (msg.wParam == VK_PACKET)
1245 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyPress, code,
1246 modifiers, scancode, quint32(msg.wParam), nModifiers, text,
false);
1250 if (msgType == WM_SYSKEYDOWN && !result && a) {
1251 HWND parent = GetParent(QWindowsWindow::handleOf(receiver));
1253 if (GetMenu(parent)) {
1254 SendMessage(parent, WM_SYSCOMMAND, SC_KEYMENU, a);
1259 parent = GetParent(parent);
1274 if (!rec && !(code == Qt::Key_Shift
1275 || code == Qt::Key_Control
1276 || code == Qt::Key_Meta
1277 || code == Qt::Key_Alt)) {
1284 if ((msg.lParam & 0x40000000) == 0 &&
1285 Qt::KeyboardModifier(state) == Qt::NoModifier &&
1286 ((code == Qt::Key_F18) || (code == Qt::Key_F19) || (code == Qt::Key_F20))) {
1287 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyPress, code,
1288 Qt::MetaModifier, scancode,
1289 quint32(msg.wParam), MetaLeft);
1290 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyRelease, code,
1291 Qt::NoModifier, scancode,
1292 quint32(msg.wParam), 0);
1300 if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
1301 code = Qt::Key_Backtab;
1302 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyRelease, code,
1303 Qt::KeyboardModifier(state), scancode, quint32(msg.wParam),
1305 (rec ? rec->text : QString()),
false);
1308 if (code == Qt::Key_Alt) {
1310 HWND parent = GetParent(QWindowsWindow::handleOf(receiver));
1316 parent = GetParent(parent);
1326 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
1327 if (GetKeyState(VK_SHIFT) < 0)
1328 modifiers |= Qt::ShiftModifier;
1329 if (GetKeyState(VK_CONTROL) < 0)
1330 modifiers |= Qt::ControlModifier;
1331 if (GetKeyState(VK_MENU) < 0)
1332 modifiers |= Qt::AltModifier;
1333 if (GetKeyState(VK_LWIN) < 0 || GetKeyState(VK_RWIN) < 0)
1334 modifiers |= Qt::MetaModifier;
1340 QList<QKeyCombination> result;
1343 const quint32 nativeVirtualKey = e->nativeVirtualKey();
1344 if (nativeVirtualKey > 255)
1351 quint32 baseKey = kbItem.qtKey[0];
1352 Qt::KeyboardModifiers keyMods = e->modifiers();
1353 if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
1354 result << (Qt::Key_Enter | keyMods);
1360 if (baseKey == Qt::Key_Tab && (keyMods & Qt::ShiftModifier))
1361 result << (Qt::Key_Backtab | (keyMods & ~Qt::ShiftModifier));
1364 result << QKeyCombination::fromCombined(
int(baseKey) +
int(keyMods));
1366 for (size_t i = 1; i < NumMods; ++i) {
1367 Qt::KeyboardModifiers neededMods = ModsTbl[i];
1368 quint32 key = kbItem.qtKey[i];
1369 if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
1370 const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods;
1371 const auto matchedKey = QKeyCombination::fromCombined(
int(key) +
int(missingMods));
1372 const auto it = std::find_if(result.begin(), result.end(),
1373 [key](
auto keyCombination) {
1374 return keyCombination.key() == key;
1378 if (it == result.end())
1379 result << matchedKey;
1380 else if (missingMods > it->keyboardModifiers())
1384 qCDebug(lcQpaEvents) <<
__FUNCTION__ << e <<
"nativeVirtualKey="
1385 << Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase
1386 << e->modifiers() << kbItem <<
"\n returns" << result;
\inmodule QtCore\reentrant
Singleton container for all relevant information.
QWindowsWindow * findPlatformWindow(const QWindowsMenuBar *mb) const
static QWindowsContext * instance()
Windows Input context implementation.
static QWindowsIntegration * instance()
Translates Windows keys to QWindowSystemInterface events.
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
Combined button and popup list for selecting options.
static const Qt::KeyboardModifiers ModsTbl[]
static bool isAltGr(MSG *msg)
static constexpr quint32 getScancode(const MSG &msg)
static int asciiToKeycode(char a, int state)
static const size_t NumMods
static const int QT_MAX_KEY_RECORDINGS
static int getTitleBarHeight(const HWND hwnd)
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)
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 const uint CmdTbl[]
static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state)
static bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
static void showSystemMenu(QWindow *w)
static KeyRecorder key_recorder
static const uint KeyTbl[]
KeyRecord(int c, int a, int s, const QString &t)
void storeKey(int code, int ascii, int state, const QString &text)
KeyRecord * findKey(int code, bool remove)
KeyRecord records[QT_MAX_KEY_RECORDINGS]