From 4e8b3dd45ae4cc66a1b77cce901f80406b2a0f69 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Mon, 2 Mar 2020 13:19:38 +0100 Subject: 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 Change-Id: I58bbbb0adf145c9cfc30a7dd0acb2a0e1231481b Reviewed-by: Mitch Curtis --- src/virtualkeyboard/content/InputPanel.qml | 5 +++- .../content/components/Keyboard.qml | 2 ++ .../qvirtualkeyboardinputcontext_p.cpp | 35 +++++++++++++++++++--- .../qvirtualkeyboardinputcontext_p.h | 2 ++ 4 files changed, 39 insertions(+), 5 deletions(-) (limited to 'src') 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 #include +#include +#include #include #include @@ -213,6 +215,15 @@ bool QVirtualKeyboardInputContextPrivate::hasEnterKeyAction(QObject *item) const return item != nullptr && qmlAttachedPropertiesObject(item, false); } +void QVirtualKeyboardInputContextPrivate::registerInputPanel(QObject *inputPanel) +{ + VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputContextPrivate::registerInputPanel():" << inputPanel; + Q_ASSERT(!this->inputPanel); + this->inputPanel = inputPanel; + if (QQuickItem *item = qobject_cast(inputPanel)) + item->setZ(std::numeric_limits::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(inputPanel)) { + if (QQuickItem *quickItem = qobject_cast(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 inputPanel; QRectF keyboardRect; QRectF previewRect; bool _previewVisible; -- cgit v1.2.3