diff options
author | Andy Shaw <andy.shaw@qt.io> | 2018-04-17 16:45:09 +0200 |
---|---|---|
committer | Andy Shaw <andy.shaw@qt.io> | 2018-04-20 10:18:49 +0000 |
commit | 7c532891e0be2cf78c89738e175b3d312d305e4e (patch) | |
tree | e7afb2e9e1360effe004fdf31fa5497c18d14eca | |
parent | 941db4e0bb3170b6bc3cf775f150a226754e6285 (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.cpp | 16 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qaction/tst_qaction.cpp | 37 |
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" |