From 237cb4ab7eaa6c9965354be2effd77627778a7f7 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 21 Jan 2025 18:35:57 +0100 Subject: [PATCH] CloseOnPressOutside enabled for the vitual keyboard to commits and close the edited text. This allows to finish inputs, when Qt::ImhMultiLine is enabled. --- src/controls/QskAbstractTextInput.cpp | 1 - src/inputpanel/QskInputContext.cpp | 47 ++++++++++++++++++++++++--- src/inputpanel/QskInputPanel.cpp | 27 ++++++++------- src/inputpanel/QskInputPanel.h | 1 + src/inputpanel/QskInputPanelBox.cpp | 14 ++++---- 5 files changed, 67 insertions(+), 23 deletions(-) diff --git a/src/controls/QskAbstractTextInput.cpp b/src/controls/QskAbstractTextInput.cpp index c8bcb6fa..dd59ae9c 100644 --- a/src/controls/QskAbstractTextInput.cpp +++ b/src/controls/QskAbstractTextInput.cpp @@ -121,7 +121,6 @@ static inline void qskForwardEvent( QQuickItem* item, QEvent* event ) namespace { - class PropertyBinder : public QObject { Q_OBJECT diff --git a/src/inputpanel/QskInputContext.cpp b/src/inputpanel/QskInputContext.cpp index e859cc0e..5ed082a8 100644 --- a/src/inputpanel/QskInputContext.cpp +++ b/src/inputpanel/QskInputContext.cpp @@ -14,6 +14,7 @@ #include "QskTextPredictor.h" #include "QskWindow.h" #include "QskPlatform.h" +#include "QskInputGrabber.h" #include #include @@ -31,20 +32,53 @@ namespace { class Popup : public QskPopup { + Q_OBJECT + using Inherited = QskPopup; - public: + public: Popup() { setPolishOnResize( true ); setPolishOnParentResize( true ); } - protected: + Q_SIGNALS: + void commitRequested(); + + protected: + void aboutToShow() override + { + Inherited::aboutToShow(); + + if ( popupFlags() & QskPopup::CloseOnPressOutside ) + { + if ( auto inputGrabber = findChild< QskInputGrabber* >() ) + inputGrabber->installEventFilter( this ); + } + } + + bool eventFilter( QObject* object, QEvent* event ) override + { + if ( qobject_cast< QskInputGrabber* >( object ) ) + { + if ( event->type() == QEvent::MouseButtonPress ) + { + if ( popupFlags() & QskPopup::CloseOnPressOutside ) + { + Q_EMIT commitRequested(); + return true; + } + } + } + + return Inherited::eventFilter( object, event ); + } + void updateLayout() override - { + { const auto m = margins(); - const auto item = findChild(); + const auto item = findChild< const QskInputPanel* >(); auto r = qskItemGeometry( parentItem() ); r -= m; @@ -426,6 +460,7 @@ void QskInputContext::showPanel( const QQuickItem* item ) popup->setMargins( 5 ); popup->setModal( true ); + popup->setPopupFlag( QskPopup::CloseOnPressOutside, true ); popup->setPopupFlag( QskPopup::DeleteOnClose, true ); popup->setParentItem( item->window()->contentItem() ); @@ -438,6 +473,9 @@ void QskInputContext::showPanel( const QQuickItem* item ) panel->setParent( popup ); popup->open(); + + connect( popup, &Popup::commitRequested, panel, + [panel]() { panel->commitCurrentText( true ); } ); } panel->attachInputItem( const_cast< QQuickItem* >( item ) ); @@ -580,4 +618,5 @@ QskInputPanel* QskInputContextFactory::createPanel() const return new Panel(); } +#include "QskInputContext.moc" #include "moc_QskInputContext.cpp" diff --git a/src/inputpanel/QskInputPanel.cpp b/src/inputpanel/QskInputPanel.cpp index d2d83442..698214fc 100644 --- a/src/inputpanel/QskInputPanel.cpp +++ b/src/inputpanel/QskInputPanel.cpp @@ -311,7 +311,7 @@ class QskInputPanel::PrivateData Qt::InputMethodHints inputHints; bool hasPredictorLocale = false; - const QskInputPanel* panel; + QskInputPanel* panel; void handleKeyProcessingFinished( const Result& result ) { @@ -325,16 +325,7 @@ class QskInputPanel::PrivateData } case Qt::Key_Return: { - if ( auto proxy = panel->inputProxy() ) - { - // using input method query instead - const auto value = proxy->property( "text" ); - if ( value.canConvert< QString >() ) - { - qskSendReplaceText( inputItem, value.toString() ); - } - } - + panel->commitCurrentText( false ); qskSendKey( inputItem, result.key ); break; } @@ -605,5 +596,19 @@ void QskInputPanel::commitKey( int key ) key, m_data->inputHints, this, predictor, spaceLeft ); } +void QskInputPanel::commitCurrentText( bool isFinal ) +{ + if ( auto proxy = inputProxy() ) + { + // using Qt::ImSurroundingText instead ?? + const auto value = proxy->property( "text" ); + if ( value.canConvert< QString >() ) + qskSendReplaceText( m_data->inputItem, value.toString() ); + } + + if ( isFinal ) + commitKey( Qt::Key_Escape ); +} + #include "moc_QskInputPanel.cpp" #include "QskInputPanel.moc" diff --git a/src/inputpanel/QskInputPanel.h b/src/inputpanel/QskInputPanel.h index d72e3d7c..1eba1fb0 100644 --- a/src/inputpanel/QskInputPanel.h +++ b/src/inputpanel/QskInputPanel.h @@ -35,6 +35,7 @@ class QSK_EXPORT QskInputPanel : public QskControl public Q_SLOTS: void commitKey( int keyCode ); void commitPredictiveText( int index ); + void commitCurrentText( bool isFinal ); Q_SIGNALS: void keySelected( int keyCode ); diff --git a/src/inputpanel/QskInputPanelBox.cpp b/src/inputpanel/QskInputPanelBox.cpp index 26af7c31..2bd3736a 100644 --- a/src/inputpanel/QskInputPanelBox.cpp +++ b/src/inputpanel/QskInputPanelBox.cpp @@ -343,7 +343,7 @@ void QskInputPanelBox::keyPressEvent( QKeyEvent* event ) case Qt::Key_Return: case Qt::Key_Escape: { - keyCode = event->key(); + Q_EMIT keySelected( event->key() ); break; } @@ -355,13 +355,13 @@ void QskInputPanelBox::keyPressEvent( QKeyEvent* event ) keyCode = text[ 0 ].unicode(); else keyCode = event->key(); - } - } - if ( m_data->keyboard->hasKey( keyCode ) ) - { - // animating the corresponding key button ??? - Q_EMIT keySelected( keyCode ); + if ( m_data->keyboard->hasKey( keyCode ) ) + { + // animating the corresponding key button ??? + Q_EMIT keySelected( keyCode ); + } + } } }