diff options
author | Tor Arne Vestbø <[email protected]> | 2023-09-29 17:45:49 +0200 |
---|---|---|
committer | Tor Arne Vestbø <[email protected]> | 2023-10-11 20:32:05 +0200 |
commit | cd4000a97d325029acab7c253c1774c01ad6f782 (patch) | |
tree | c2a9e2cc9d8c7fe0bf73493cd16aebed2323d4cb | |
parent | 7d3417fbfcbfc46061609a842768a0111c5a15a2 (diff) |
Use QtGui to match QWindow based shortcuts, even when QApplication is used
If a QShortcut is registered with a QWindow as its parent, but QApplication
is used, we end up in QApplicationPrivate::createShortcutPrivate(), and
create a QtWidgetsShortcutPrivate that implements shortcut context matching
via qWidgetShortcutContextMatcher.
The problem is that qWidgetShortcutContextMatcher expects the windows
to be QWidgetWindows, which meant that plain QWindow based shortcuts
would always fail.
This can happen for example if a QApplication is used in Qt Quick
to provide dialog fallbacks, but QShortcuts are otherwise used
with plain QWindows, or QQuickWindows e.g.
We now defer the check of whether there's an active (widget) window,
and fall back to QtGui's simpleContextMatcher in case we don't find
a QWidget, QAction, or QGraphicsWidget shortcut owner to handle
the matching for.
Note: We don't support shortcut matching for QAction in QtGui,
but this is left for another day. There is also a discrepancy
between how QtGui and QtWidgets handles Qt::ApplicationShortcut.
The former will treat it as a match even if there is no active
QWindow, while the latter requires that there's an active widget
window.
Fixes: QTBUG-116221
Change-Id: I487995f2e660a40f6556828b84a521d81a58f1b6
Reviewed-by: Volker Hilsheimer <[email protected]>
-rw-r--r-- | src/gui/kernel/qshortcut.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qshortcut_p.h | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qshortcut_widgets.cpp | 18 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qshortcut/CMakeLists.txt | 14 |
4 files changed, 29 insertions, 7 deletions
diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp index b10d96237e9..3f6822cb031 100644 --- a/src/gui/kernel/qshortcut.cpp +++ b/src/gui/kernel/qshortcut.cpp @@ -96,7 +96,7 @@ QT_BEGIN_NAMESPACE \sa activated() */ -static bool simpleContextMatcher(QObject *object, Qt::ShortcutContext context) +bool QShortcutPrivate::simpleContextMatcher(QObject *object, Qt::ShortcutContext context) { auto guiShortcut = qobject_cast<QShortcut *>(object); if (QGuiApplication::applicationState() != Qt::ApplicationActive || guiShortcut == nullptr) diff --git a/src/gui/kernel/qshortcut_p.h b/src/gui/kernel/qshortcut_p.h index a99cca27c1b..8ff833d4778 100644 --- a/src/gui/kernel/qshortcut_p.h +++ b/src/gui/kernel/qshortcut_p.h @@ -43,6 +43,8 @@ public: virtual QShortcutMap::ContextMatcher contextMatcher() const; virtual bool handleWhatsThis() { return false; } + static bool simpleContextMatcher(QObject *object, Qt::ShortcutContext context); + QList<QKeySequence> sc_sequences; QString sc_whatsthis; Qt::ShortcutContext sc_context = Qt::WindowShortcut; diff --git a/src/widgets/kernel/qshortcut_widgets.cpp b/src/widgets/kernel/qshortcut_widgets.cpp index cb184ef07da..6e25d79bd6a 100644 --- a/src/widgets/kernel/qshortcut_widgets.cpp +++ b/src/widgets/kernel/qshortcut_widgets.cpp @@ -65,9 +65,6 @@ bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context) } } - if (!active_window) - return false; - #if QT_CONFIG(action) if (auto a = qobject_cast<QAction *>(object)) return correctActionContext(context, a, active_window); @@ -95,14 +92,17 @@ bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context) } } - if (!w) - return false; + if (w) + return correctWidgetContext(context, w, active_window); - return correctWidgetContext(context, w, active_window); + return QShortcutPrivate::simpleContextMatcher(object, context); } static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window) { + if (!active_window) + return false; + bool visible = w->isVisible(); #if QT_CONFIG(menubar) if (auto menuBar = qobject_cast<QMenuBar *>(w)) { @@ -188,6 +188,9 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge #if QT_CONFIG(graphicsview) static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window) { + if (!active_window) + return false; + bool visible = w->isVisible(); #if defined(Q_OS_DARWIN) && QT_CONFIG(menubar) if (!QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w)) @@ -247,6 +250,9 @@ static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsW #if QT_CONFIG(action) static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window) { + if (!active_window) + return false; + const QObjectList associatedObjects = a->associatedObjects(); #if defined(DEBUG_QSHORTCUTMAP) if (associatedObjects.isEmpty()) diff --git a/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt b/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt index 30883baebb8..517286f3249 100644 --- a/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt @@ -22,3 +22,17 @@ qt_internal_add_test(tst_qshortcut Qt::Widgets Qt::WidgetsPrivate ) + +qt_internal_add_test(tst_qguishortcut_with_qapplication + SOURCES + ../../../gui/kernel/qshortcut/tst_qshortcut.cpp + DEFINES + tst_QShortcut=tst_QGuiShortcutWithQApplication + INCLUDE_DIRECTORIES + .. + LIBRARIES + Qt::Gui + Qt::GuiPrivate + Qt::Widgets + Qt::WidgetsPrivate +) |