Android: implement batch editing for input methods

Task-number: QTBUG-37584
Change-Id: I59f063b2e4b6427a66f7b561cfae7193ceafa43c
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
bb10
Paul Olav Tvete 2014-03-26 16:45:24 +01:00 committed by The Qt Project
parent 9b28ab3f38
commit 3c6c14c0bf
3 changed files with 57 additions and 8 deletions

View File

@ -61,6 +61,8 @@ class QtExtractedText
class QtNativeInputConnection
{
static native boolean beginBatchEdit();
static native boolean endBatchEdit();
static native boolean commitText(String text, int newCursorPosition);
static native boolean commitCompletion(String text, int position);
static native boolean deleteSurroundingText(int leftLength, int rightLength);
@ -121,14 +123,14 @@ public class QtInputConnection extends BaseInputConnection
public boolean beginBatchEdit()
{
setClosing(false);
return true;
return QtNativeInputConnection.beginBatchEdit();
}
@Override
public boolean endBatchEdit()
{
setClosing(false);
return true;
return QtNativeInputConnection.endBatchEdit();
}
@Override

View File

@ -70,6 +70,35 @@ static jfieldID m_selectionStartFieldID = 0;
static jfieldID m_startOffsetFieldID = 0;
static jfieldID m_textFieldID = 0;
static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
{
if (!m_androidInputContext)
return JNI_FALSE;
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ BEGINBATCH";
#endif
return m_androidInputContext->beginBatchEdit();
return JNI_TRUE;
}
static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
{
if (!m_androidInputContext)
return JNI_FALSE;
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ ENDBATCH";
#endif
return m_androidInputContext->endBatchEdit();
return JNI_TRUE;
}
static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint newCursorPosition)
{
if (!m_androidInputContext)
@ -285,6 +314,8 @@ static jboolean updateCursorPosition(JNIEnv */*env*/, jobject /*thiz*/)
static JNINativeMethod methods[] = {
{"beginBatchEdit", "()Z", (void *)beginBatchEdit},
{"endBatchEdit", "()Z", (void *)endBatchEdit},
{"commitText", "(Ljava/lang/String;I)Z", (void *)commitText},
{"deleteSurroundingText", "(II)Z", (void *)deleteSurroundingText},
{"finishComposingText", "()Z", (void *)finishComposingText},
@ -306,7 +337,7 @@ static JNINativeMethod methods[] = {
QAndroidInputContext::QAndroidInputContext()
: QPlatformInputContext(), m_blockUpdateSelection(false)
: QPlatformInputContext(), m_blockUpdateSelection(false), m_batchEditNestingLevel(0)
{
QtAndroid::AttachedJNIEnv env;
if (!env.jniEnv)
@ -416,7 +447,7 @@ void QAndroidInputContext::commit()
void QAndroidInputContext::updateCursorPosition()
{
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (!query.isNull() && !m_blockUpdateSelection) {
if (!query.isNull() && !m_blockUpdateSelection && !m_batchEditNestingLevel) {
// make sure it also works with editors that have not been updated to the new API
QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt();
@ -507,6 +538,19 @@ void QAndroidInputContext::sendEvent(QObject *receiver, QInputMethodQueryEvent *
QCoreApplication::sendEvent(receiver, event);
}
jboolean QAndroidInputContext::beginBatchEdit()
{
++m_batchEditNestingLevel;
return JNI_TRUE;
}
jboolean QAndroidInputContext::endBatchEdit()
{
if (--m_batchEditNestingLevel == 0 && !m_blockUpdateSelection) //ending batch edit mode
updateCursorPosition();
return JNI_TRUE;
}
jboolean QAndroidInputContext::commitText(const QString &text, jint /*newCursorPosition*/)
{
m_composingText = text;
@ -610,7 +654,7 @@ QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
{
QVariant textBefore = queryFocusObjectThreadSafe(Qt::ImTextBeforeCursor, QVariant(length));
if (textBefore.isValid()) {
return textBefore.toString().left(length);
return textBefore.toString().left(length) + m_composingText;
}
//compatibility code for old controls that do not implement the new API
@ -624,7 +668,7 @@ QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
return text;
const int wordLeftPos = cursorPos - length;
return text.mid(wordLeftPos > 0 ? wordLeftPos : 0, cursorPos);
return text.mid(wordLeftPos > 0 ? wordLeftPos : 0, cursorPos) + m_composingText;
}
jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCursorPosition)
@ -647,11 +691,11 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur
sendInputMethodEvent(&event);
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (!query.isNull() && !m_blockUpdateSelection) {
if (!query.isNull() && !m_blockUpdateSelection && !m_batchEditNestingLevel) {
QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt();
const int preeditLength = text.length();
QtAndroidInput::updateSelection(cursorPos+preeditLength, cursorPos+preeditLength, cursorPos, cursorPos+preeditLength);
QtAndroidInput::updateSelection(cursorPos+preeditLength, cursorPos+preeditLength, -1, -1);
}
return JNI_TRUE;

View File

@ -97,6 +97,8 @@ public:
void clear();
//---------------//
jboolean beginBatchEdit();
jboolean endBatchEdit();
jboolean commitText(const QString &text, jint newCursorPosition);
jboolean deleteSurroundingText(jint leftLength, jint rightLength);
jboolean finishComposingText();
@ -133,6 +135,7 @@ private:
QString m_composingText;
QMetaObject::Connection m_updateCursorPosConnection;
bool m_blockUpdateSelection;
int m_batchEditNestingLevel;
};
QT_END_NAMESPACE