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>
20#if defined(WM_APPCOMMAND)
21# ifndef FAPPCOMMAND_MOUSE
22# define FAPPCOMMAND_MOUSE 0x8000
24# ifndef FAPPCOMMAND_KEY
25# define FAPPCOMMAND_KEY 0
27# ifndef FAPPCOMMAND_OEM
28# define FAPPCOMMAND_OEM 0x1000
30# ifndef FAPPCOMMAND_MASK
31# define FAPPCOMMAND_MASK 0xF000
33# ifndef GET_APPCOMMAND_LPARAM
34# define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
36# ifndef GET_DEVICE_LPARAM
37# define GET_DEVICE_LPARAM(lParam) ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK))
39# ifndef GET_MOUSEORKEY_LPARAM
40# define GET_MOUSEORKEY_LPARAM GET_DEVICE_LPARAM
42# ifndef GET_FLAGS_LPARAM
43# define GET_FLAGS_LPARAM(lParam) (LOWORD(lParam))
45# ifndef GET_KEYSTATE_LPARAM
46# define GET_KEYSTATE_LPARAM(lParam) GET_FLAGS_LPARAM(lParam)
53
54
55
56
57
58
59
64 : m_useRTLExtensions(
false), m_keyGrabber(
nullptr)
66 memset(keyLayout, 0,
sizeof(keyLayout));
67 auto *app =
static_cast<QGuiApplication *>(QGuiApplication::instance());
68 QObject::connect(app, &QGuiApplication::applicationStateChanged,
69 app, clearKeyRecorderOnApplicationInActive);
76#define LANG_PASHTO 0x63
79#define LANG_SYRIAC 0x5a
82#define LANG_DIVEHI 0x65
85#define VK_OEM_PLUS 0xBB
94 const auto keyFlags = HIWORD(msg.lParam);
95 quint32 scancode = LOBYTE(keyFlags);
98 if ((keyFlags & KF_EXTENDED) != 0)
120 inline void storeKey(
int code,
int ascii,
int state,
const QString& text);
131 if (state == Qt::ApplicationInactive)
138 for (
int i = 0; i <
nrecs; ++i) {
139 if (records[i].code == code) {
141 deleted_record = records[i];
143 while (i + 1 <
nrecs) {
144 records[i] = records[i + 1];
148 result = &deleted_record;
150 result = &records[i];
161 "Internal KeyRecorder",
162 "Keyboard recorder buffer overflow, consider increasing QT_MAX_KEY_RECORDINGS");
165 qWarning(
"Qt: Internal keyboard buffer overflow");
168 records[nrecs++] = KeyRecord(code,ascii,state,text);
363 Qt::Key_MediaPrevious,
365 Qt::Key_MediaTogglePlayPause,
460 Qt::Key_MediaPrevious,
462 Qt::Key_MediaTogglePlayPause,
473 Qt::Key_MicVolumeDown,
497 Qt::Key_AudioForward,
509 Qt::ControlModifier | Qt::ShiftModifier,
511 Qt::AltModifier | Qt::ShiftModifier,
512 Qt::AltModifier | Qt::ControlModifier,
513 Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier,
517static_assert((
NumMods == KeyboardLayoutItem::NumQtKeys));
519#ifndef QT_NO_DEBUG_STREAM
522 QDebugStateSaver saver(d);
524 d <<
"KeyboardLayoutItem(";
526 for (size_t i = 0; i < NumMods; ++i) {
527 if (
const quint32 qtKey = k.qtKey[i]) {
528 d <<
'[' << i <<
' ';
529 QtDebugUtils::formatQFlags(d, ModsTbl[i]);
530 d <<
' ' << Qt::hex << Qt::showbase << qtKey << Qt::dec << Qt::noshowbase <<
' ';
531 QtDebugUtils::formatQEnum(d, Qt::Key(qtKey));
532 if (qtKey >= 32 && qtKey < 128)
533 d <<
" '" <<
char(qtKey) <<
'\'';
534 if (k.deadkeys & (1<<i))
546
547
550 return KeyTbl[keyCode];
554static inline quint32 toKeyOrUnicode(quint32 vk, quint32 scancode,
unsigned char *kbdBuffer,
bool *isDeadkey =
nullptr)
556 Q_ASSERT(vk > 0 && vk < 256);
558 QChar unicodeBuffer[5];
559 int res = ToUnicode(vk, scancode, kbdBuffer,
reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);
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;
569 code = unicodeBuffer[0].toUpper().unicode();
573 if (code < 0x20 || code == 0x7f)
574 code = winceKeyBend(vk);
577 *isDeadkey = (res == -1);
579 return code == Qt::Key_unknown ? 0 : code;
584 a = QtMiscUtils::toAsciiUpper(a);
585 if ((state & Qt::ControlModifier) != 0) {
586 if (a >= 0 && a <= 31)
599 for (KeyboardLayoutItem &k : keyLayout)
608
610 LCID newLCID = MAKELCID(quintptr(GetKeyboardLayout(0)), SORT_DEFAULT);
614 wchar_t LCIDFontSig[16];
615 if (GetLocaleInfo(newLCID, LOCALE_FONTSIGNATURE, LCIDFontSig,
sizeof(LCIDFontSig) /
sizeof(
wchar_t))
616 && (LCIDFontSig[7] &
wchar_t(0x0800)))
619 keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight;
625inline void setKbdState(
unsigned char *kbd,
bool shift,
bool ctrl,
bool alt)
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);
638 unsigned char kbdBuffer[256];
639 GetKeyboardState(kbdBuffer);
640 const quint32 scancode = getScancode(msg);
641 updatePossibleKeyCodes(kbdBuffer, scancode, quint32(msg.wParam));
647void QWindowsKeyMapper::updatePossibleKeyCodes(
unsigned char *kbdBuffer, quint32 scancode,
650 if (!vk_key || (keyLayout[vk_key].exists && !keyLayout[vk_key].dirty))
654 unsigned char buffer[256];
655 memcpy(buffer, kbdBuffer,
sizeof(buffer));
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;
663 buffer[VK_RSHIFT ] = 0;
664 buffer[VK_RCONTROL] = 0;
665 buffer[VK_LMENU ] = 0;
671 bool isDeadKey =
false;
672 keyLayout[vk_key].deadkeys = 0;
673 keyLayout[vk_key].dirty =
false;
674 keyLayout[vk_key].exists =
true;
676 keyLayout[vk_key].qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
677 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x01 : 0;
679 keyLayout[vk_key].qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
680 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x02 : 0;
682 keyLayout[vk_key].qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
683 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x04 : 0;
685 keyLayout[vk_key].qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
686 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x08 : 0;
688 keyLayout[vk_key].qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
689 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x10 : 0;
691 keyLayout[vk_key].qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
692 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x20 : 0;
694 keyLayout[vk_key].qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
695 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x40 : 0;
697 keyLayout[vk_key].qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
698 keyLayout[vk_key].deadkeys |= isDeadKey ? 0x80 : 0;
700 quint32 fallbackKey = winceKeyBend(vk_key);
701 if (!fallbackKey || fallbackKey == Qt::Key_unknown) {
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;
707 keyLayout[vk_key].qtKey[8] = fallbackKey;
711 if (keyLayout[vk_key].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);
723 qCDebug(lcQpaEvents) <<
__FUNCTION__ <<
"for virtual key="
724 << Qt::hex << Qt::showbase << vk_key << Qt::dec << Qt::noshowbase << keyLayout[vk_key];
729 const QChar ch = QChar(ushort(msg.wParam));
730 return ch.isNull() ? QString() : QString(ch);
735 const UINT dpi = GetDpiForWindow(hwnd);
736 const int captionHeight = GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
738 return captionHeight;
741 const int frameHeight = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
742 + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
743 return captionHeight + frameHeight;
748 static constexpr const Qt::WindowFlags titleBarHints =
749 Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint;
750 return (flags & Qt::WindowSystemMenuHint) && (flags & Qt::WindowTitleHint) && !(flags & titleBarHints)
751 && (flags & (Qt::FramelessWindowHint | Qt::CustomizeWindowHint));
757 HWND topLevelHwnd = QWindowsWindow::handleOf(topLevel);
758 HMENU menu = GetSystemMenu(topLevelHwnd, FALSE);
762#define enabled (MF_BYCOMMAND | MFS_ENABLED)
763#define disabled (MF_BYCOMMAND | MFS_GRAYED)
765 EnableMenuItem(menu, SC_MINIMIZE, (topLevel->flags() & Qt::WindowMinimizeButtonHint) ?
enabled :
disabled);
766 const bool maximized = IsZoomed(topLevelHwnd);
768 EnableMenuItem(menu, SC_MAXIMIZE, !(topLevel->flags() & Qt::WindowMaximizeButtonHint) || maximized ?
disabled :
enabled);
773 EnableMenuItem(menu, SC_SIZE, (topLevel->flags() & Qt::MSWindowsFixedSizeDialogHint) || maximized ?
disabled :
enabled);
775 EnableMenuItem(menu, SC_CLOSE,
enabled);
779 HiliteMenuItem(topLevelHwnd, menu, SC_RESTORE, MF_BYCOMMAND | MFS_HILITE);
782 SetMenuDefaultItem(menu, SC_CLOSE, FALSE);
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,
798 HiliteMenuItem(topLevelHwnd, menu, SC_RESTORE, MF_BYCOMMAND | MFS_UNHILITE);
801 qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, WPARAM(ret), 0);
805 Qt::KeyboardModifiers mods,
806 quint32 nativeScanCode,
807 quint32 nativeVirtualKey,
808 quint32 nativeModifiers,
809 const QString & text = QString(),
810 bool autorep =
false,
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);
818
819
822 const MSG &msg, LRESULT *result)
827 if (msg.message == WM_INPUTLANGCHANGE) {
832#if defined(WM_APPCOMMAND)
833 if (msg.message == WM_APPCOMMAND)
834 return translateMultimediaKeyEventInternal(widget, msg);
840 if (msg.message != WM_CHAR && msg.message != WM_IME_CHAR)
845 if (PeekMessage(&peekedMsg, hwnd, 0, 0, PM_NOREMOVE) && peekedMsg.message == WM_DEADCHAR)
848 return translateKeyEventInternal(widget, msg,
false, result);
851bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window,
const MSG &msg)
853#if defined(WM_APPCOMMAND)
854 const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
856 bool skipPressRelease =
false;
857 switch (GET_DEVICE_LPARAM(msg.lParam)) {
858 case FAPPCOMMAND_MOUSE:
860 case FAPPCOMMAND_KEY:
864 if (cmd != APPCOMMAND_BROWSER_HOME)
865 skipPressRelease =
true;
869 const int dwKeys = GET_KEYSTATE_LPARAM(msg.lParam);
871 state |= (dwKeys & MK_SHIFT ?
int(Qt::ShiftModifier) : 0);
872 state |= (dwKeys & MK_CONTROL ?
int(Qt::ControlModifier) : 0);
874 QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
876 if (cmd < 0 || cmd > 52)
879 const int qtKey =
int(CmdTbl[cmd]);
880 if (!skipPressRelease)
881 sendExtendedPressRelease(receiver, msg.time, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
884# if QT_CONFIG(shortcut)
885 const QKeySequence sequence(Qt::Modifier(state) | Qt::Key(qtKey));
886 return QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(sequence);
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)) {
905 const UINT expectedMessage = msg->message == WM_SYSKEYUP
906 ? WM_KEYUP : msg->message;
908 if (PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_NOREMOVE) == FALSE
909 || peekedMsg.message != expectedMessage || peekedMsg.wParam != VK_MENU
910 || (peekedMsg.lParam & RightFlag) == 0) {
914 PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_REMOVE);
919 bool , LRESULT *lResult)
921 const bool altGr = m_detectAltGrModifier && isAltGr(&msg);
924 const UINT msgType = msg.message;
926 const quint32 scancode = getScancode(msg);
927 auto vk_key = quint32(msg.wParam);
928 quint32 nModifiers = 0;
930 QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
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);
942 nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0);
943 nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0);
944 nModifiers |= (GetKeyState(VK_SCROLL ) & 0x01 ? ScrollLock : 0);
951 state |= (nModifiers & ShiftAny ?
int(Qt::ShiftModifier) : 0);
952 state |= (nModifiers & AltLeft ?
int(Qt::AltModifier) : 0);
953 if ((nModifiers & AltRight) != 0)
954 state |= m_seenAltGr ? Qt::GroupSwitchModifier : Qt::AltModifier;
955 if ((nModifiers & ControlAny) != 0 && (state & Qt::GroupSwitchModifier) == 0)
956 state |= Qt::ControlModifier;
957 state |= (nModifiers & MetaAny ?
int(Qt::MetaModifier) : 0);
960 if (msgType == WM_CHAR || msgType == WM_IME_CHAR) {
961 sendExtendedPressRelease(receiver, msg.time, 0, Qt::KeyboardModifier(state), scancode, 0, nModifiers, messageKeyText(msg),
false);
966 if (msgType == WM_SYSKEYDOWN && (nModifiers & AltAny) != 0 && GetMenu(msg.hwnd) !=
nullptr)
968 if (msgType == WM_SYSKEYUP && nModifiers == 0 && GetMenu(msg.hwnd) !=
nullptr)
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;
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);
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);
1017 if (msg.wParam == VK_PROCESSKEY)
1021 if (msg.wParam == 0 || msg.wParam == 0xFF)
1025 int modifiersIndex = 0;
1026 modifiersIndex |= (nModifiers &
ShiftAny ? 0x1 : 0);
1027 modifiersIndex |= (nModifiers &
ControlAny ? 0x2 : 0);
1028 modifiersIndex |= (nModifiers &
AltAny ? 0x4 : 0);
1032 int code = keyLayout[vk_key].qtKey[modifiersIndex];
1036 if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000))
1037 code = Qt::Key_Enter;
1039 code = Qt::Key_AltGr;
1044 if (code == Qt::Key_Control)
1045 state = state ^ Qt::ControlModifier;
1046 else if (code == Qt::Key_Shift)
1047 state = state ^ Qt::ShiftModifier;
1048 else if (code == Qt::Key_Alt)
1049 state = state ^ Qt::AltModifier;
1050 else if (code == Qt::Key_AltGr)
1051 state = state ^ Qt::GroupSwitchModifier;
1054 if (!(msg.lParam & 0x1000000)) {
1060 case Qt::Key_PageUp:
1061 case Qt::Key_PageDown:
1064 case Qt::Key_Insert:
1065 case Qt::Key_Delete:
1066 case Qt::Key_Asterisk:
1069 case Qt::Key_Period:
1081 state |= ((msg.wParam >=
'0' && msg.wParam <=
'9')
1083 ? 0 :
int(Qt::KeypadModifier);
1086 if (uint(msg.lParam) == 0x004c0001 || uint(msg.lParam) == 0xc04c0001)
1087 state |= Qt::KeypadModifier;
1096 case Qt::Key_NumLock:
1097 state |= Qt::KeypadModifier;
1105 if (msgType == WM_KEYDOWN || msgType == WM_IME_KEYDOWN || msgType == WM_SYSKEYDOWN) {
1113 if (rec && rec
->state != state) {
1120 UINT charType = (msgType == WM_KEYDOWN
1122 : msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR);
1125 if (PeekMessage(&wm_char,
nullptr, charType, charType, PM_REMOVE)) {
1126 if (QWindowsContext::filterNativeEvent(&wm_char, lResult))
1128 if (receiver && QWindowsContext::filterNativeEvent(receiver, &wm_char, lResult))
1131 uch = QChar(ushort(wm_char.wParam));
1132 if (uch.isHighSurrogate()) {
1133 m_lastHighSurrogate = uch;
1136 if (uch.isLowSurrogate() && !m_lastHighSurrogate.isNull()) {
1137 if (QObject *focusObject = QGuiApplication::focusObject()) {
1138 const QChar chars[2] = {m_lastHighSurrogate, uch};
1139 QInputMethodEvent event;
1140 event.setCommitString(QString(chars, 2));
1141 QCoreApplication::sendEvent(focusObject, &event);
1143 m_lastHighSurrogate = QChar();
1146 m_lastHighSurrogate = QChar();
1148 if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN))
1149 uch = uch.toLower();
1150 if (!code && !uch.row())
1158 if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
1159 const auto *windowsInputContext =
1161 if (!(windowsInputContext && windowsInputContext->isComposing()))
1162 vk_key = ImmGetVirtualKey(
reinterpret_cast<HWND>(window->winId()));
1164 wchar_t newKey[3] = {0};
1165 GetKeyboardState(keyState);
1166 int val = ToUnicode(vk_key, scancode, keyState, newKey, 2, 0);
1168 uch = QChar(newKey[0]);
1178 if (msg.wParam == VK_DELETE) {
1179 uch = QChar(QLatin1Char(0x7f));
1181 if (msgType != WM_SYSKEYDOWN || !code) {
1182 UINT map = MapVirtualKey(UINT(msg.wParam), 2);
1184 if (!(map & 0x80000000))
1185 uch = QChar(ushort(map));
1188 if (!code && !uch.row())
1193 if (state == Qt::AltModifier) {
1195 case Qt::Key_Escape:
1209 if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
1210 code = Qt::Key_Backtab;
1215 if (code < Qt::Key_Shift || code > Qt::Key_ScrollLock) {
1216 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyRelease, code,
1217 Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text,
true);
1218 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyPress, code,
1219 Qt::KeyboardModifier(state), scancode, quint32(msg.wParam), nModifiers, rec->text,
true);
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
1231 if (modifiers == Qt::SHIFT && code == Qt::Key_F10
1232 && !QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(QKeySequence(Qt::SHIFT | Qt::Key_F10))) {
1236 key_recorder.storeKey(
int(msg.wParam), a, state, text);
1241 if (msg.wParam == VK_PACKET)
1244 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyPress, code,
1245 modifiers, scancode, quint32(msg.wParam), nModifiers, text,
false);
1249 if (msgType == WM_SYSKEYDOWN && !result && a) {
1250 HWND parent = GetParent(QWindowsWindow::handleOf(receiver));
1252 if (GetMenu(parent)) {
1253 SendMessage(parent, WM_SYSCOMMAND, SC_KEYMENU, a);
1258 parent = GetParent(parent);
1273 if (!rec && !(code == Qt::Key_Shift
1274 || code == Qt::Key_Control
1275 || code == Qt::Key_Meta
1276 || code == Qt::Key_Alt)) {
1283 if ((msg.lParam & 0x40000000) == 0 &&
1284 Qt::KeyboardModifier(state) == Qt::NoModifier &&
1285 ((code == Qt::Key_F18) || (code == Qt::Key_F19) || (code == Qt::Key_F20))) {
1286 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyPress, code,
1287 Qt::MetaModifier, scancode,
1288 quint32(msg.wParam), MetaLeft);
1289 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyRelease, code,
1290 Qt::NoModifier, scancode,
1291 quint32(msg.wParam), 0);
1299 if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
1300 code = Qt::Key_Backtab;
1301 QWindowSystemInterface::handleExtendedKeyEvent(receiver, msg.time, QEvent::KeyRelease, code,
1302 Qt::KeyboardModifier(state), scancode, quint32(msg.wParam),
1304 (rec ? rec->text : QString()),
false);
1307 if (code == Qt::Key_Alt) {
1309 HWND parent = GetParent(QWindowsWindow::handleOf(receiver));
1315 parent = GetParent(parent);
1325 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
1326 if (GetKeyState(VK_SHIFT) < 0)
1327 modifiers |= Qt::ShiftModifier;
1328 if (GetKeyState(VK_CONTROL) < 0)
1329 modifiers |= Qt::ControlModifier;
1330 if (GetKeyState(VK_MENU) < 0)
1331 modifiers |= Qt::AltModifier;
1332 if (GetKeyState(VK_LWIN) < 0 || GetKeyState(VK_RWIN) < 0)
1333 modifiers |= Qt::MetaModifier;
1339 QList<QKeyCombination> result;
1342 const quint32 nativeVirtualKey = e->nativeVirtualKey();
1343 if (nativeVirtualKey > 255)
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);
1359 if (baseKey == Qt::Key_Tab && (keyMods & Qt::ShiftModifier))
1360 result << (Qt::Key_Backtab | (keyMods & ~Qt::ShiftModifier));
1363 result << QKeyCombination::fromCombined(
int(baseKey) +
int(keyMods));
1365 for (size_t i = 1; i < NumMods; ++i) {
1366 Qt::KeyboardModifiers neededMods = ModsTbl[i];
1367 quint32 key = kbItem.qtKey[i];
1368 if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
1369 const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods;
1370 const auto matchedKey = QKeyCombination::fromCombined(
int(key) +
int(missingMods));
1371 const auto it = std::find_if(result.begin(), result.end(),
1372 [key](
auto keyCombination) {
1373 return keyCombination.key() == key;
1377 if (it == result.end())
1378 result << matchedKey;
1379 else if (missingMods > it->keyboardModifiers())
1383 qCDebug(lcQpaEvents) <<
__FUNCTION__ << e <<
"nativeVirtualKey="
1384 << Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase
1385 << 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
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]