Skip to content

Commit

Permalink
Fix Windows Auto-Type sending characters to virtualized guests
Browse files Browse the repository at this point in the history
* Fix #1833
  • Loading branch information
droidmonkey committed Feb 9, 2022
1 parent 5927821 commit 1150b69
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 122 deletions.
58 changes: 47 additions & 11 deletions src/autotype/windows/AutoTypeWindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,32 +83,68 @@ bool AutoTypePlatformWin::raiseWindow(WId window)
//
void AutoTypePlatformWin::sendChar(const QChar& ch, bool isKeyDown)
{
DWORD nativeFlags = KEYEVENTF_UNICODE;
auto vkey = VkKeyScanExW(ch.unicode(), GetKeyboardLayout(0));
if (vkey == -1) {
// VKey not found, send as Unicode character
DWORD flags = KEYEVENTF_UNICODE;
if (!isKeyDown) {
flags |= KEYEVENTF_KEYUP;
}

INPUT in;
in.type = INPUT_KEYBOARD;
in.ki.wVk = 0;
in.ki.wScan = ch.unicode();
in.ki.dwFlags = flags;
in.ki.time = 0;
in.ki.dwExtraInfo = ::GetMessageExtraInfo();
::SendInput(1, &in, sizeof(INPUT));
return;
}

if (HIBYTE(vkey) & 0x1) {
sendKey(Qt::Key_Shift, true);
}
if (HIBYTE(vkey) & 0x2) {
sendKey(Qt::Key_Control, true);
}
if (HIBYTE(vkey) & 0x4) {
sendKey(Qt::Key_Alt, true);
}

DWORD flags = KEYEVENTF_SCANCODE;
if (!isKeyDown) {
nativeFlags |= KEYEVENTF_KEYUP;
flags |= KEYEVENTF_KEYUP;
}

INPUT in;
in.type = INPUT_KEYBOARD;
in.ki.wVk = 0;
in.ki.wScan = ch.unicode();
in.ki.dwFlags = nativeFlags;
in.ki.wScan = MapVirtualKey(LOBYTE(vkey), MAPVK_VK_TO_VSC);
in.ki.dwFlags = flags;
in.ki.time = 0;
in.ki.dwExtraInfo = ::GetMessageExtraInfo();

::SendInput(1, &in, sizeof(INPUT));

if (HIBYTE(vkey) & 0x1) {
sendKey(Qt::Key_Shift, false);
}
if (HIBYTE(vkey) & 0x2) {
sendKey(Qt::Key_Control, false);
}
if (HIBYTE(vkey) & 0x4) {
sendKey(Qt::Key_Alt, false);
}
}

//
// Send virtual key code to foreground window
//
void AutoTypePlatformWin::sendKey(Qt::Key key, bool isKeyDown)
{
DWORD nativeKeyCode = winUtils()->qtToNativeKeyCode(key);
if (nativeKeyCode < 1 || nativeKeyCode > 254) {
return;
}
DWORD nativeFlags = 0;
WORD nativeKeyCode = winUtils()->qtToNativeKeyCode(key);
DWORD nativeFlags = KEYEVENTF_SCANCODE;
if (isExtendedKey(nativeKeyCode)) {
nativeFlags |= KEYEVENTF_EXTENDEDKEY;
}
Expand All @@ -118,8 +154,8 @@ void AutoTypePlatformWin::sendKey(Qt::Key key, bool isKeyDown)

INPUT in;
in.type = INPUT_KEYBOARD;
in.ki.wVk = LOWORD(nativeKeyCode);
in.ki.wScan = LOWORD(::MapVirtualKeyW(nativeKeyCode, MAPVK_VK_TO_VSC));
in.ki.wVk = 0;
in.ki.wScan = MapVirtualKey(LOBYTE(nativeKeyCode), MAPVK_VK_TO_VSC);
in.ki.dwFlags = nativeFlags;
in.ki.time = 0;
in.ki.dwExtraInfo = ::GetMessageExtraInfo();
Expand Down
112 changes: 2 additions & 110 deletions src/gui/osutils/winutils/WinUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ void WinUtils::triggerGlobalShortcut(int id)
// Translate qt key code to windows virtual key code
// see: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
//
DWORD WinUtils::qtToNativeKeyCode(Qt::Key key)
WORD WinUtils::qtToNativeKeyCode(Qt::Key key)
{
switch (key) {
case Qt::Key_Backspace:
Expand Down Expand Up @@ -266,80 +266,6 @@ DWORD WinUtils::qtToNativeKeyCode(Qt::Key key)
case Qt::Key_Help:
return VK_HELP; // 0x2F

case Qt::Key_0:
return 0x30; // 0x30
case Qt::Key_1:
return 0x31; // 0x31
case Qt::Key_2:
return 0x32; // 0x32
case Qt::Key_3:
return 0x33; // 0x33
case Qt::Key_4:
return 0x34; // 0x34
case Qt::Key_5:
return 0x35; // 0x35
case Qt::Key_6:
return 0x36; // 0x36
case Qt::Key_7:
return 0x37; // 0x37
case Qt::Key_8:
return 0x38; // 0x38
case Qt::Key_9:
return 0x39; // 0x39

case Qt::Key_A:
return 0x41; // 0x41
case Qt::Key_B:
return 0x42; // 0x42
case Qt::Key_C:
return 0x43; // 0x43
case Qt::Key_D:
return 0x44; // 0x44
case Qt::Key_E:
return 0x45; // 0x45
case Qt::Key_F:
return 0x46; // 0x46
case Qt::Key_G:
return 0x47; // 0x47
case Qt::Key_H:
return 0x48; // 0x48
case Qt::Key_I:
return 0x49; // 0x49
case Qt::Key_J:
return 0x4A; // 0x4A
case Qt::Key_K:
return 0x4B; // 0x4B
case Qt::Key_L:
return 0x4C; // 0x4C
case Qt::Key_M:
return 0x4D; // 0x4D
case Qt::Key_N:
return 0x4E; // 0x4E
case Qt::Key_O:
return 0x4F; // 0x4F
case Qt::Key_P:
return 0x50; // 0x50
case Qt::Key_Q:
return 0x51; // 0x51
case Qt::Key_R:
return 0x52; // 0x52
case Qt::Key_S:
return 0x53; // 0x53
case Qt::Key_T:
return 0x54; // 0x54
case Qt::Key_U:
return 0x55; // 0x55
case Qt::Key_V:
return 0x56; // 0x56
case Qt::Key_W:
return 0x57; // 0x57
case Qt::Key_X:
return 0x58; // 0x58
case Qt::Key_Y:
return 0x59; // 0x59
case Qt::Key_Z:
return 0x5A; // 0x5A

case Qt::Key_F1:
return VK_F1; // 0x70
case Qt::Key_F2:
Expand Down Expand Up @@ -394,42 +320,8 @@ DWORD WinUtils::qtToNativeKeyCode(Qt::Key key)
case Qt::Key_ScrollLock:
return VK_SCROLL; // 0x91

case Qt::Key_Exclam: // !
case Qt::Key_QuoteDbl: // "
case Qt::Key_NumberSign: // #
case Qt::Key_Dollar: // $
case Qt::Key_Percent: // %
case Qt::Key_Ampersand: // &
case Qt::Key_Apostrophe: // '
case Qt::Key_ParenLeft: // (
case Qt::Key_ParenRight: // )
case Qt::Key_Asterisk: // *
case Qt::Key_Plus: // +
case Qt::Key_Comma: // ,
case Qt::Key_Minus: // -
case Qt::Key_Period: // .
case Qt::Key_Slash: // /
case Qt::Key_Colon: // :
case Qt::Key_Semicolon: // ;
case Qt::Key_Less: // <
case Qt::Key_Equal: // =
case Qt::Key_Greater: // >
case Qt::Key_Question: // ?
case Qt::Key_BracketLeft: // [
case Qt::Key_Backslash: // '\'
case Qt::Key_BracketRight: // ]
case Qt::Key_AsciiCircum: // ^
case Qt::Key_Underscore: // _
case Qt::Key_QuoteLeft: // `
case Qt::Key_BraceLeft: // {
case Qt::Key_Bar: // |
case Qt::Key_BraceRight: // }
case Qt::Key_AsciiTilde: // ~
return LOBYTE(::VkKeyScanExW(key, ::GetKeyboardLayout(0)));

default:
Q_ASSERT(false);
return 0;
return LOBYTE(::VkKeyScanExW(key, ::GetKeyboardLayout(0)));
}
}
// clang-format on
Expand Down
2 changes: 1 addition & 1 deletion src/gui/osutils/winutils/WinUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class WinUtils : public OSUtilsBase, QAbstractNativeEventFilter
QString* error = nullptr) override;
bool unregisterGlobalShortcut(const QString& name) override;

DWORD qtToNativeKeyCode(Qt::Key key);
WORD qtToNativeKeyCode(Qt::Key key);
DWORD qtToNativeModifiers(Qt::KeyboardModifiers modifiers);

bool canPreventScreenCapture() const override;
Expand Down

0 comments on commit 1150b69

Please sign in to comment.