Fix input panel event propagation

This commit is contained in:
Peter Hartmann 2018-03-14 17:30:39 +01:00
parent e365592457
commit 5a250eff8b
7 changed files with 71 additions and 22 deletions

View File

@ -37,20 +37,20 @@ static QString qskKeyString( int code )
class QskInputCompositionModel::PrivateData
{
public:
PrivateData() :
inputItem( nullptr ),
groupIndex( 0 )
{
}
// QInputMethod
QString preedit;
QTextCharFormat preeditFormat;
QList< QInputMethodEvent::Attribute > preeditAttributes;
QObject* inputItem;
int groupIndex;
};
static inline void sendCompositionEvent( QInputMethodEvent* e )
{
if ( auto focusObject = QGuiApplication::focusObject() )
QCoreApplication::sendEvent( focusObject, e );
}
QskInputCompositionModel::QskInputCompositionModel():
m_data( new PrivateData )
{
@ -77,7 +77,7 @@ void QskInputCompositionModel::composeKey( Qt::Key key )
QInputMethodQueryEvent queryEvent(
Qt::ImSurroundingText | Qt::ImMaximumTextLength | Qt::ImHints );
QCoreApplication::sendEvent( focusObject, &queryEvent );
QCoreApplication::sendEvent( m_data->inputItem, &queryEvent );
const auto hints = static_cast< Qt::InputMethodHints >(
queryEvent.value( Qt::ImHints ).toInt() );
const int maxLength = queryEvent.value( Qt::ImMaximumTextLength ).toInt();
@ -237,8 +237,8 @@ void QskInputCompositionModel::backspace()
// Backspace one character only if preedit was inactive
QKeyEvent keyPress( QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier );
QKeyEvent keyRelease( QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier );
QCoreApplication::sendEvent( focusWindow, &keyPress );
QCoreApplication::sendEvent( focusWindow, &keyRelease );
QCoreApplication::sendEvent( m_data->inputItem, &keyPress );
QCoreApplication::sendEvent( m_data->inputItem, &keyRelease );
return;
}
@ -267,6 +267,12 @@ void QskInputCompositionModel::moveCursor( Qt::Key key )
QCoreApplication::sendEvent( focusWindow, &moveCursorRelease );
}
void QskInputCompositionModel::sendCompositionEvent( QInputMethodEvent* e )
{
if ( m_data->inputItem )
QCoreApplication::sendEvent( m_data->inputItem, e );
}
bool QskInputCompositionModel::hasIntermediate() const
{
return false;
@ -300,6 +306,11 @@ QVector< Qt::Key > QskInputCompositionModel::groups() const
return QVector< Qt::Key >();
}
void QskInputCompositionModel::setInputItem( QObject *inputItem )
{
m_data->inputItem = inputItem;
}
bool QskInputCompositionModel::nextGroupIndex(int& index, bool forward) const
{
Q_UNUSED(index);

View File

@ -10,6 +10,7 @@
#include <memory>
class QInputMethodEvent;
class QStringList;
class QskInputCompositionModel : public QObject
@ -37,6 +38,8 @@ public:
virtual QVector< Qt::Key > groups() const;
void setInputItem( QObject* inputItem );
protected:
// Used for text composition
virtual bool hasIntermediate() const;
@ -50,6 +53,7 @@ Q_SIGNALS:
private:
void backspace();
void moveCursor( Qt::Key key );
void sendCompositionEvent( QInputMethodEvent* e );
class PrivateData;
std::unique_ptr< PrivateData > m_data;

View File

@ -26,6 +26,8 @@ QskInputContext::QskInputContext():
connect( qskSetup, &QskSetup::inputPanelChanged,
this, &QskInputContext::setInputPanel );
setInputPanel( qskSetup->inputPanel() );
m_inputCompositionModel.reset( new QskInputCompositionModel );
}
QskInputContext::~QskInputContext()
@ -41,11 +43,11 @@ bool QskInputContext::isValid() const
void QskInputContext::update( Qt::InputMethodQueries queries )
{
if ( !m_focusObject )
if ( !m_inputItem )
return;
QInputMethodQueryEvent queryEvent( queries );
if ( !QCoreApplication::sendEvent( m_focusObject, &queryEvent ) )
if ( !QCoreApplication::sendEvent( m_inputItem, &queryEvent ) )
return;
// Qt::ImCursorRectangle
@ -209,18 +211,39 @@ void QskInputContext::setFocusObject( QObject* focusObject )
m_focusObject = focusObject;
if ( !m_focusObject )
return;
QInputMethodQueryEvent queryEvent( Qt::ImEnabled );
if ( !QCoreApplication::sendEvent( m_focusObject, &queryEvent ) )
return;
if ( !queryEvent.value( Qt::ImEnabled ).toBool() )
{
hideInputPanel();
m_inputItem = nullptr;
m_inputCompositionModel->setInputItem( nullptr );
return;
}
bool inputItemChanged = false;
auto focusQuickItem = qobject_cast< QQuickItem* >( focusObject );
if( focusQuickItem )
{
// Do not change the input item when panel buttons get the focus:
if( qskNearestFocusScope( focusQuickItem ) != m_inputPanel )
{
m_inputItem = focusQuickItem;
m_inputCompositionModel->setInputItem( m_inputItem ); // ### use a signal/slot connection
inputItemChanged = true;
}
}
if( inputItemChanged )
{
QInputMethodQueryEvent queryEvent( Qt::ImEnabled );
if ( !QCoreApplication::sendEvent( m_inputItem, &queryEvent ) )
return;
if ( !queryEvent.value( Qt::ImEnabled ).toBool() )
{
hideInputPanel();
return;
}
}
m_focusObject->installEventFilter( this );
update( Qt::InputMethodQuery( Qt::ImQueryAll & ~Qt::ImEnabled ) );
}

View File

@ -8,6 +8,7 @@
#include <qpa/qplatforminputcontext.h>
#include <QPointer>
#include <QQuickItem>
#include <memory>
@ -45,6 +46,7 @@ private Q_SLOTS:
private:
QPointer< QObject > m_focusObject;
QPointer< QQuickItem > m_inputItem;
QPointer< QskInputPanel > m_inputPanel;
std::unique_ptr< QskInputCompositionModel > m_inputCompositionModel;
};

View File

@ -10,3 +10,8 @@ TextInput::~TextInput()
{
}
void TextInput::inputMethodEvent(QInputMethodEvent *event)
{
QQuickTextInput::inputMethodEvent(event);
}

View File

@ -7,7 +7,10 @@ class TextInput : public QQuickTextInput
{
public:
TextInput( QQuickItem* parent );
virtual ~TextInput();
virtual ~TextInput() override;
protected:
void inputMethodEvent(QInputMethodEvent *) Q_DECL_OVERRIDE;
};
#endif // TEXTINPUT_H

View File

@ -148,8 +148,6 @@ QskKeyButton::QskKeyButton( int keyIndex, QskInputPanel* inputPanel, QQuickItem*
m_keyIndex( keyIndex ),
m_inputPanel( inputPanel )
{
setFlag( QQuickItem::ItemAcceptsInputMethod );
updateText();
connect( this, &QskKeyButton::pressed, this, [ this ]()
@ -248,6 +246,9 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
QObject::connect( this, &QskControl::localeChanged,
this, &QskInputPanel::updateLocale );
setFlag( ItemIsFocusScope, true );
setTabFence( true );
}
QskInputPanel::~QskInputPanel()