filtering of input method events moved to QskInputContext

This commit is contained in:
Uwe Rathmann 2018-04-11 08:58:14 +02:00
parent 02ea027ca8
commit 67dee082ec
5 changed files with 41 additions and 93 deletions

View File

@ -323,6 +323,8 @@ void QskInputContext::hideInputPanel()
{ {
m_data->inputPanel->setVisible( false ); m_data->inputPanel->setVisible( false );
} }
qGuiApp->removeEventFilter( this );
} }
bool QskInputContext::isInputPanelVisible() const bool QskInputContext::isInputPanelVisible() const
@ -365,6 +367,14 @@ void QskInputContext::setFocusObject( QObject* focusObject )
if( qskNearestFocusScope( focusItem ) != m_data->inputPanel ) if( qskNearestFocusScope( focusItem ) != m_data->inputPanel )
setInputItem( focusItem ); setInputItem( focusItem );
} }
if ( m_data->inputPanel && m_data->inputPanel->isVisible() )
{
if ( m_data->inputItem && focusItem != m_data->inputItem )
qGuiApp->installEventFilter( this );
else
qGuiApp->removeEventFilter( this );
}
} }
void QskInputContext::setCompositionModel( void QskInputContext::setCompositionModel(
@ -468,11 +478,12 @@ void QskInputContext::setInputPanel( QQuickItem* inputPanel )
if ( inputPanel ) if ( inputPanel )
{ {
// maybe using a QQuickItemChangeListener instead
#if 1
connect( inputPanel, &QQuickItem::visibleChanged, connect( inputPanel, &QQuickItem::visibleChanged,
this, &QPlatformInputContext::emitInputPanelVisibleChanged ); this, &QPlatformInputContext::emitInputPanelVisibleChanged );
// maybe using a QQuickItemChangeListener instead
#if 1
connect( inputPanel, &QQuickItem::xChanged, connect( inputPanel, &QQuickItem::xChanged,
this, &QPlatformInputContext::emitKeyboardRectChanged ); this, &QPlatformInputContext::emitKeyboardRectChanged );
@ -508,6 +519,28 @@ void QskInputContext::commit()
{ {
} }
bool QskInputContext::eventFilter( QObject* object, QEvent* event )
{
if ( event->type() == QEvent::InputMethodQuery )
{
/*
Qt/Quick expects that the item associated with the input context
holds the focus. But this does not work, when a virtual
keyboard is used, where you can navigate and select inside.
So we have to fix the receiver.
*/
if ( ( object != m_data->inputItem )
&& qskIsAncestorOf( m_data->inputPanel, m_data->inputItem ) )
{
sendEventToInputItem( event );
return true;
}
}
return Inherited::eventFilter( object, event );
}
bool QskInputContext::filterEvent( const QEvent* event ) bool QskInputContext::filterEvent( const QEvent* event )
{ {
// called from QXcbKeyboard, but what about other platforms // called from QXcbKeyboard, but what about other platforms

View File

@ -57,6 +57,8 @@ private Q_SLOTS:
void handleCandidatesChanged(); void handleCandidatesChanged();
void setInputPanel( QQuickItem* ); void setInputPanel( QQuickItem* );
virtual bool eventFilter( QObject*, QEvent* ) override;
private: private:
void setInputItem( QQuickItem* ); void setInputItem( QQuickItem* );
QskInputCompositionModel* compositionModel() const; QskInputCompositionModel* compositionModel() const;

View File

@ -78,6 +78,9 @@ bool qskIsItemComplete( const QQuickItem* item )
bool qskIsAncestorOf( const QQuickItem* item, const QQuickItem* child ) bool qskIsAncestorOf( const QQuickItem* item, const QQuickItem* child )
{ {
if ( item == nullptr || child == nullptr )
return false;
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
return item->isAncestorOf( child ); return item->isAncestorOf( child );
#else #else

View File

@ -10,13 +10,7 @@
#include <QString> #include <QString>
#include <QLocale> #include <QLocale>
#include <QGuiApplication>
QSK_QT_PRIVATE_BEGIN
#include <private/qinputmethod_p.h>
QSK_QT_PRIVATE_END
#include <qpa/qplatformintegration.h>
#include <qpa/qplatforminputcontext.h>
QString qskNativeLocaleString( const QLocale& locale ) QString qskNativeLocaleString( const QLocale& locale )
{ {
@ -105,32 +99,6 @@ QString qskNativeLocaleString( const QLocale& locale )
} }
} }
static inline QQuickItem* qskInputItem()
{
QPlatformInputContext* inputContext;
#if 1
inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
#else
// for some reason the gcc sanitizer does not like this one
inputContext = QInputMethodPrivate::get( inputMethod )->platformInputContext();
#endif
QQuickItem* item = nullptr;
QMetaObject::invokeMethod( inputContext, "inputItem",
Qt::DirectConnection, Q_RETURN_ARG( QQuickItem*, item ) );
return item;
}
static inline void qskInstallEventFilter( QskInputPanel* panel, bool on )
{
if ( on )
qGuiApp->installEventFilter( panel );
else
qGuiApp->removeEventFilter( panel );
}
class QskInputPanel::PrivateData class QskInputPanel::PrivateData
{ {
public: public:
@ -201,57 +169,4 @@ void QskInputPanel::commitKey( Qt::Key key )
static_cast< QInputMethod::Action >( Compose ), key ); static_cast< QInputMethod::Action >( Compose ), key );
} }
void QskInputPanel::updateLayout()
{
if ( !isInitiallyPainted() )
qskInstallEventFilter( this, isVisible() );
Inherited::updateLayout();
}
void QskInputPanel::itemChange( QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData& value )
{
switch( change )
{
case QQuickItem::ItemVisibleHasChanged:
case QQuickItem::ItemSceneChange:
{
if ( isInitiallyPainted() )
qskInstallEventFilter( this, isVisible() );
break;
}
default:
break;
}
Inherited::itemChange( change, value );
}
bool QskInputPanel::eventFilter( QObject* object, QEvent* event )
{
if ( event->type() == QEvent::InputMethodQuery )
{
const auto item = qskInputItem();
/*
Qt/Quick expects that the item associated with the input context
always has the focus. But this does not work, when a virtual
keyboard is used, where you can navigate and select inside.
So we have to fix the receiver.
Maybe QEvent::EnterEditFocus is good for something ??
*/
if ( item && ( object != item ) && qskIsAncestorOf( this, item ) )
{
QGuiApplication::sendEvent( item, event );
return true;
}
}
return Inherited::eventFilter( object, event );
}
#include "moc_QskInputPanel.cpp" #include "moc_QskInputPanel.cpp"

View File

@ -38,11 +38,6 @@ public Q_SLOTS:
void setCandidatesEnabled( bool ); void setCandidatesEnabled( bool );
void setCandidates( const QVector< QString >& ); void setCandidates( const QVector< QString >& );
protected:
virtual void updateLayout() override;
virtual void itemChange( ItemChange, const ItemChangeData& ) override;
virtual bool eventFilter( QObject*, QEvent* ) override;
private: private:
void commitKey( Qt::Key ); void commitKey( Qt::Key );
void commitCandidate( int ); void commitCandidate( int );