Commit ed576da6 authored by Pekka Vuorela's avatar Pekka Vuorela Committed by Qt by Nokia

Enhance editors notifying input panel for input method changes

Introduced protected QQuickItem::updateInputMethod() and removed
similar, but badly named updateMicroFocus(). Added some missing
notifications from the editors and avoided unnecessary updates when not
having focus.

Change-Id: Id5c00e87dc26fd35c3f919006817511d4ed6418d
Reviewed-by: default avatarAndrew den Exter <andrew.den-exter@nokia.com>
Reviewed-by: default avatarJoona Petrell <joona.t.petrell@nokia.com>
parent 8aa187fe
......@@ -3081,13 +3081,6 @@ void QQuickItem::setInputMethodHints(Qt::InputMethodHints hints)
qApp->inputPanel()->update(Qt::ImHints);
}
void QQuickItem::updateMicroFocus()
{
QInputPanel *p = qApp->inputPanel();
if (p->inputItem() == this)
qApp->inputPanel()->update(Qt::ImQueryInput);
}
QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
{
Q_D(const QQuickItem);
......@@ -3608,6 +3601,15 @@ void QQuickItem::itemChange(ItemChange change, const ItemChangeData &value)
Q_UNUSED(value);
}
/*!
Notify input method on updated query values if needed. \a indicates changed attributes.
*/
void QQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
{
if (hasActiveFocus())
qApp->inputPanel()->update(queries);
}
/*! \internal */
// XXX todo - do we want/need this anymore?
// Note that it's now used for varying clip rect
......
......@@ -324,7 +324,6 @@ public:
public Q_SLOTS:
void update();
void updateMicroFocus();
Q_SIGNALS:
void childrenRectChanged(const QRectF &);
......@@ -359,6 +358,8 @@ protected:
bool isComponentComplete() const;
virtual void itemChange(ItemChange, const ItemChangeData &);
void updateInputMethod(Qt::InputMethodQueries queries = Qt::ImQueryInput);
void setImplicitWidth(qreal);
bool widthValid() const; // ### better name?
void setImplicitHeight(qreal);
......
......@@ -373,6 +373,7 @@ void QQuickTextEdit::setFont(const QFont &font)
}
updateSize();
updateDocument();
updateInputMethod(Qt::ImCursorRectangle | Qt::ImFont);
}
emit fontChanged(d->sourceFont);
}
......@@ -1248,6 +1249,7 @@ void QQuickTextEdit::setReadOnly(bool r)
if (!r)
d->control->moveCursor(QTextCursor::End);
updateInputMethod(Qt::ImEnabled);
q_canPasteChanged();
emit readOnlyChanged(r);
}
......@@ -1853,7 +1855,7 @@ void QQuickTextEdit::moveCursorDelegate()
{
Q_D(QQuickTextEdit);
d->determineHorizontalAlignment();
updateMicroFocus();
updateInputMethod();
emit cursorRectangleChanged();
if (!d->cursor)
return;
......
......@@ -306,7 +306,7 @@ void QQuickTextInput::setFont(const QFont &font)
if (oldFont != d->font) {
d->updateLayout();
updateCursorRectangle();
qApp->inputPanel()->update(Qt::ImCursorRectangle | Qt::ImFont);
updateInputMethod(Qt::ImCursorRectangle | Qt::ImFont);
}
emit fontChanged(d->sourceFont);
}
......@@ -575,6 +575,7 @@ void QQuickTextInput::setReadOnly(bool ro)
d->m_readOnly = ro;
if (!ro)
d->setCursorPosition(d->end());
updateInputMethod(Qt::ImEnabled);
q_canPasteChanged();
d->emitUndoRedoChanged();
emit readOnlyChanged(ro);
......@@ -2508,6 +2509,7 @@ void QQuickTextInput::updateCursorRectangle()
d->cursorItem->setPos(r.topLeft());
d->cursorItem->setHeight(r.height());
}
updateInputMethod(Qt::ImCursorRectangle);
}
void QQuickTextInput::selectionChanged()
......@@ -2873,8 +2875,8 @@ void QQuickTextInputPrivate::setSelection(int start, int length)
}
emit q->selectionChanged();
emitCursorPositionChanged();
qApp->inputPanel()->update(Qt::ImCursorRectangle | Qt::ImAnchorPosition
| Qt::ImCursorPosition | Qt::ImCurrentSelection);
q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorPosition
| Qt::ImCursorPosition | Qt::ImCurrentSelection);
}
/*!
......@@ -2964,7 +2966,7 @@ void QQuickTextInputPrivate::moveCursor(int pos, bool mark)
emit q->selectionChanged();
}
emitCursorPositionChanged();
q->updateMicroFocus();
q->updateInputMethod();
}
/*!
......@@ -3065,7 +3067,6 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
emitCursorPositionChanged();
} else if (m_preeditCursor != oldPreeditCursor) {
q->updateCursorRectangle();
qApp->inputPanel()->update(Qt::ImCursorRectangle);
}
bool tentativeCommitChanged = m_tentativeCommit != event->tentativeCommitString();
......@@ -3080,8 +3081,8 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
if (selectionChange) {
emit q->selectionChanged();
qApp->inputPanel()->update(Qt::ImCursorRectangle | Qt::ImAnchorPosition
| Qt::ImCursorPosition | Qt::ImCurrentSelection);
q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorPosition
| Qt::ImCursorPosition | Qt::ImCurrentSelection);
}
}
......@@ -3123,7 +3124,7 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo
Q_Q(QQuickTextInput);
Q_UNUSED(update)
bool notifyInputPanel = m_textDirty || m_selDirty;
bool inputMethodAttributesChanged = m_textDirty || m_selDirty;
bool alignmentChanged = false;
if (m_textDirty) {
......@@ -3194,9 +3195,9 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo
emit q->selectionChanged();
}
notifyInputPanel |= (m_cursor == m_lastCursorPos);
if (notifyInputPanel)
q->updateMicroFocus();
inputMethodAttributesChanged |= (m_cursor == m_lastCursorPos);
if (inputMethodAttributesChanged)
q->updateInputMethod();
emitUndoRedoChanged();
if (!emitCursorPositionChanged() && alignmentChanged)
......
......@@ -144,6 +144,7 @@ private slots:
void canPaste();
void canPasteEmpty();
void textInput();
void inputPanelUpdate();
void openInputPanel();
void geometrySignals();
void pastingRichText_QTBUG_14003();
......@@ -226,7 +227,7 @@ void tst_qquicktextedit::simulateKeys(QWindow *window, const QList<Key> &keys)
void tst_qquicktextedit::simulateKeys(QWindow *window, const QKeySequence &sequence)
{
for (uint i = 0; i < sequence.count(); ++i) {
for (int i = 0; i < sequence.count(); ++i) {
const int key = sequence[i];
const int modifiers = key & Qt::KeyboardModifierMask;
......@@ -236,7 +237,7 @@ void tst_qquicktextedit::simulateKeys(QWindow *window, const QKeySequence &seque
QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
{
for (uint i = 0; i < sequence.count(); ++i)
for (int i = 0; i < sequence.count(); ++i)
keys << Key(sequence[i], QChar());
return keys;
}
......@@ -2131,6 +2132,100 @@ void tst_qquicktextedit::textInput()
QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event2);
QCOMPARE(spy.count(), 1);
QCOMPARE(edit->text(), QString("string"));
QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &queryEvent);
QCOMPARE(queryEvent.value(Qt::ImEnabled).toBool(), true);
edit->setReadOnly(true);
QGuiApplication::sendEvent(edit, &queryEvent);
QCOMPARE(queryEvent.value(Qt::ImEnabled).toBool(), false);
}
void tst_qquicktextedit::inputPanelUpdate()
{
PlatformInputContext platformInputContext;
QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
inputPanelPrivate->testContext = &platformInputContext;
QQuickView view(testFileUrl("inputMethodEvent.qml"));
view.show();
view.requestActivateWindow();
QTest::qWaitForWindowShown(&view);
QTRY_COMPARE(&view, qGuiApp->focusWindow());
QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
QVERIFY(edit);
QVERIFY(edit->hasActiveFocus() == true);
// text change even without cursor position change needs to trigger update
edit->setText("test");
platformInputContext.clear();
edit->setText("xxxx");
QVERIFY(platformInputContext.m_updateCallCount > 0);
// input method event replacing text
platformInputContext.clear();
{
QInputMethodEvent inputMethodEvent;
inputMethodEvent.setCommitString("y", -1, 1);
QGuiApplication::sendEvent(edit, &inputMethodEvent);
}
QVERIFY(platformInputContext.m_updateCallCount > 0);
// input method changing selection
platformInputContext.clear();
{
QList<QInputMethodEvent::Attribute> attributes;
attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 2, QVariant());
QInputMethodEvent inputMethodEvent("", attributes);
QGuiApplication::sendEvent(edit, &inputMethodEvent);
}
QVERIFY(edit->selectionStart() != edit->selectionEnd());
QVERIFY(platformInputContext.m_updateCallCount > 0);
// font changes
platformInputContext.clear();
QFont font = edit->font();
font.setBold(!font.bold());
edit->setFont(font);
QVERIFY(platformInputContext.m_updateCallCount > 0);
// normal input
platformInputContext.clear();
{
QInputMethodEvent inputMethodEvent;
inputMethodEvent.setCommitString("y");
QGuiApplication::sendEvent(edit, &inputMethodEvent);
}
QVERIFY(platformInputContext.m_updateCallCount > 0);
// changing cursor position
platformInputContext.clear();
edit->setCursorPosition(0);
QVERIFY(platformInputContext.m_updateCallCount > 0);
// continuing with selection
platformInputContext.clear();
edit->moveCursorSelection(1);
QVERIFY(platformInputContext.m_updateCallCount > 0);
// read only disabled input method
platformInputContext.clear();
edit->setReadOnly(true);
QVERIFY(platformInputContext.m_updateCallCount > 0);
edit->setReadOnly(false);
// no updates while no focus
edit->setFocus(false);
platformInputContext.clear();
edit->setText("Foo");
QCOMPARE(platformInputContext.m_updateCallCount, 0);
edit->setCursorPosition(1);
QCOMPARE(platformInputContext.m_updateCallCount, 0);
edit->selectAll();
QCOMPARE(platformInputContext.m_updateCallCount, 0);
edit->setReadOnly(true);
QCOMPARE(platformInputContext.m_updateCallCount, 0);
}
void tst_qquicktextedit::openInputPanel()
......
......@@ -222,7 +222,7 @@ void tst_qquicktextinput::simulateKeys(QWindow *window, const QList<Key> &keys)
void tst_qquicktextinput::simulateKeys(QWindow *window, const QKeySequence &sequence)
{
for (uint i = 0; i < sequence.count(); ++i) {
for (int i = 0; i < sequence.count(); ++i) {
const int key = sequence[i];
const int modifiers = key & Qt::KeyboardModifierMask;
......@@ -232,7 +232,7 @@ void tst_qquicktextinput::simulateKeys(QWindow *window, const QKeySequence &sequ
QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
{
for (uint i = 0; i < sequence.count(); ++i)
for (int i = 0; i < sequence.count(); ++i)
keys << Key(sequence[i], QChar());
return keys;
}
......@@ -1951,6 +1951,14 @@ void tst_qquicktextinput::inputMethods()
event.setCommitString("replacement", -input->text().length(), input->text().length());
QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &event);
QCOMPARE(input->selectionStart(), input->selectionEnd());
QInputMethodQueryEvent enabledQueryEvent(Qt::ImEnabled);
QGuiApplication::sendEvent(input, &enabledQueryEvent);
QCOMPARE(enabledQueryEvent.value(Qt::ImEnabled).toBool(), true);
input->setReadOnly(true);
QGuiApplication::sendEvent(input, &enabledQueryEvent);
QCOMPARE(enabledQueryEvent.value(Qt::ImEnabled).toBool(), false);
}
/*
......@@ -3081,6 +3089,24 @@ void tst_qquicktextinput::inputPanelUpdate()
platformInputContext.clear();
input->setCursorPosition(0);
QVERIFY(platformInputContext.m_updateCallCount > 0);
// read only disabled input method
platformInputContext.clear();
input->setReadOnly(true);
QVERIFY(platformInputContext.m_updateCallCount > 0);
input->setReadOnly(false);
// no updates while no focus
input->setFocus(false);
platformInputContext.clear();
input->setText("Foo");
QCOMPARE(platformInputContext.m_updateCallCount, 0);
input->setCursorPosition(1);
QCOMPARE(platformInputContext.m_updateCallCount, 0);
input->selectAll();
QCOMPARE(platformInputContext.m_updateCallCount, 0);
input->setReadOnly(true);
QCOMPARE(platformInputContext.m_updateCallCount, 0);
}
void tst_qquicktextinput::cursorRectangleSize()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment