From de8395404e19954fc09941cfc2160c64113e1304 Mon Sep 17 00:00:00 2001 From: freaksdd Date: Wed, 14 Aug 2024 14:25:58 +0200 Subject: [PATCH 1/3] Make Cutekeyboard compatible with Dialogs and Popup Because of the Modal option, the keyboard doesn't work with Dialogs and Popups. The solution is to register the QQuickItem of InputPanel in the Backend and set the focusItem as parent of the InputPanel. Note that the keyboard is still incompatible with QtQuick.Dialogs --- src/VirtualKeyboardInputContext.cpp | 37 +++++++++++++++++++++++++++++ src/VirtualKeyboardInputContext.h | 9 +++++++ src/qml/InputPanel.qml | 6 +++++ 3 files changed, 52 insertions(+) diff --git a/src/VirtualKeyboardInputContext.cpp b/src/VirtualKeyboardInputContext.cpp index 8807730..7a092ab 100644 --- a/src/VirtualKeyboardInputContext.cpp +++ b/src/VirtualKeyboardInputContext.cpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include "DeclarativeInputEngine.h" #include "EnterKeyAction.hpp" @@ -70,6 +72,14 @@ bool VirtualKeyboardInputContext::focusItemHasEnterKeyAction( qmlAttachedPropertiesObject(item, false); } +void VirtualKeyboardInputContext::registerInputPanel(QObject *inputPanel) +{ + Q_ASSERT(!this->inputPanel); + this->inputPanel = inputPanel; + if (QQuickItem *item = qobject_cast(inputPanel)) + item->setZ(std::numeric_limits::max()); +} + bool VirtualKeyboardInputContext::isValid() const { return true; } QRectF VirtualKeyboardInputContext::keyboardRect() const { return QRectF(); } @@ -108,9 +118,36 @@ void VirtualKeyboardInputContext::setFocusObject(QObject *object) { bool AcceptsInput = d->FocusItem->inputMethodQuery(Qt::ImEnabled).toBool(); if (!AcceptsInput) { + hideInputPanel(); return; } + // set the focusItem as parent of InputPanel + if (QObject *item = inputItem()) { + // ToDo: the InputPanel is set once, so cast can be done at register QQuickItem + if (QQuickItem *vkbPanel = qobject_cast(inputPanel)) { + // ToDo: cast of inputItem is overflow ... use d->FocusItem + 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); + } + } + } + } + + QObject::connect(d->FocusItem, &QQuickItem::visibleChanged, this, [&](){ + if(!d->FocusItem->isVisible()) + hideInputPanel(); + else + showInputPanel(); + }); + emit inputItemChanged(); Qt::InputMethodHints InputMethodHints( diff --git a/src/VirtualKeyboardInputContext.h b/src/VirtualKeyboardInputContext.h index 73f68b3..4a0525d 100644 --- a/src/VirtualKeyboardInputContext.h +++ b/src/VirtualKeyboardInputContext.h @@ -15,6 +15,7 @@ #include #include +#include class QQmlEngine; class QJSEngine; @@ -96,6 +97,12 @@ class VirtualKeyboardInputContext : public QPlatformInputContext { */ Q_INVOKABLE bool focusItemHasEnterKeyAction(QObject *item) const; + /** + * This function register the InputPanel (QQucikItem) to the backend + * to handle the focusItem as parent + */ + Q_INVOKABLE void registerInputPanel(QObject *inputPanel); + protected: /** * Protected constructor - use instance function to get the one and only @@ -135,7 +142,9 @@ class VirtualKeyboardInputContext : public QPlatformInputContext { static QObject *inputContextProvider(QQmlEngine *engine, QJSEngine *scriptEngine); + private: VirtualKeyboardInputContextPrivate *d; + QPointer inputPanel; }; #endif // VIRTUALKEYBOARDINPUTCONTEXT_H diff --git a/src/qml/InputPanel.qml b/src/qml/InputPanel.qml index 62059db..ba0757e 100644 --- a/src/qml/InputPanel.qml +++ b/src/qml/InputPanel.qml @@ -20,6 +20,9 @@ Item { property string languageIcon: "qrc:/icons/language.png" property var availableLanguageLayouts: ["En"] + /*! \internal */ + readonly property bool __isRootItem: inputPanel.parent !== null && inputPanel.parent.parent === null + function showKeyPopup(keyButton) { keyPopup.popup(keyButton, root); } @@ -59,6 +62,9 @@ Item { } onLanguageLayoutChanged: loadLettersLayout() Component.onCompleted: { + + InputContext.registerInputPanel(root) + if (availableLanguageLayouts.length == 0) availableLanguageLayouts = ["En"]; From 194f51f680e4d0c015b904ea184d7ed56ae6f0a2 Mon Sep 17 00:00:00 2001 From: freaksdd Date: Thu, 15 Aug 2024 07:35:09 +0200 Subject: [PATCH 2/3] fix: delete old item-connection when there are manny items, there are a lot of connections in backend. if the current item in action, the connection can be handle. if a new item is focus, the 'old' connection can be overwritten. --- src/VirtualKeyboardInputContext.cpp | 4 ++-- src/VirtualKeyboardInputContext.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/VirtualKeyboardInputContext.cpp b/src/VirtualKeyboardInputContext.cpp index 7a092ab..c8fe344 100644 --- a/src/VirtualKeyboardInputContext.cpp +++ b/src/VirtualKeyboardInputContext.cpp @@ -141,12 +141,12 @@ void VirtualKeyboardInputContext::setFocusObject(QObject *object) { } } - QObject::connect(d->FocusItem, &QQuickItem::visibleChanged, this, [&](){ + visibleConnection = std::make_shared(QObject::connect(d->FocusItem, &QQuickItem::visibleChanged, this, [&](){ if(!d->FocusItem->isVisible()) hideInputPanel(); else showInputPanel(); - }); + })); emit inputItemChanged(); diff --git a/src/VirtualKeyboardInputContext.h b/src/VirtualKeyboardInputContext.h index 4a0525d..93d0427 100644 --- a/src/VirtualKeyboardInputContext.h +++ b/src/VirtualKeyboardInputContext.h @@ -16,6 +16,7 @@ #include #include +#include class QQmlEngine; class QJSEngine; @@ -145,6 +146,7 @@ class VirtualKeyboardInputContext : public QPlatformInputContext { private: VirtualKeyboardInputContextPrivate *d; QPointer inputPanel; + std::shared_ptr visibleConnection; }; #endif // VIRTUALKEYBOARDINPUTCONTEXT_H From 7b96d7693efce2245c5841670dd773c6f36082eb Mon Sep 17 00:00:00 2001 From: freaksdd Date: Thu, 15 Aug 2024 07:23:44 +0200 Subject: [PATCH 3/3] Add translations for the SpaceBar Added SpaceBar translation with 'spaceIdentifier' property. The translation can be added to the map inside DeclarativeInputEngine.cpp, with 'space' as fallback. --- src/DeclarativeInputEngine.cpp | 18 +++++++++++++++++- src/DeclarativeInputEngine.h | 8 ++++++-- src/qml/InputPanel.qml | 5 +++++ src/qml/QwertyLayout.qml | 1 + src/qml/SymbolLayout.qml | 2 ++ 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/DeclarativeInputEngine.cpp b/src/DeclarativeInputEngine.cpp index fe25722..3c20397 100644 --- a/src/DeclarativeInputEngine.cpp +++ b/src/DeclarativeInputEngine.cpp @@ -17,6 +17,7 @@ struct DeclarativeInputEnginePrivate { struct LayoutData { QString layoutFile; QString description; + QString spaceIdentifier = "Space"; }; DeclarativeInputEngine *_this; @@ -32,7 +33,7 @@ struct DeclarativeInputEnginePrivate { {DeclarativeInputEngine::Fr, {"FrLayout", "Français"}}, {DeclarativeInputEngine::It, {"ItLayout", "Italiano"}}, {DeclarativeInputEngine::Es, {"EsLayout", "Español"}}, - {DeclarativeInputEngine::De, {"DeLayout", "Deutsch"}}, + {DeclarativeInputEngine::De, {"DeLayout", "Deutsch", "Leerzeichen"}}, {DeclarativeInputEngine::Nl, {"NlLayout", "Nederlands"}}, {DeclarativeInputEngine::Pt, {"PtLayout", "Português"}}, {DeclarativeInputEngine::Cs, {"CsLayout", "Čeština"}}, @@ -165,3 +166,18 @@ QString DeclarativeInputEngine::descriptionOfLayout(QString layout) { } return d->layoutFiles.value(layoutVal, {}).description; } + +QString DeclarativeInputEngine::spaceIdentifierOfLayout(QString layout) +{ + if (!inputLayoutValid(layout)) { + return ""; + } + bool ok = false; + auto layoutVal = static_cast( + QMetaEnum::fromType().keyToValue(layout.toUtf8().data(), + &ok)); + if (!ok) { + return ""; + } + return d->layoutFiles.value(layoutVal, {}).spaceIdentifier; +} diff --git a/src/DeclarativeInputEngine.h b/src/DeclarativeInputEngine.h index a69a14c..67b2b00 100644 --- a/src/DeclarativeInputEngine.h +++ b/src/DeclarativeInputEngine.h @@ -117,11 +117,15 @@ class DeclarativeInputEngine : public QObject { Q_INVOKABLE QString fileOfLayout(QString layout); /** - * Use this function to get the correct layout file for each language - * (only needed for languages that share one file) + * Use this function to get the correct description for each language */ Q_INVOKABLE QString descriptionOfLayout(QString layout); + /** + * Use this function to get the correct 'space'-identifier for each language + */ + Q_INVOKABLE QString spaceIdentifierOfLayout(QString layout); + public slots: /** * Emits a key click event for the given key, text and modifiers. diff --git a/src/qml/InputPanel.qml b/src/qml/InputPanel.qml index ba0757e..225ffd9 100644 --- a/src/qml/InputPanel.qml +++ b/src/qml/InputPanel.qml @@ -37,14 +37,17 @@ Item { function loadLettersLayout() { var description = InputEngine.descriptionOfLayout(languageLayout); + var spaceIdentifier = InputEngine.spaceIdentifierOfLayout(languageLayout); var source = InputEngine.fileOfLayout(languageLayout); if (description !== "" && source !== "") { layoutLoader.langDescription = description; + layoutLoader.spaceIdentifier = spaceIdentifier; layoutLoader.setSource(source + ".qml", { "inputPanel": root }); } else { layoutLoader.langDescription = "English"; + layoutLoader.spaceIdentifier = "space"; layoutLoader.setSource("EnLayout.qml", { "inputPanel": root }); @@ -126,6 +129,8 @@ Item { // lang description only needed for layouts that share a file property string langDescription + // space identifier for the correct translation of the word "space" + property string spaceIdentifier anchors { fill: parent diff --git a/src/qml/QwertyLayout.qml b/src/qml/QwertyLayout.qml index 30f0332..0b7617e 100644 --- a/src/qml/QwertyLayout.qml +++ b/src/qml/QwertyLayout.qml @@ -225,6 +225,7 @@ ColumnLayout { SpaceKey { weight: 1168 inputPanelRef: inputPanel + btnDisplayedText: spaceIdentifier } Key { diff --git a/src/qml/SymbolLayout.qml b/src/qml/SymbolLayout.qml index f3576b0..8a954ea 100644 --- a/src/qml/SymbolLayout.qml +++ b/src/qml/SymbolLayout.qml @@ -244,6 +244,7 @@ Item { SpaceKey { weight: 1168 inputPanelRef: inputPanel + btnDisplayedText: spaceIdentifier } Key { @@ -492,6 +493,7 @@ Item { SpaceKey { weight: 1168 inputPanelRef: inputPanel + btnDisplayedText: spaceIdentifier } Key {