aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2021-10-16 13:18:04 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-11-03 19:05:11 +0000
commit2b84f3b13688164510126bde60d16d46cc7e57cf (patch)
tree27003fe4535d53726ccf6b0ab3b5e041e2fe5718
parent7fe94a079ba9931060f1c1d488b09e5432798a4c (diff)
Use a containment mask to keep input panel working during modal session
Instead of reparenting the input panel to be on top of the overlay as introduced in 4e8b3dd45ae4cc66a1b77cce901f80406b2a0f69, set a the input context as a containment mask on the dimmer that is modally blocking the UI elements underneath the overlay. Since modality is a Qt Quick Control concept that doesn't exist in Qt Quick, we have to use the dynamic property through which the dimmer registers itself within the item hierarchy. If called, the contains() implementation then lets all input events through that occur within the rectangles occupied by the virtual keyboard. Remove the documentation about the reparenting during modal sessions, we no longer have to do that. [ChangeLog][QtVirtualKeyboard][InputPanel] Since Qt 5.15, the virtual keyboard's input panel has automatically been reparented to prevent the keyboard UI from being blocked by modal dialogs. This is no longer done; the input panel instead uses a containment mask on the dimmer item that blocks input during modal sessions, allowing clicks through to the keyboard UI. Task-number: QTBUG-97075 Task-number: QTBUG-56918 Task-number: QTBUG-92881 Change-Id: I2627a4602913e29233778ed190b44a1ce47f5259 Reviewed-by: Jarkko Koivikko <jarkko.koivikko@code-q.fi> (cherry picked from commit 1129af130964c5e0f2db6e8a6fb6dc2fe70f3bc8) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/virtualkeyboard/qvirtualkeyboardinputcontext_p.cpp52
-rw-r--r--src/virtualkeyboard/qvirtualkeyboardinputcontext_p.h5
2 files changed, 39 insertions, 18 deletions
diff --git a/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.cpp b/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.cpp
index 4324ffe7..96d80d68 100644
--- a/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.cpp
+++ b/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.cpp
@@ -270,6 +270,29 @@ void QVirtualKeyboardInputContextPrivate::forceCursorPosition(int anchorPosition
}
}
+/*! \internal
+ The context private becomes a containment mask for a dimmer opened by a
+ modal QQuickPopup. The dimmer eats events, and the virtual keyboard must
+ continue to work during modal sessions as well. This implementation lets
+ all pointer events within the area of the input panel through.
+*/
+bool QVirtualKeyboardInputContextPrivate::contains(const QPointF &point) const
+{
+ bool hit = false;
+ if (dimmer) {
+ const auto scenePoint = dimmer->mapToScene(point);
+ if (keyboardRectangle().contains(scenePoint)) {
+ hit = true;
+ } else if (QQuickItem *vkbPanel = qobject_cast<QQuickItem*>(inputPanel)) {
+ const auto vkbPanelPoint = vkbPanel->mapFromScene(scenePoint);
+ if (vkbPanel->contains(vkbPanelPoint))
+ hit = true;
+ }
+ }
+ // dimmer doesn't contain points that hit the input panel
+ return !hit;
+}
+
void QVirtualKeyboardInputContextPrivate::onInputItemChanged()
{
QObject *item = inputItem();
@@ -277,25 +300,22 @@ void QVirtualKeyboardInputContextPrivate::onInputItemChanged()
if (QQuickItem *vkbPanel = qobject_cast<QQuickItem*>(inputPanel)) {
if (QQuickItem *quickItem = qobject_cast<QQuickItem*>(item)) {
const QVariant isDesktopPanel = vkbPanel->property("desktopPanel");
- /*
- For integrated keyboards, make sure it's a sibling to the overlay. The
- high z-order will make sure it gets events also during a modal session.
- */
if (isDesktopPanel.isValid() && !isDesktopPanel.toBool()) {
+ // Integrated keyboards used in a Qt Quick Controls UI must continue to
+ // work during a modal session, which is implemented using an overlay
+ // and dimmer item. So, make use of some QQC2 internals to find out if
+ // there is a dimmer, and if so, make ourselves the containment mask
+ // that can let pointer events through to the keyboard.
if (QQuickWindow *quickWindow = quickItem->window()) {
- QQuickItem *overlay = quickWindow->property("_q_QQuickOverlay").value<QQuickItem*>();
- if (overlay && overlay->isVisible()) {
- if (vkbPanel->parentItem() != overlay->parentItem()) {
- inputPanelParentItem = vkbPanel->parentItem();
- inputPanelZ = vkbPanel->z();
- vkbPanel->setParentItem(overlay->parentItem());
- vkbPanel->setZ(overlay->z() + 1);
+ if (QQuickItem *overlay = quickWindow->property("_q_QQuickOverlay").value<QQuickItem*>()) {
+ if (dimmer && dimmer->containmentMask() == this) {
+ dimmer->setContainmentMask(nullptr);
+ dimmer = nullptr;
}
- } else {
- if (QQuickItem *oldParentItem = qobject_cast<QQuickItem *>(inputPanelParentItem.data())) {
- vkbPanel->setParentItem(oldParentItem);
- vkbPanel->setZ(inputPanelZ);
- inputPanelParentItem = nullptr;
+ if (overlay && overlay->isVisible()) {
+ dimmer = overlay->property("_q_dimmerItem").value<QQuickItem*>();
+ if (dimmer)
+ dimmer->setContainmentMask(this);
}
}
}
diff --git a/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.h b/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.h
index ab2698d5..b8258294 100644
--- a/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.h
+++ b/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.h
@@ -45,6 +45,7 @@
#include <QRectF>
#include <QSet>
#include <QInputMethodEvent>
+#include <QQuickItem>
#include <QtVirtualKeyboard/qvirtualkeyboardinputcontext.h>
#include <QtVirtualKeyboard/private/shadowinputcontext_p.h>
#include <QtVirtualKeyboard/qvirtualkeyboardobserver.h>
@@ -117,6 +118,7 @@ public:
Q_INVOKABLE bool fileExists(const QUrl &fileUrl);
Q_INVOKABLE bool hasEnterKeyAction(QObject *item) const;
Q_INVOKABLE void registerInputPanel(QObject *inputPanel);
+ Q_INVOKABLE bool contains(const QPointF &point) const;
Q_SIGNALS:
void focusChanged();
@@ -158,8 +160,7 @@ private:
QVirtualKeyboardInputEngine *inputEngine;
QtVirtualKeyboard::ShiftHandler *_shiftHandler;
QPointer<QObject> inputPanel;
- QPointer<QObject> inputPanelParentItem;
- qreal inputPanelZ = .0;
+ QPointer<QQuickItem> dimmer;
QRectF keyboardRect;
QRectF previewRect;
bool _previewVisible;