From 9e5ded43c605332f41790b7765d31c817458a9e1 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 12 Jun 2018 10:56:06 +0200 Subject: [PATCH] sending of input method update hints improved --- inputcontext/QskInputContextPlugin.cpp | 19 ++++---- src/controls/QskQuick.cpp | 67 ++++++++++++-------------- src/controls/QskQuick.h | 1 - src/inputpanel/QskInputContext.cpp | 14 ++++-- src/inputpanel/QskInputContext.h | 8 +-- src/inputpanel/QskInputPanel.cpp | 8 +++ 6 files changed, 61 insertions(+), 56 deletions(-) diff --git a/inputcontext/QskInputContextPlugin.cpp b/inputcontext/QskInputContextPlugin.cpp index b9e61024..6f29992c 100644 --- a/inputcontext/QskInputContextPlugin.cpp +++ b/inputcontext/QskInputContextPlugin.cpp @@ -76,7 +76,7 @@ public: virtual bool filterEvent( const QEvent* ) override; - Q_INVOKABLE QQuickItem* inputItem(); + Q_INVOKABLE void update( const QQuickItem*, Qt::InputMethodQueries ); protected: virtual bool event( QEvent* ) override; @@ -150,7 +150,14 @@ bool QskPlatformInputContext::hasCapability( Capability ) const void QskPlatformInputContext::update( Qt::InputMethodQueries queries ) { if ( m_context ) - m_context->update( queries ); + m_context->update( nullptr, queries ); +} + +void QskPlatformInputContext::update( + const QQuickItem* item, Qt::InputMethodQueries queries ) +{ + if ( m_context ) + m_context->update( item, queries ); } void QskPlatformInputContext::invokeAction( @@ -233,14 +240,6 @@ bool QskPlatformInputContext::filterEvent( const QEvent* ) return false; } -QQuickItem* QskPlatformInputContext::inputItem() -{ - if ( m_context ) - return m_context->inputItem(); - - return nullptr; -} - bool QskPlatformInputContext::event( QEvent* event ) { switch( event->type() ) diff --git a/src/controls/QskQuick.cpp b/src/controls/QskQuick.cpp index e312a770..82adb4bc 100644 --- a/src/controls/QskQuick.cpp +++ b/src/controls/QskQuick.cpp @@ -138,59 +138,54 @@ void qskForceActiveFocus( QQuickItem* item, Qt::FocusReason reason ) } } -QQuickItem* qskInputContextItem() +void qskUpdateInputMethod( const QQuickItem* item, Qt::InputMethodQueries queries ) { - /* - The item that is connected to the input context. - - often the item having the active focus. - */ + if ( item == nullptr || !( item->flags() & QQuickItem::ItemAcceptsInputMethod ) ) + return; - QQuickItem* inputItem = nullptr; + static QPlatformInputContext* context = nullptr; + static int methodId = -1; /* We could also get the inputContext from QInputMethodPrivate but for some reason the gcc sanitizer reports errors when using it. So let's go with QGuiApplicationPrivate. */ - const auto inputContext = - QGuiApplicationPrivate::platformIntegration()->inputContext(); - if ( inputContext && inputContext->isInputPanelVisible() ) + auto inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext(); + if ( inputContext == nullptr ) { - /* - QskInputContext allows to navigate inside the input panel - without losing the connected input item - */ + context = nullptr; + methodId = -1; - if ( inputContext->metaObject()->indexOfMethod( "inputItem()" ) >= 0 ) - { - QMetaObject::invokeMethod( inputContext, "inputItem", - Qt::DirectConnection, Q_RETURN_ARG( QQuickItem*, inputItem ) ); - } + return; } - return inputItem; -} + if ( inputContext != context ) + { + context = inputContext; + methodId = inputContext->metaObject()->indexOfMethod( + "update(const QQuickItem*,Qt::InputMethodQueries)" ); + } -void qskUpdateInputMethod( const QQuickItem* item, Qt::InputMethodQueries queries ) -{ - if ( item == nullptr ) - return; + if ( methodId >= 0 ) + { + /* + The protocol for input methods does not fit well for a + virtual keyboard as it is tied to the focus. + So we try to bypass QInputMethod calling the + inputContext directly. + */ -#if 1 - if ( !( item->flags() & QQuickItem::ItemAcceptsInputMethod ) ) - return; -#endif - - bool doUpdate; - - if ( const QQuickItem* inputItem = qskInputContextItem() ) - doUpdate = ( item == inputItem ); + inputContext->metaObject()->method( methodId ).invoke( + inputContext, Qt::DirectConnection, + Q_ARG( const QQuickItem*, item ), + Q_ARG( Qt::InputMethodQueries, queries ) ); + } else - doUpdate = item->hasActiveFocus(); - - if ( doUpdate ) + { QGuiApplication::inputMethod()->update( queries ); + } } QList< QQuickItem* > qskPaintOrderChildItems( const QQuickItem* item ) diff --git a/src/controls/QskQuick.h b/src/controls/QskQuick.h index 35825bcb..857b2819 100644 --- a/src/controls/QskQuick.h +++ b/src/controls/QskQuick.h @@ -31,7 +31,6 @@ QSK_EXPORT void qskForceActiveFocus( QQuickItem*, Qt::FocusReason ); QSK_EXPORT QList< QQuickItem* > qskPaintOrderChildItems( const QQuickItem* ); QSK_EXPORT void qskUpdateInputMethod( const QQuickItem*, Qt::InputMethodQueries ); -QSK_EXPORT QQuickItem* qskInputContextItem(); QSK_EXPORT const QSGNode* qskItemNode( const QQuickItem* ); QSK_EXPORT const QSGNode* qskPaintNode( const QQuickItem* ); diff --git a/src/inputpanel/QskInputContext.cpp b/src/inputpanel/QskInputContext.cpp index 230f6481..da865244 100644 --- a/src/inputpanel/QskInputContext.cpp +++ b/src/inputpanel/QskInputContext.cpp @@ -164,13 +164,17 @@ QskTextPredictor* QskInputContext::textPredictor( const QLocale& locale ) return nullptr; } -QQuickItem* QskInputContext::inputItem() const +void QskInputContext::update( const QQuickItem* item, Qt::InputMethodQueries queries ) { - return m_data->inputItem; -} + if ( item == nullptr ) + { + item = qobject_cast< QQuickItem* >( QGuiApplication::focusObject() ); +#if 1 + // those are coming from QQuickWindow based on focus changes + return; +#endif + } -void QskInputContext::update( Qt::InputMethodQueries queries ) -{ if ( queries & Qt::ImEnabled ) { QInputMethodQueryEvent event( Qt::ImEnabled ); diff --git a/src/inputpanel/QskInputContext.h b/src/inputpanel/QskInputContext.h index 394d4924..f06e28f8 100644 --- a/src/inputpanel/QskInputContext.h +++ b/src/inputpanel/QskInputContext.h @@ -74,10 +74,10 @@ private: friend class QskPlatformInputContext; // called from QskPlatformInputContext - virtual void setFocusObject( QObject* ); - virtual void update( Qt::InputMethodQueries ); - virtual void processClickAt( int cursorPosition ); - virtual void commitPrediction( bool ); + void setFocusObject( QObject* ); + void update( const QQuickItem*, Qt::InputMethodQueries ); + void processClickAt( int cursorPosition ); + void commitPrediction( bool ); void ensurePanel(); diff --git a/src/inputpanel/QskInputPanel.cpp b/src/inputpanel/QskInputPanel.cpp index 63b16c46..0f01f494 100644 --- a/src/inputpanel/QskInputPanel.cpp +++ b/src/inputpanel/QskInputPanel.cpp @@ -345,6 +345,14 @@ void QskInputPanel::updateInputPanel( Qt::InputMethodQueries queries ) { setLocale( event.value( Qt::ImPreferredLanguage ).toLocale() ); } + + if ( queries & Qt::ImInputItemClipRectangle ) + { + /* + Could be used to move the panel, + so that it does not hide the item. + */ + } } void QskInputPanel::updateLocale( const QLocale& locale )