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)
66 memset(keyLayout, 0,
sizeof(keyLayout));
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)
161 "Internal KeyRecorder",
162 "Keyboard recorder buffer overflow, consider increasing QT_MAX_KEY_RECORDINGS");
165 qWarning(
"Qt: Internal keyboard buffer overflow");
505static const Qt::KeyboardModifiers
ModsTbl[] = {
519#ifndef QT_NO_DEBUG_STREAM
524 d <<
"KeyboardLayoutItem(";
528 d <<
'[' <<
i <<
' ';
533 d <<
" '" << char(
qtKey) <<
'\'';
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;
573 if (code < 0x20 || code == 0x7f)
577 *isDeadkey = (
res == -1);
586 if (
a >= 0 &&
a <= 31)
597void QWindowsKeyMapper::deleteLayouts()
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)))
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);
636void QWindowsKeyMapper::updateKeyMap(
const MSG &msg)
638 unsigned char kbdBuffer[256];
639 GetKeyboardState(kbdBuffer);
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];
671 bool isDeadKey =
false;
673 keyLayout[vk_key].
dirty =
false;
674 keyLayout[vk_key].
exists =
true;
677 keyLayout[vk_key].
deadkeys |= isDeadKey ? 0x01 : 0;
680 keyLayout[vk_key].
deadkeys |= isDeadKey ? 0x02 : 0;
683 keyLayout[vk_key].
deadkeys |= isDeadKey ? 0x04 : 0;
686 keyLayout[vk_key].
deadkeys |= isDeadKey ? 0x08 : 0;
689 keyLayout[vk_key].
deadkeys |= isDeadKey ? 0x10 : 0;
692 keyLayout[vk_key].
deadkeys |= isDeadKey ? 0x20 : 0;
695 keyLayout[vk_key].
deadkeys |= isDeadKey ? 0x40 : 0;
698 keyLayout[vk_key].
deadkeys |= isDeadKey ? 0x80 : 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;
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="
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 =
758 HMENU
menu = GetSystemMenu(topLevelHwnd, FALSE);
762#define enabled (MF_BYCOMMAND | MFS_ENABLED)
763#define disabled (MF_BYCOMMAND | MFS_GRAYED)
766 const bool maximized = IsZoomed(topLevelHwnd);
779 HiliteMenuItem(topLevelHwnd,
menu, SC_RESTORE, MF_BYCOMMAND | MFS_HILITE);
782 SetMenuDefaultItem(
menu, SC_CLOSE, FALSE);
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);
805 Qt::KeyboardModifiers mods,
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);
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);
876 if (cmd < 0 || cmd > 52)
880 if (!skipPressRelease)
884# if QT_CONFIG(shortcut)
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;
927 auto vk_key =
quint32(msg.wParam);
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);
960 if (msgType == WM_CHAR || msgType == WM_IME_CHAR) {
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;
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)))) {
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)))) {
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];
1054 if (!(msg.lParam & 0x1000000)) {
1081 state |= ((msg.wParam >=
'0' && msg.wParam <=
'9')
1086 if (
uint(msg.lParam) == 0x004c0001 ||
uint(msg.lParam) == 0xc04c0001)
1105 if (msgType == WM_KEYDOWN || msgType == WM_IME_KEYDOWN || msgType == WM_SYSKEYDOWN) {
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)) {
1132 if (uch.isHighSurrogate()) {
1133 m_lastHighSurrogate = uch;
1136 if (uch.isLowSurrogate() && !m_lastHighSurrogate.isNull()) {
1138 const QChar chars[2] = {m_lastHighSurrogate, uch};
1140 event.setCommitString(
QString(chars, 2));
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) {
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) {
1181 if (msgType != WM_SYSKEYDOWN || !code) {
1182 UINT
map = MapVirtualKey(UINT(msg.wParam), 2);
1184 if (!(
map & 0x80000000))
1188 if (!code && !uch.row())
1227 const char a = uch.row() ? char(0) : char(uch.cell());
1229#ifndef QT_NO_SHORTCUT
1241 if (msg.wParam == VK_PACKET)
1249 if (msgType == WM_SYSKEYDOWN && !
result &&
a) {
1252 if (GetMenu(parent)) {
1253 SendMessage(parent, WM_SYSCOMMAND, SC_KEYMENU,
a);
1258 parent = GetParent(parent);
1283 if ((msg.lParam & 0x40000000) == 0 &&
1311 if (!
context->findPlatformWindow(parent) && GetMenu(parent)) {
1315 parent = GetParent(parent);
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)
1339 QList<QKeyCombination>
result;
1343 if (nativeVirtualKey > 255)
1351 Qt::KeyboardModifiers keyMods = e->
modifiers();
1361 Qt::KeyboardModifiers neededMods =
ModsTbl[
i];
1363 if (
key &&
key != baseKey && ((keyMods & neededMods) == neededMods)) {
1364 const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods;
1367 [
key](
auto keyCombination) {
1368 return keyCombination.key() == key;
1374 else if (missingMods >
it->keyboardModifiers())
1378 qCDebug(lcQpaEvents) << __FUNCTION__ << e <<
"nativeVirtualKey="
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.
static QGuiApplicationPrivate * instance()
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)
static constexpr QKeyCombination fromCombined(int combined)
The QKeyEvent class describes a key event.
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
quint32 nativeVirtualKey() const
quint32 nativeModifiers() const
The QKeySequence class encapsulates a key sequence as used by shortcuts.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
\inmodule QtCore\reentrant
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isNull() const
Returns true if this string is null; otherwise returns false.
QString toUpper() const &
const QChar * unicode() const
Returns a Unicode representation of the string.
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)
Qt::WindowFlags flags
the window flags of the window
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
QMap< QString, QString > map
[6]
QSet< QString >::iterator it
T toNativePixels(const T &value, const C *context)
Combined button and popup list for selecting options.
static void formatQEnum(QDebug &debug, QEnum value)
static void formatQFlags(QDebug &debug, const QFlags< Enum > &value)
constexpr char toAsciiUpper(char ch) noexcept
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...
QTextStream & noshowbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ShowBase) on stream and ...
@ Key_MediaTogglePlayPause
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
@ WindowContextHelpButtonHint
@ MSWindowsFixedSizeDialogHint
@ WindowMaximizeButtonHint
@ WindowMinimizeButtonHint
@ WindowMinMaxButtonsHint
static QT_WARNING_DISABLE_FLOAT_COMPARE ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
#define qCDebug(category,...)
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
GLenum GLenum GLsizei const GLuint GLboolean enabled
#define Q_ASSERT_X(cond, x, msg)
static QString qtKey(CFStringRef cfkey)
static QWindowsInputContext * windowsInputContext()
LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND, UINT, WPARAM, LPARAM)
static const size_t NumMods
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[]
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[]
static const Qt::KeyboardModifiers ModsTbl[]
settings remove("monkey")
QApplication app(argc, argv)
[0]
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 * findKey(int code, bool remove)
static const size_t NumQtKeys
\inmodule QtCore \reentrant