summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Shaw <andy.shaw@qt.io>2018-04-17 16:45:09 +0200
committerAndy Shaw <andy.shaw@qt.io>2018-04-20 10:18:49 +0000
commit7c532891e0be2cf78c89738e175b3d312d305e4e (patch)
treee7afb2e9e1360effe004fdf31fa5497c18d14eca
parent941db4e0bb3170b6bc3cf775f150a226754e6285 (diff)
Send ShortcutOverride event when receiving a non-spontaneous key press
When a key press is received which is not spontaneous then it needs to be manually sent as a shortcut override event to ensure that any matching shortcut is triggered first. This enables emulation/playback of recorded events to still have the same effect. [ChangeLog][QtWidgets] Sending a key press event with sendEvent() now sends a ShortCutOverride event first to the widget to trigger any shortcuts set first. Task-number: QTBUG-48325 Change-Id: Iafcc2cdb1773bffe89edaeb0abc44cd5a51088e6 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
-rw-r--r--src/widgets/kernel/qapplication.cpp16
-rw-r--r--tests/auto/widgets/kernel/qaction/tst_qaction.cpp37
2 files changed, 51 insertions, 2 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 0d434c7097..404bebd40c 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -130,6 +130,7 @@ QT_BEGIN_NAMESPACE
}
Q_CORE_EXPORT void qt_call_post_routines();
+Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1);
QApplicationPrivate *QApplicationPrivate::self = 0;
@@ -3068,8 +3069,19 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
switch (e->type()) {
case QEvent::KeyPress: {
- int key = static_cast<QKeyEvent*>(e)->key();
- qt_in_tab_key_event = (key == Qt::Key_Backtab
+ QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e);
+ const int key = keyEvent->key();
+ // When a key press is received which is not spontaneous then it needs to
+ // be manually sent as a shortcut override event to ensure that any
+ // matching shortcut is triggered first. This enables emulation/playback
+ // of recorded events to still have the same effect.
+ if (!e->spontaneous() && receiver->isWidgetType()) {
+ if (qt_sendShortcutOverrideEvent(qobject_cast<QWidget *>(receiver), keyEvent->timestamp(),
+ key, keyEvent->modifiers(), keyEvent->text(),
+ keyEvent->isAutoRepeat(), keyEvent->count()))
+ return true;
+ }
+ qt_in_tab_key_event = (key == Qt::Key_Backtab
|| key == Qt::Key_Tab
|| key == Qt::Key_Left
|| key == Qt::Key_Up
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
index ddf9ccb416..3d68e42baf 100644
--- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -67,6 +67,7 @@ private slots:
void keysequence(); // QTBUG-53381
void disableShortcutsWithBlockedWidgets_data();
void disableShortcutsWithBlockedWidgets();
+ void shortcutFromKeyEvent(); // QTBUG-48325
private:
int m_lastEventType;
@@ -509,5 +510,41 @@ void tst_QAction::disableShortcutsWithBlockedWidgets()
QCOMPARE(spy.count(), 0);
}
+class ShortcutOverrideWidget : public QWidget
+{
+public:
+ ShortcutOverrideWidget(QWidget *parent = 0) : QWidget(parent), shortcutOverrideCount(0) {}
+ int shortcutOverrideCount;
+protected:
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::ShortcutOverride)
+ ++shortcutOverrideCount;
+ return QWidget::event(e);
+ }
+};
+
+// Test that a key press event sent with sendEvent() still gets handled as a possible
+// ShortcutOverride event first before passing it on as a normal KeyEvent.
+void tst_QAction::shortcutFromKeyEvent()
+{
+ ShortcutOverrideWidget testWidget;
+ QAction action;
+ action.setShortcut(Qt::Key_1);
+ testWidget.addAction(&action);
+ testWidget.show();
+ QSignalSpy spy(&action, &QAction::triggered);
+ QVERIFY(spy.isValid());
+ QVERIFY(QTest::qWaitForWindowActive(&testWidget));
+ QCOMPARE(testWidget.shortcutOverrideCount, 0);
+
+ // Don't use the QTest::keyPress approach as this will take the
+ // shortcut route for us
+ QKeyEvent e(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier);
+ QApplication::sendEvent(&testWidget, &e);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(testWidget.shortcutOverrideCount, 1);
+}
+
QTEST_MAIN(tst_QAction)
#include "tst_qaction.moc"