Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickshortcutcontext.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
8#include <QtQmlModels/private/qtqmlmodels-config_p.h>
9#if QT_CONFIG(qml_object_model)
10#include "qquickmenu_p.h"
11#include "qquickmenu_p_p.h"
12#endif
13#include "qquickpopup_p.h"
14
15#include <QtCore/qloggingcategory.h>
16#include <QtGui/qguiapplication.h>
17#include <QtGui/private/qguiapplication_p.h>
18#include <QtQuick/qquickrendercontrol.h>
19#include <QtQuickTemplates2/private/qquickpopupwindow_p_p.h>
20
21QT_BEGIN_NAMESPACE
22
23Q_STATIC_LOGGING_CATEGORY(lcContextMatcher, "qt.quick.controls.shortcutcontext.matcher")
24
25static bool isBlockedByPopup(QQuickItem *item)
26{
27 if (!item || !item->window())
28 return false;
29
30 QQuickOverlay *overlay = QQuickOverlay::overlay(item->window());
31 auto popups = QQuickOverlayPrivate::get(overlay)->stackingOrderPopups();
32
33 for (QWindow *popupWindow : QGuiApplicationPrivate::popup_list) {
34 if (QQuickPopupWindow *quickPopupWindow = qobject_cast<QQuickPopupWindow *>(popupWindow);
35 quickPopupWindow && quickPopupWindow->popup())
36 popups += quickPopupWindow->popup();
37 }
38
39 for (QQuickPopup *popup : std::as_const(popups)) {
40 if (qobject_cast<QQuickToolTip *>(popup))
41 continue; // ignore tooltips (QTBUG-60492)
42 if (popup->isModal() || popup->closePolicy() & QQuickPopup::CloseOnEscape) {
43 qCDebug(lcContextMatcher) << popup << "is modal or has a CloseOnEscape policy;"
44 << "if one of the following is true," << item
45 << "will be blocked by it:" << (item != popup->popupItem())
46 << !popup->popupItem()->isAncestorOf(item);
47 return item != popup->popupItem() && !popup->popupItem()->isAncestorOf(item);
48 }
49 }
50 return false;
51}
52
53bool QQuickShortcutContext::matcher(QObject *obj, Qt::ShortcutContext context)
54{
55 if ((context != Qt::ApplicationShortcut) && (context != Qt::WindowShortcut))
56 return false;
57
58 QQuickItem *item = nullptr;
59
60 // look for the window contains embedded shortcut
61 while (obj && !obj->isWindowType()) {
62 item = qobject_cast<QQuickItem *>(obj);
63 if (item && item->window()) {
64 obj = item->window();
65 break;
66 } else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(obj)) {
67 obj = popup->window();
68 item = popup->popupItem();
69
70#if QT_CONFIG(qml_object_model)
71 if (!obj) {
72 // The popup has no associated window (yet). However, sub-menus,
73 // unlike top-level menus, will not have an associated window
74 // until their parent menu is opened. So, check if this is a sub-menu
75 // so that actions within it can grab shortcuts.
76 if (auto *menu = qobject_cast<QQuickMenu *>(popup)) {
77 auto parentMenu = QQuickMenuPrivate::get(menu)->parentMenu;
78 while (parentMenu) {
79 obj = parentMenu->window();
80 if (obj)
81 break;
82
83 parentMenu = QQuickMenuPrivate::get(parentMenu)->parentMenu;
84 }
85 }
86 }
87#endif
88 break;
89 }
90 obj = obj->parent();
91 }
92
93 if (context == Qt::ApplicationShortcut) {
94 // the application shortcuts inside hidden/closed windows should not match
95 return obj && qobject_cast<QWindow*>(obj)->isVisible();
96 } else {
97 Q_ASSERT(context == Qt::WindowShortcut);
98 QQuickWindow *window = qobject_cast<QQuickWindow *>(obj);
99 if (QWindow *renderWindow = QQuickRenderControl::renderWindowFor(window))
100 obj = renderWindow;
101 qCDebug(lcContextMatcher) << "obj" << obj << "item" << item << "focusWindow"
102 << QGuiApplication::focusWindow()
103 << "!isBlockedByPopup(item)" << !isBlockedByPopup(item);
104 return obj && qobject_cast<QWindow*>(obj)->isActive() && !isBlockedByPopup(item);
105 }
106}
107
108QT_END_NAMESPACE