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

View File

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

View File

@ -26,6 +26,8 @@ QskInputContext::QskInputContext():
connect( qskSetup, &QskSetup::inputPanelChanged, connect( qskSetup, &QskSetup::inputPanelChanged,
this, &QskInputContext::setInputPanel ); this, &QskInputContext::setInputPanel );
setInputPanel( qskSetup->inputPanel() ); setInputPanel( qskSetup->inputPanel() );
m_inputCompositionModel.reset( new QskInputCompositionModel );
} }
QskInputContext::~QskInputContext() QskInputContext::~QskInputContext()
@ -41,11 +43,11 @@ bool QskInputContext::isValid() const
void QskInputContext::update( Qt::InputMethodQueries queries ) void QskInputContext::update( Qt::InputMethodQueries queries )
{ {
if ( !m_focusObject ) if ( !m_inputItem )
return; return;
QInputMethodQueryEvent queryEvent( queries ); QInputMethodQueryEvent queryEvent( queries );
if ( !QCoreApplication::sendEvent( m_focusObject, &queryEvent ) ) if ( !QCoreApplication::sendEvent( m_inputItem, &queryEvent ) )
return; return;
// Qt::ImCursorRectangle // Qt::ImCursorRectangle
@ -209,10 +211,30 @@ void QskInputContext::setFocusObject( QObject* focusObject )
m_focusObject = focusObject; m_focusObject = focusObject;
if ( !m_focusObject ) if ( !m_focusObject )
{
m_inputItem = nullptr;
m_inputCompositionModel->setInputItem( nullptr );
return; 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 ); QInputMethodQueryEvent queryEvent( Qt::ImEnabled );
if ( !QCoreApplication::sendEvent( m_focusObject, &queryEvent ) ) if ( !QCoreApplication::sendEvent( m_inputItem, &queryEvent ) )
return; return;
if ( !queryEvent.value( Qt::ImEnabled ).toBool() ) if ( !queryEvent.value( Qt::ImEnabled ).toBool() )
@ -220,6 +242,7 @@ void QskInputContext::setFocusObject( QObject* focusObject )
hideInputPanel(); hideInputPanel();
return; return;
} }
}
m_focusObject->installEventFilter( this ); m_focusObject->installEventFilter( this );
update( Qt::InputMethodQuery( Qt::ImQueryAll & ~Qt::ImEnabled ) ); update( Qt::InputMethodQuery( Qt::ImQueryAll & ~Qt::ImEnabled ) );

View File

@ -8,6 +8,7 @@
#include <qpa/qplatforminputcontext.h> #include <qpa/qplatforminputcontext.h>
#include <QPointer> #include <QPointer>
#include <QQuickItem>
#include <memory> #include <memory>
@ -45,6 +46,7 @@ private Q_SLOTS:
private: private:
QPointer< QObject > m_focusObject; QPointer< QObject > m_focusObject;
QPointer< QQuickItem > m_inputItem;
QPointer< QskInputPanel > m_inputPanel; QPointer< QskInputPanel > m_inputPanel;
std::unique_ptr< QskInputCompositionModel > m_inputCompositionModel; 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: public:
TextInput( QQuickItem* parent ); TextInput( QQuickItem* parent );
virtual ~TextInput(); virtual ~TextInput() override;
protected:
void inputMethodEvent(QInputMethodEvent *) Q_DECL_OVERRIDE;
}; };
#endif // TEXTINPUT_H #endif // TEXTINPUT_H

View File

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