sending of input method update hints improved

This commit is contained in:
Uwe Rathmann 2018-06-12 10:56:06 +02:00
parent e195614654
commit 9e5ded43c6
6 changed files with 61 additions and 56 deletions

View File

@ -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() )

View File

@ -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 )

View File

@ -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* );

View File

@ -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 );

View File

@ -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();

View File

@ -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 )