Android: input method fixes for SwiftEdit keyboard

* Report correct pre-edit information when calling updateSelection()
  on endBatchEdit()
* Fix getExtractedText() to report the correct offset and cursor position,
* Fix setSelection() to use the correct cursor position.

Task-number: QTBUG-35689

Change-Id: I7e8427d0f5a18abf18ba2faf9d510756ddf6044b
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
This commit is contained in:
Paul Olav Tvete 2014-03-28 17:16:58 +01:00 committed by The Qt Project
parent e432787ad0
commit eccf1c51a6

View File

@ -150,12 +150,13 @@ static jobject getExtractedText(JNIEnv *env, jobject /*thiz*/, int hintMaxChars,
if (!m_androidInputContext) if (!m_androidInputContext)
return 0; return 0;
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ GETEX";
#endif
const QAndroidInputContext::ExtractedText &extractedText = const QAndroidInputContext::ExtractedText &extractedText =
m_androidInputContext->getExtractedText(hintMaxChars, hintMaxLines, flags); m_androidInputContext->getExtractedText(hintMaxChars, hintMaxLines, flags);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ GETEX" << hintMaxChars << hintMaxLines << QString::fromLatin1("0x") + QString::number(flags,16) << extractedText.text << "partOff:" << extractedText.partialStartOffset << extractedText.partialEndOffset << "sel:" << extractedText.selectionStart << extractedText.selectionEnd << "offset:" << extractedText.startOffset;
#endif
jobject object = env->NewObject(m_extractedTextClass, m_classConstructorMethodID); jobject object = env->NewObject(m_extractedTextClass, m_classConstructorMethodID);
env->SetIntField(object, m_partialStartOffsetFieldID, extractedText.partialStartOffset); env->SetIntField(object, m_partialStartOffsetFieldID, extractedText.partialStartOffset);
env->SetIntField(object, m_partialEndOffsetFieldID, extractedText.partialEndOffset); env->SetIntField(object, m_partialEndOffsetFieldID, extractedText.partialEndOffset);
@ -451,7 +452,10 @@ void QAndroidInputContext::updateCursorPosition()
// make sure it also works with editors that have not been updated to the new API // make sure it also works with editors that have not been updated to the new API
QVariant absolutePos = query->value(Qt::ImAbsolutePosition); QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt(); const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt();
QtAndroidInput::updateSelection(cursorPos, cursorPos, -1, -1); //selection empty and no pre-edit text const int composeLength = m_composingText.length();
const int composeStart = composeLength ? cursorPos : -1;
QtAndroidInput::updateSelection(cursorPos + composeLength, cursorPos + composeLength, //empty selection
composeStart, composeStart + composeLength); // pre-edit text
} }
} }
@ -603,19 +607,39 @@ jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/)
const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedText(jint hintMaxChars, jint /*hintMaxLines*/, jint /*flags*/) const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedText(jint hintMaxChars, jint /*hintMaxLines*/, jint /*flags*/)
{ {
// Note to self: "if the GET_EXTRACTED_TEXT_MONITOR flag is set, you should be calling
// updateExtractedText(View, int, ExtractedText) whenever you call
// updateSelection(View, int, int, int, int)." QTBUG-37980
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery(); QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull()) if (query.isNull())
return m_extractedText; return m_extractedText;
if (hintMaxChars) int localPos = query->value(Qt::ImCursorPosition).toInt(); //position before pre-edit text relative to the current block
m_extractedText.text = query->value(Qt::ImSurroundingText).toString().right(hintMaxChars); QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
int blockPos = absolutePos.isValid() ? absolutePos.toInt() - localPos : 0; // position of the start of the current block
QString blockText = query->value(Qt::ImSurroundingText).toString() + m_composingText;
int composeLength = m_composingText.length();
int cpos = localPos + composeLength; //actual cursor pos relative to the current block
int localOffset = 0; // start of extracted text relative to the current block
if (hintMaxChars) {
if (cpos > hintMaxChars)
localOffset = cpos - hintMaxChars;
m_extractedText.text = blockText.mid(localOffset, hintMaxChars);
}
m_extractedText.startOffset = blockPos + localOffset; // "The offset in the overall text at which the extracted text starts."
m_extractedText.startOffset = query->value(Qt::ImCursorPosition).toInt();
const QString &selection = query->value(Qt::ImCurrentSelection).toString(); const QString &selection = query->value(Qt::ImCurrentSelection).toString();
const int selLen = selection.length(); const int selLen = selection.length();
if (selLen) { if (selLen) {
m_extractedText.selectionStart = query->value(Qt::ImAnchorPosition).toInt(); m_extractedText.selectionStart = query->value(Qt::ImAnchorPosition).toInt() - localOffset;
m_extractedText.selectionEnd = m_extractedText.startOffset; m_extractedText.selectionEnd = m_extractedText.selectionStart + selLen;
} else {
m_extractedText.selectionStart = cpos - localOffset;
m_extractedText.selectionEnd = cpos - localOffset;
} }
return m_extractedText; return m_extractedText;
@ -757,9 +781,17 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
jboolean QAndroidInputContext::setSelection(jint start, jint end) jboolean QAndroidInputContext::setSelection(jint start, jint end)
{ {
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_FALSE;
int localPos = query->value(Qt::ImCursorPosition).toInt();
QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
int blockPosition = absolutePos.isValid() ? absolutePos.toInt() - localPos : 0;
QList<QInputMethodEvent::Attribute> attributes; QList<QInputMethodEvent::Attribute> attributes;
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
start, start - blockPosition,
end - start, end - start,
QVariant())); QVariant()));