diff --git a/COPYING b/COPYING
index 17dfe47553..35cfc1b1ee 100644
--- a/COPYING
+++ b/COPYING
@@ -175,14 +175,12 @@ Files: share/icons/application/scalable/actions/chevron-double-down.svg
share/icons/application/scalable/actions/hammer-wrench.svg
share/icons/application/scalable/actions/health.svg
share/icons/application/scalable/actions/help-about.svg
- share/icons/application/scalable/actions/key-enter.svg
share/icons/application/scalable/actions/lock-question.svg
share/icons/application/scalable/actions/message-close.svg
share/icons/application/scalable/actions/move-down.svg
share/icons/application/scalable/actions/move-up.svg
share/icons/application/scalable/actions/paperclip.svg
share/icons/application/scalable/actions/password-copy.svg
- share/icons/application/scalable/actions/password-generate.svg
share/icons/application/scalable/actions/password-generator.svg
share/icons/application/scalable/actions/password-show-off.svg
share/icons/application/scalable/actions/password-show-on.svg
diff --git a/docs/images/autotype_selection_dialog_type_menu.png b/docs/images/autotype_selection_dialog_type_menu.png
index f0e83ee80f..08fb0f9ee2 100644
Binary files a/docs/images/autotype_selection_dialog_type_menu.png and b/docs/images/autotype_selection_dialog_type_menu.png differ
diff --git a/docs/topics/AutoType.adoc b/docs/topics/AutoType.adoc
index 6d54e34e30..8b60830d9c 100644
--- a/docs/topics/AutoType.adoc
+++ b/docs/topics/AutoType.adoc
@@ -60,6 +60,7 @@ image::autotype_entry_sequences.png[]
|{DELAY X} |Pause typing for X milliseconds
|{CLEARFIELD} |Clear the input field
|{PICKCHARS} |Pick specific password characters from a dialog
+|{MODE=VIRTUAL} |(Experimental) Use virtual key presses on Windows, useful for virtual machines
|===
=== Performing Global Auto-Type
diff --git a/share/icons/application/scalable/actions/key-enter.svg b/share/icons/application/scalable/actions/key-enter.svg
deleted file mode 100644
index 05126f2a36..0000000000
--- a/share/icons/application/scalable/actions/key-enter.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/share/icons/application/scalable/actions/password-generate.svg b/share/icons/application/scalable/actions/password-generate.svg
deleted file mode 100644
index 7192714859..0000000000
--- a/share/icons/application/scalable/actions/password-generate.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/share/icons/icons.qrc b/share/icons/icons.qrc
index 61cbc91033..209a1d35cc 100644
--- a/share/icons/icons.qrc
+++ b/share/icons/icons.qrc
@@ -50,7 +50,6 @@
application/scalable/actions/health.svg
application/scalable/actions/help-about.svg
application/scalable/actions/hibp.svg
- application/scalable/actions/key-enter.svg
application/scalable/actions/lock-question.svg
application/scalable/actions/keyboard-shortcuts.svg
application/scalable/actions/message-close.svg
@@ -60,7 +59,6 @@
application/scalable/actions/object-unlocked.svg
application/scalable/actions/paperclip.svg
application/scalable/actions/password-copy.svg
- application/scalable/actions/password-generate.svg
application/scalable/actions/password-generator.svg
application/scalable/actions/password-show-off.svg
application/scalable/actions/password-show-on.svg
diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index 92d8de75de..155dfa2ff8 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -705,14 +705,6 @@
-
-
-
-
@@ -753,6 +745,19 @@ Ctrl+3 - Type TOTP</p>
+
+
+
+
+
+
+
+
BrowserAccessControlDialog
diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp
index 6038960044..850863e916 100644
--- a/src/autotype/AutoType.cpp
+++ b/src/autotype/AutoType.cpp
@@ -254,7 +254,10 @@ void AutoType::unregisterGlobalShortcut()
/**
* Core Autotype function that will execute actions
*/
-void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, const QString& sequence, WId window)
+void AutoType::executeAutoTypeActions(const Entry* entry,
+ const QString& sequence,
+ WId window,
+ AutoTypeExecutor::Mode mode)
{
QString error;
auto actions = parseSequence(sequence, entry, error);
@@ -274,7 +277,8 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
return;
}
- if (hideWindow) {
+ // Explicitly hide the main window if no target window is specified
+ if (window == 0) {
#if defined(Q_OS_MACOS)
// Check for accessibility permission
if (!macUtils()->enableAccessibility()) {
@@ -289,20 +293,22 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
macUtils()->raiseLastActiveWindow();
m_plugin->hideOwnWindow();
#else
- getMainWindow()->minimizeOrHide();
+ if (getMainWindow()) {
+ getMainWindow()->minimizeOrHide();
+ }
#endif
- }
-
- // Restore window state in case app stole focus
- restoreWindowState();
- QCoreApplication::processEvents();
- m_plugin->raiseWindow(m_windowForGlobal);
-
- // Used only for selected entry auto-type
- if (!window) {
+ QCoreApplication::processEvents();
window = m_plugin->activeWindow();
+ } else {
+ // Restore window state (macOS only) then raise the target window
+ restoreWindowState();
+ QCoreApplication::processEvents();
+ m_plugin->raiseWindow(window);
}
+ // Restore executor mode
+ m_executor->mode = mode;
+
int delay = qMax(100, config()->get(Config::AutoTypeStartDelay).toInt());
Tools::wait(delay);
@@ -346,7 +352,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
* Single Autotype entry-point function
* Look up the Auto-Type sequence for the given entry then perfom Auto-Type in the active window
*/
-void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow)
+void AutoType::performAutoType(const Entry* entry)
{
if (!m_plugin) {
return;
@@ -354,7 +360,7 @@ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow)
auto sequences = entry->autoTypeSequences();
if (!sequences.isEmpty()) {
- executeAutoTypeActions(entry, hideWindow, sequences.first());
+ executeAutoTypeActions(entry, sequences.first());
}
}
@@ -362,13 +368,13 @@ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow)
* Extra Autotype entry-point function
* Perfom Auto-Type of the directly specified sequence in the active window
*/
-void AutoType::performAutoTypeWithSequence(const Entry* entry, const QString& sequence, QWidget* hideWindow)
+void AutoType::performAutoTypeWithSequence(const Entry* entry, const QString& sequence)
{
if (!m_plugin) {
return;
}
- executeAutoTypeActions(entry, hideWindow, sequence);
+ executeAutoTypeActions(entry, sequence);
}
void AutoType::startGlobalAutoType(const QString& search)
@@ -467,12 +473,19 @@ void AutoType::performGlobalAutoType(const QList>& dbLi
}
connect(getMainWindow(), &MainWindow::databaseLocked, selectDialog, &AutoTypeSelectDialog::reject);
- connect(selectDialog, &AutoTypeSelectDialog::matchActivated, this, [this](const AutoTypeMatch& match) {
- m_lastMatch = match;
- m_lastMatchRetypeTimer.start(config()->get(Config::GlobalAutoTypeRetypeTime).toInt() * 1000);
- executeAutoTypeActions(match.first, nullptr, match.second, m_windowForGlobal);
- resetAutoTypeState();
- });
+ connect(selectDialog,
+ &AutoTypeSelectDialog::matchActivated,
+ this,
+ [this](const AutoTypeMatch& match, bool virtualMode) {
+ m_lastMatch = match;
+ m_lastMatchRetypeTimer.start(config()->get(Config::GlobalAutoTypeRetypeTime).toInt() * 1000);
+ executeAutoTypeActions(match.first,
+ match.second,
+ m_windowForGlobal,
+ virtualMode ? AutoTypeExecutor::Mode::VIRTUAL
+ : AutoTypeExecutor::Mode::NORMAL);
+ resetAutoTypeState();
+ });
connect(selectDialog, &QDialog::rejected, this, [this] {
restoreWindowState();
resetAutoTypeState();
@@ -488,7 +501,7 @@ void AutoType::performGlobalAutoType(const QList>& dbLi
selectDialog->activateWindow();
} else if (!matchList.isEmpty()) {
// Only one match and not asking, do it!
- executeAutoTypeActions(matchList.first().first, nullptr, matchList.first().second, m_windowForGlobal);
+ executeAutoTypeActions(matchList.first().first, matchList.first().second, m_windowForGlobal);
resetAutoTypeState();
} else {
// We should never get here
@@ -717,6 +730,12 @@ AutoType::parseSequence(const QString& entrySequence, const Entry* entry, QStrin
error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder);
return {};
}
+ } else if (placeholder.startsWith("mode=")) {
+ auto mode = AutoTypeExecutor::Mode::NORMAL;
+ if (placeholder.endsWith("virtual")) {
+ mode = AutoTypeExecutor::Mode::VIRTUAL;
+ }
+ actions << QSharedPointer::create(mode);
} else if (placeholder == "beep" || placeholder.startsWith("vkey") || placeholder.startsWith("appactivate")
|| placeholder.startsWith("c:")) {
// Ignore these commands
diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h
index 1e09adaf36..5fc07adab2 100644
--- a/src/autotype/AutoType.h
+++ b/src/autotype/AutoType.h
@@ -19,15 +19,15 @@
#ifndef KEEPASSX_AUTOTYPE_H
#define KEEPASSX_AUTOTYPE_H
+#include "AutoTypeAction.h"
+
#include
-#include
#include
#include
+#include "AutoTypeAction.h"
#include "AutoTypeMatch.h"
-class AutoTypeAction;
-class AutoTypeExecutor;
class AutoTypePlatformInterface;
class Database;
class Entry;
@@ -41,8 +41,8 @@ class AutoType : public QObject
QStringList windowTitles();
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers, QString* error = nullptr);
void unregisterGlobalShortcut();
- void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr);
- void performAutoTypeWithSequence(const Entry* entry, const QString& sequence, QWidget* hideWindow = nullptr);
+ void performAutoType(const Entry* entry);
+ void performAutoTypeWithSequence(const Entry* entry, const QString& sequence);
static bool verifyAutoTypeSyntax(const QString& sequence, const Entry* entry, QString& error);
@@ -80,9 +80,9 @@ private slots:
~AutoType() override;
void loadPlugin(const QString& pluginPath);
void executeAutoTypeActions(const Entry* entry,
- QWidget* hideWindow = nullptr,
- const QString& customSequence = QString(),
- WId window = 0);
+ const QString& sequence = QString(),
+ WId window = 0,
+ AutoTypeExecutor::Mode mode = AutoTypeExecutor::Mode::NORMAL);
void restoreWindowState();
void resetAutoTypeState();
diff --git a/src/autotype/AutoTypeAction.cpp b/src/autotype/AutoTypeAction.cpp
index d43ff70025..237d7743fe 100644
--- a/src/autotype/AutoTypeAction.cpp
+++ b/src/autotype/AutoTypeAction.cpp
@@ -65,3 +65,14 @@ AutoTypeAction::Result AutoTypeBegin::exec(AutoTypeExecutor* executor) const
{
return executor->execBegin(this);
}
+
+AutoTypeMode::AutoTypeMode(AutoTypeExecutor::Mode mode)
+ : mode(mode)
+{
+}
+
+AutoTypeAction::Result AutoTypeMode::exec(AutoTypeExecutor* executor) const
+{
+ executor->mode = mode;
+ return AutoTypeAction::Result::Ok();
+}
diff --git a/src/autotype/AutoTypeAction.h b/src/autotype/AutoTypeAction.h
index 48dd29cc9b..082d0aea7d 100644
--- a/src/autotype/AutoTypeAction.h
+++ b/src/autotype/AutoTypeAction.h
@@ -121,13 +121,29 @@ class KEEPASSXC_EXPORT AutoTypeBegin : public AutoTypeAction
class KEEPASSXC_EXPORT AutoTypeExecutor
{
public:
+ enum class Mode
+ {
+ NORMAL,
+ VIRTUAL
+ };
+
virtual ~AutoTypeExecutor() = default;
virtual AutoTypeAction::Result execBegin(const AutoTypeBegin* action) = 0;
virtual AutoTypeAction::Result execType(const AutoTypeKey* action) = 0;
virtual AutoTypeAction::Result execClearField(const AutoTypeClearField* action) = 0;
int execDelayMs = 25;
+ Mode mode = Mode::NORMAL;
QString error;
};
+class KEEPASSXC_EXPORT AutoTypeMode : public AutoTypeAction
+{
+public:
+ AutoTypeMode(AutoTypeExecutor::Mode mode = AutoTypeExecutor::Mode::NORMAL);
+ Result exec(AutoTypeExecutor* executor) const override;
+
+ const AutoTypeExecutor::Mode mode;
+};
+
#endif // KEEPASSX_AUTOTYPEACTION_H
diff --git a/src/autotype/AutoTypeSelectDialog.cpp b/src/autotype/AutoTypeSelectDialog.cpp
index d58e331510..0c8eefdc4a 100644
--- a/src/autotype/AutoTypeSelectDialog.cpp
+++ b/src/autotype/AutoTypeSelectDialog.cpp
@@ -58,6 +58,8 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent)
}
});
+ m_ui->helpButton->setIcon(icons()->icon("system-help"));
+
m_ui->search->installEventFilter(this);
m_searchTimer.setInterval(300);
@@ -118,7 +120,7 @@ void AutoTypeSelectDialog::submitAutoTypeMatch(AutoTypeMatch match)
if (match.first) {
m_accepted = true;
accept();
- emit matchActivated(std::move(match));
+ emit matchActivated(std::move(match), m_virtualMode);
}
}
@@ -274,34 +276,54 @@ void AutoTypeSelectDialog::buildActionMenu()
m_actionMenu->addAction(typeUsernameAction);
m_actionMenu->addAction(typePasswordAction);
m_actionMenu->addAction(typeTotpAction);
+#ifdef Q_OS_WIN
+ auto typeVirtualAction = new QAction(icons()->icon("auto-type"), tr("Use Virtual Keyboard"));
+ m_actionMenu->addAction(typeVirtualAction);
+#endif
m_actionMenu->addAction(copyUsernameAction);
m_actionMenu->addAction(copyPasswordAction);
m_actionMenu->addAction(copyTotpAction);
- auto shortcut = new QShortcut(Qt::CTRL + Qt::Key_1, this);
- connect(shortcut, &QShortcut::activated, typeUsernameAction, &QAction::trigger);
+ typeUsernameAction->setShortcut(Qt::CTRL + Qt::Key_1);
connect(typeUsernameAction, &QAction::triggered, this, [&] {
auto match = m_ui->view->currentMatch();
match.second = "{USERNAME}";
submitAutoTypeMatch(match);
});
- shortcut = new QShortcut(Qt::CTRL + Qt::Key_2, this);
- connect(shortcut, &QShortcut::activated, typePasswordAction, &QAction::trigger);
+ typePasswordAction->setShortcut(Qt::CTRL + Qt::Key_2);
connect(typePasswordAction, &QAction::triggered, this, [&] {
auto match = m_ui->view->currentMatch();
match.second = "{PASSWORD}";
submitAutoTypeMatch(match);
});
- shortcut = new QShortcut(Qt::CTRL + Qt::Key_3, this);
- connect(shortcut, &QShortcut::activated, typeTotpAction, &QAction::trigger);
+ typeTotpAction->setShortcut(Qt::CTRL + Qt::Key_3);
connect(typeTotpAction, &QAction::triggered, this, [&] {
auto match = m_ui->view->currentMatch();
match.second = "{TOTP}";
submitAutoTypeMatch(match);
});
+#ifdef Q_OS_WIN
+ typeVirtualAction->setShortcut(Qt::CTRL + Qt::Key_4);
+ connect(typeVirtualAction, &QAction::triggered, this, [&] {
+ m_virtualMode = true;
+ activateCurrentMatch();
+ });
+#endif
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
+ // Qt 5.10 introduced a new "feature" to hide shortcuts in context menus
+ // Unfortunately, Qt::AA_DontShowShortcutsInContextMenus is broken, have to manually enable them
+ typeUsernameAction->setShortcutVisibleInContextMenu(true);
+ typePasswordAction->setShortcutVisibleInContextMenu(true);
+ typeTotpAction->setShortcutVisibleInContextMenu(true);
+#ifdef Q_OS_WIN
+ typeVirtualAction->setShortcutVisibleInContextMenu(true);
+#endif
+#endif
+
connect(copyUsernameAction, &QAction::triggered, this, [&] {
auto entry = m_ui->view->currentMatch().first;
if (entry) {
diff --git a/src/autotype/AutoTypeSelectDialog.h b/src/autotype/AutoTypeSelectDialog.h
index fec596b344..9c05804106 100644
--- a/src/autotype/AutoTypeSelectDialog.h
+++ b/src/autotype/AutoTypeSelectDialog.h
@@ -45,7 +45,7 @@ class AutoTypeSelectDialog : public QDialog
void setSearchString(const QString& search);
signals:
- void matchActivated(AutoTypeMatch match);
+ void matchActivated(AutoTypeMatch match, bool virtualMode = false);
protected:
bool eventFilter(QObject* obj, QEvent* event) override;
@@ -69,6 +69,7 @@ private slots:
QTimer m_searchTimer;
QPointer m_actionMenu;
+ bool m_virtualMode = false;
bool m_accepted = false;
};
diff --git a/src/autotype/AutoTypeSelectDialog.ui b/src/autotype/AutoTypeSelectDialog.ui
index cac656d608..0c5e3c8c28 100644
--- a/src/autotype/AutoTypeSelectDialog.ui
+++ b/src/autotype/AutoTypeSelectDialog.ui
@@ -43,34 +43,29 @@
-
-
-
-
- 0
- 0
-
+
+
+ PointingHandCursor
-
-
- 14
- 14
-
+
+ Qt::NoFocus
<p>You can use advanced search queries to find any entry in your open databases. The following shortcuts are useful:<br/>
Ctrl+F - Toggle database search<br/>
Ctrl+1 - Type username<br/>
Ctrl+2 - Type password<br/>
-Ctrl+3 - Type TOTP</p>
+Ctrl+3 - Type TOTP<br/>
+Ctrl+4 - Use Virtual Keyboard (Windows Only)</p>
-
-
+
+ QToolButton {
+ border: none;
+ background: none;
+}
-
- :/icons/application/scalable/actions/system-help.svg
-
-
- true
+
+ ?
diff --git a/src/autotype/windows/AutoTypeWindows.cpp b/src/autotype/windows/AutoTypeWindows.cpp
index 894980f83c..9d0467b90a 100644
--- a/src/autotype/windows/AutoTypeWindows.cpp
+++ b/src/autotype/windows/AutoTypeWindows.cpp
@@ -81,67 +81,71 @@ bool AutoTypePlatformWin::raiseWindow(WId window)
//
// Send unicode character to foreground window
//
-void AutoTypePlatformWin::sendChar(const QChar& ch, bool isKeyDown)
+void AutoTypePlatformWin::sendChar(const QChar& ch)
{
- 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;
- }
+ DWORD nativeFlags = KEYEVENTF_UNICODE;
+
+ INPUT in[2];
+ in[0].type = INPUT_KEYBOARD;
+ in[0].ki.wVk = 0;
+ in[0].ki.wScan = ch.unicode();
+ in[0].ki.dwFlags = KEYEVENTF_UNICODE;
+ in[0].ki.time = 0;
+ in[0].ki.dwExtraInfo = ::GetMessageExtraInfo();
+
+ in[1] = in[0];
+ in[1].ki.dwFlags |= 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));
+ ::SendInput(2, &in[0], sizeof(INPUT));
+}
+
+void AutoTypePlatformWin::sendCharVirtual(const QChar& ch)
+{
+ auto vKey = VkKeyScanExW(ch.unicode(), GetKeyboardLayout(0));
+ if (vKey == -1) {
+ // VKey not found, send as Unicode character
+ sendChar(ch);
return;
}
- if (HIBYTE(vkey) & 0x6) {
- sendKey(Qt::Key_AltGr, true);
+ if (HIBYTE(vKey) & 0x6) {
+ setKeyState(Qt::Key_AltGr, true);
} else {
- if (HIBYTE(vkey) & 0x1) {
- sendKey(Qt::Key_Shift, true);
+ if (HIBYTE(vKey) & 0x1) {
+ setKeyState(Qt::Key_Shift, true);
}
- if (HIBYTE(vkey) & 0x2) {
- sendKey(Qt::Key_Control, true);
+ if (HIBYTE(vKey) & 0x2) {
+ setKeyState(Qt::Key_Control, true);
}
- if (HIBYTE(vkey) & 0x4) {
- sendKey(Qt::Key_Alt, true);
+ if (HIBYTE(vKey) & 0x4) {
+ setKeyState(Qt::Key_Alt, true);
}
}
- DWORD flags = KEYEVENTF_SCANCODE;
- if (!isKeyDown) {
- flags |= KEYEVENTF_KEYUP;
- }
+ INPUT in[2];
+ in[0].type = INPUT_KEYBOARD;
+ in[0].ki.wVk = 0;
+ in[0].ki.wScan = MapVirtualKey(LOBYTE(vKey), MAPVK_VK_TO_VSC);
+ in[0].ki.dwFlags = KEYEVENTF_SCANCODE;
+ in[0].ki.time = 0;
+ in[0].ki.dwExtraInfo = ::GetMessageExtraInfo();
- INPUT in;
- in.type = INPUT_KEYBOARD;
- in.ki.wVk = 0;
- in.ki.wScan = MapVirtualKey(LOBYTE(vkey), MAPVK_VK_TO_VSC);
- in.ki.dwFlags = flags;
- in.ki.time = 0;
- in.ki.dwExtraInfo = ::GetMessageExtraInfo();
+ in[1] = in[0];
+ in[1].ki.dwFlags |= KEYEVENTF_KEYUP;
- ::SendInput(1, &in, sizeof(INPUT));
+ ::SendInput(2, &in[0], sizeof(INPUT));
- if (HIBYTE(vkey) & 0x6) {
- sendKey(Qt::Key_AltGr, false);
+ if (HIBYTE(vKey) & 0x6) {
+ setKeyState(Qt::Key_AltGr, false);
} else {
- if (HIBYTE(vkey) & 0x1) {
- sendKey(Qt::Key_Shift, false);
+ if (HIBYTE(vKey) & 0x1) {
+ setKeyState(Qt::Key_Shift, false);
}
- if (HIBYTE(vkey) & 0x2) {
- sendKey(Qt::Key_Control, false);
+ if (HIBYTE(vKey) & 0x2) {
+ setKeyState(Qt::Key_Control, false);
}
- if (HIBYTE(vkey) & 0x4) {
- sendKey(Qt::Key_Alt, false);
+ if (HIBYTE(vKey) & 0x4) {
+ setKeyState(Qt::Key_Alt, false);
}
}
}
@@ -149,14 +153,14 @@ void AutoTypePlatformWin::sendChar(const QChar& ch, bool isKeyDown)
//
// Send virtual key code to foreground window
//
-void AutoTypePlatformWin::sendKey(Qt::Key key, bool isKeyDown)
+void AutoTypePlatformWin::setKeyState(Qt::Key key, bool down)
{
WORD nativeKeyCode = winUtils()->qtToNativeKeyCode(key);
DWORD nativeFlags = KEYEVENTF_SCANCODE;
if (isExtendedKey(nativeKeyCode)) {
nativeFlags |= KEYEVENTF_EXTENDEDKEY;
}
- if (!isKeyDown) {
+ if (!down) {
nativeFlags |= KEYEVENTF_KEYUP;
}
@@ -279,37 +283,40 @@ AutoTypeAction::Result AutoTypeExecutorWin::execBegin(const AutoTypeBegin* actio
AutoTypeAction::Result AutoTypeExecutorWin::execType(const AutoTypeKey* action)
{
if (action->modifiers & Qt::ShiftModifier) {
- m_platform->sendKey(Qt::Key_Shift, true);
+ m_platform->setKeyState(Qt::Key_Shift, true);
}
if (action->modifiers & Qt::ControlModifier) {
- m_platform->sendKey(Qt::Key_Control, true);
+ m_platform->setKeyState(Qt::Key_Control, true);
}
if (action->modifiers & Qt::AltModifier) {
- m_platform->sendKey(Qt::Key_Alt, true);
+ m_platform->setKeyState(Qt::Key_Alt, true);
}
if (action->modifiers & Qt::MetaModifier) {
- m_platform->sendKey(Qt::Key_Meta, true);
+ m_platform->setKeyState(Qt::Key_Meta, true);
}
if (action->key != Qt::Key_unknown) {
- m_platform->sendKey(action->key, true);
- m_platform->sendKey(action->key, false);
+ m_platform->setKeyState(action->key, true);
+ m_platform->setKeyState(action->key, false);
} else {
- m_platform->sendChar(action->character, true);
- m_platform->sendChar(action->character, false);
+ if (mode == Mode::VIRTUAL) {
+ m_platform->sendCharVirtual(action->character);
+ } else {
+ m_platform->sendChar(action->character);
+ }
}
if (action->modifiers & Qt::ShiftModifier) {
- m_platform->sendKey(Qt::Key_Shift, false);
+ m_platform->setKeyState(Qt::Key_Shift, false);
}
if (action->modifiers & Qt::ControlModifier) {
- m_platform->sendKey(Qt::Key_Control, false);
+ m_platform->setKeyState(Qt::Key_Control, false);
}
if (action->modifiers & Qt::AltModifier) {
- m_platform->sendKey(Qt::Key_Alt, false);
+ m_platform->setKeyState(Qt::Key_Alt, false);
}
if (action->modifiers & Qt::MetaModifier) {
- m_platform->sendKey(Qt::Key_Meta, false);
+ m_platform->setKeyState(Qt::Key_Meta, false);
}
Tools::sleep(execDelayMs);
diff --git a/src/autotype/windows/AutoTypeWindows.h b/src/autotype/windows/AutoTypeWindows.h
index 7b3d577d02..29e98ab353 100644
--- a/src/autotype/windows/AutoTypeWindows.h
+++ b/src/autotype/windows/AutoTypeWindows.h
@@ -43,8 +43,9 @@ class AutoTypePlatformWin : public QObject, public AutoTypePlatformInterface
bool raiseWindow(WId window) override;
AutoTypeExecutor* createExecutor() override;
- void sendChar(const QChar& ch, bool isKeyDown);
- void sendKey(Qt::Key key, bool isKeyDown);
+ void sendCharVirtual(const QChar& ch);
+ void sendChar(const QChar& ch);
+ void setKeyState(Qt::Key key, bool down);
private:
static bool isExtendedKey(DWORD nativeKeyCode);
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index 1187138728..864b78c6ed 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -782,9 +782,9 @@ void DatabaseWidget::performAutoType(const QString& sequence)
}
if (sequence.isEmpty()) {
- autoType()->performAutoType(currentEntry, window());
+ autoType()->performAutoType(currentEntry);
} else {
- autoType()->performAutoTypeWithSequence(currentEntry, sequence, window());
+ autoType()->performAutoTypeWithSequence(currentEntry, sequence);
}
}
}
diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp
index 32d0b82253..58ebdea6c8 100644
--- a/src/gui/entry/EditEntryWidget.cpp
+++ b/src/gui/entry/EditEntryWidget.cpp
@@ -220,7 +220,7 @@ void EditEntryWidget::openAutotypeHelp()
void EditEntryWidget::setupAutoType()
{
m_autoTypeUi->setupUi(m_autoTypeWidget);
- addPage(tr("Auto-Type"), icons()->icon("key-enter"), m_autoTypeWidget);
+ addPage(tr("Auto-Type"), icons()->icon("auto-type"), m_autoTypeWidget);
m_autoTypeUi->openHelpButton->setIcon(icons()->icon("system-help"));
diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp
index 32b4b1e499..235ba5a861 100644
--- a/tests/TestAutoType.cpp
+++ b/tests/TestAutoType.cpp
@@ -140,7 +140,7 @@ void TestAutoType::testInternal()
void TestAutoType::testSingleAutoType()
{
- m_autoType->performAutoType(m_entry1, nullptr);
+ m_autoType->performAutoType(m_entry1);
QCOMPARE(m_test->actionCount(), 14);
QCOMPARE(m_test->actionChars(),