QAndroidInputContext: Fix getTextBefore/AfterCursor() in mid. of preedit

getTextBeforeCursor() and getTextAfterCursor() were not properly
handling the case when the cursor is in the middle of preedit string
(just as TODO comments inside these functions were saying). This was
causing problems with Gboard when the user focuses a text editor by
tapping in the middle of a word.

Fixes: QTBUG-58063
Change-Id: I4a580a74d79965816557bfb342337975348d1c45
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
This commit is contained in:
Vova Mshanetskiy 2019-05-08 13:56:29 +03:00
parent d0741f4267
commit 8ea3300a08

View File

@ -1129,46 +1129,63 @@ QString QAndroidInputContext::getSelectedText(jint /*flags*/)
QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/)
{
//### the preedit text could theoretically be after the cursor
QVariant textAfter = QInputMethod::queryFocusObject(Qt::ImTextAfterCursor, QVariant(length));
if (textAfter.isValid()) {
return textAfter.toString().left(length);
}
//compatibility code for old controls that do not implement the new API
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
if (length <= 0)
return QString();
QString text = query->value(Qt::ImSurroundingText).toString();
if (!text.length())
return text;
QString text;
int cursorPos = query->value(Qt::ImCursorPosition).toInt();
return text.mid(cursorPos, length);
QVariant reportedTextAfter = QInputMethod::queryFocusObject(Qt::ImTextAfterCursor, length);
if (reportedTextAfter.isValid()) {
text = reportedTextAfter.toString();
} else {
// Compatibility code for old controls that do not implement the new API
QSharedPointer<QInputMethodQueryEvent> query =
focusObjectInputMethodQuery(Qt::ImCursorPosition | Qt::ImSurroundingText);
if (query) {
const int cursorPos = query->value(Qt::ImCursorPosition).toInt();
text = query->value(Qt::ImSurroundingText).toString().mid(cursorPos);
}
}
// Controls do not report preedit text, so we have to add it
if (!m_composingText.isEmpty()) {
const int cursorPosInsidePreedit = m_composingCursor - m_composingTextStart;
text = m_composingText.midRef(cursorPosInsidePreedit) + text;
}
text.truncate(length);
return text;
}
QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
{
QVariant textBefore = QInputMethod::queryFocusObject(Qt::ImTextBeforeCursor, QVariant(length));
if (textBefore.isValid())
return textBefore.toString().rightRef(length) + m_composingText;
//compatibility code for old controls that do not implement the new API
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
if (length <= 0)
return QString();
int cursorPos = query->value(Qt::ImCursorPosition).toInt();
QString text = query->value(Qt::ImSurroundingText).toString();
if (!text.length())
return text;
QString text;
//### the preedit text does not need to be immediately before the cursor
if (cursorPos <= length)
return text.leftRef(cursorPos) + m_composingText;
else
return text.midRef(cursorPos - length, length) + m_composingText;
QVariant reportedTextBefore = QInputMethod::queryFocusObject(Qt::ImTextBeforeCursor, length);
if (reportedTextBefore.isValid()) {
text = reportedTextBefore.toString();
} else {
// Compatibility code for old controls that do not implement the new API
QSharedPointer<QInputMethodQueryEvent> query =
focusObjectInputMethodQuery(Qt::ImCursorPosition | Qt::ImSurroundingText);
if (query) {
const int cursorPos = query->value(Qt::ImCursorPosition).toInt();
text = query->value(Qt::ImSurroundingText).toString().left(cursorPos);
}
}
// Controls do not report preedit text, so we have to add it
if (!m_composingText.isEmpty()) {
const int cursorPosInsidePreedit = m_composingCursor - m_composingTextStart;
text += m_composingText.leftRef(cursorPosInsidePreedit);
}
if (text.length() > length)
text = text.right(length);
return text;
}
/*