diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2020-03-02 13:19:38 +0100 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2020-03-03 12:38:16 +0100 |
commit | 4e8b3dd45ae4cc66a1b77cce901f80406b2a0f69 (patch) | |
tree | 4378b1eaa35948a95cf2224470280d4aae79663b /src | |
parent | 39a3c50f6f3d3aff52853510543388638a2524d5 (diff) |
Make sure that the input panel receives events during modal sessions
Parent the input panel to the focus items' window's contentItem, with
highest z order. This makes the input panel a sibling of the popup's
overlay and dimmer items, but thanks to the highest z-order, the input
panel gets all events.
This requires that we store the input panel in the InputContext, which
again assumes that there is only one input panel. Making this assumption
explicit with a Q_ASSERT.
Also, since __isRootItem is now true, we need to override the reliance
on this property alone to avoid that SelectionControl becomes disabled.
Introduce a second internal property. This should be followed up by a
change that makes the disabling of the SelectionControl in the desktop
integration case an explicit step.
Fixes: QTBUG-56918
Done-with: Jarkko Koivikko <jarkko.koivikko@code-q.fi>
Change-Id: I58bbbb0adf145c9cfc30a7dd0acb2a0e1231481b
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src')
4 files changed, 39 insertions, 5 deletions
diff --git a/src/virtualkeyboard/content/InputPanel.qml b/src/virtualkeyboard/content/InputPanel.qml index b10fef21..ea3ab23f 100644 --- a/src/virtualkeyboard/content/InputPanel.qml +++ b/src/virtualkeyboard/content/InputPanel.qml @@ -116,11 +116,14 @@ Item { /*! \internal */ readonly property bool __isRootItem: inputPanel.parent != null && inputPanel.parent.parent == null + /*! \internal */ + property bool __reparented: false + SelectionControl { objectName: "selectionControl" x: -parent.x y: -parent.y - enabled: active && !keyboard.fullScreenMode && !__isRootItem + enabled: active && !keyboard.fullScreenMode && (!__isRootItem || __reparented) } implicitHeight: keyboard.height diff --git a/src/virtualkeyboard/content/components/Keyboard.qml b/src/virtualkeyboard/content/components/Keyboard.qml index 954c6f2f..d6073d4e 100644 --- a/src/virtualkeyboard/content/components/Keyboard.qml +++ b/src/virtualkeyboard/content/components/Keyboard.qml @@ -90,6 +90,8 @@ Item { return plainInputMethod } + Component.onCompleted: InputContext.priv.registerInputPanel(parent) + width: keyboardBackground.width height: keyboardBackground.height + (VirtualKeyboardSettings.wordCandidateList.alwaysVisible ? wordCandidateView.height : 0) onActiveChanged: { diff --git a/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.cpp b/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.cpp index b99b7147..2c945356 100644 --- a/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.cpp +++ b/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.cpp @@ -36,6 +36,8 @@ #include <QtVirtualKeyboard/qvirtualkeyboardinputengine.h> #include <QGuiApplication> +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickwindow.h> #include <QtGui/qpa/qplatformintegration.h> #include <QtGui/private/qguiapplication_p.h> @@ -213,6 +215,15 @@ bool QVirtualKeyboardInputContextPrivate::hasEnterKeyAction(QObject *item) const return item != nullptr && qmlAttachedPropertiesObject<EnterKeyAction>(item, false); } +void QVirtualKeyboardInputContextPrivate::registerInputPanel(QObject *inputPanel) +{ + VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputContextPrivate::registerInputPanel():" << inputPanel; + Q_ASSERT(!this->inputPanel); + this->inputPanel = inputPanel; + if (QQuickItem *item = qobject_cast<QQuickItem *>(inputPanel)) + item->setZ(std::numeric_limits<qreal>::max()); +} + void QVirtualKeyboardInputContextPrivate::hideInputPanel() { platformInputContext->hideInputPanel(); @@ -259,10 +270,26 @@ void QVirtualKeyboardInputContextPrivate::forceCursorPosition(int anchorPosition void QVirtualKeyboardInputContextPrivate::onInputItemChanged() { - if (!inputItem() && !activeKeys.isEmpty()) { - // After losing keyboard focus it is impossible to track pressed keys - activeKeys.clear(); - clearState(State::KeyEvent); + if (QObject *item = inputItem()) { + if (QQuickItem *vkbPanel = qobject_cast<QQuickItem*>(inputPanel)) { + if (QQuickItem *quickItem = qobject_cast<QQuickItem*>(item)) { + const QVariant isRootItem = vkbPanel->property("__isRootItem"); + /* + 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 (isRootItem.isValid() && !isRootItem.toBool()) { + vkbPanel->setParentItem(quickItem->window()->contentItem()); + vkbPanel->setProperty("__reparented", true); + } + } + } + } else { + if (!activeKeys.isEmpty()) { + // After losing keyboard focus it is impossible to track pressed keys + activeKeys.clear(); + clearState(State::KeyEvent); + } } clearState(State::InputMethodClick); } diff --git a/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.h b/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.h index 4075c95f..54491e76 100644 --- a/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.h +++ b/src/virtualkeyboard/qvirtualkeyboardinputcontext_p.h @@ -111,6 +111,7 @@ public: // Helper functions Q_INVOKABLE bool fileExists(const QUrl &fileUrl); Q_INVOKABLE bool hasEnterKeyAction(QObject *item) const; + Q_INVOKABLE void registerInputPanel(QObject *inputPanel); Q_SIGNALS: void focusChanged(); @@ -151,6 +152,7 @@ private: QtVirtualKeyboard::PlatformInputContext *platformInputContext; QVirtualKeyboardInputEngine *inputEngine; QtVirtualKeyboard::ShiftHandler *_shiftHandler; + QPointer<QObject> inputPanel; QRectF keyboardRect; QRectF previewRect; bool _previewVisible; |