diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java index 399a9b7600a..f445810ee62 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java @@ -4,9 +4,11 @@ package org.qtproject.qt.android; +import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.util.Log; +import android.view.inputmethod.TextAttribute; import android.view.WindowMetrics; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; @@ -41,6 +43,7 @@ class QtNativeInputConnection static native String getSelectedText(int flags); static native String getTextAfterCursor(int length, int flags); static native String getTextBeforeCursor(int length, int flags); + static native boolean replaceText(int start, int end, String text, int newCursorPosition); static native boolean setComposingText(String text, int newCursorPosition); static native boolean setComposingRegion(int start, int end); static native boolean setSelection(int start, int end); @@ -317,6 +320,35 @@ class QtInputConnection extends BaseInputConnection return QtNativeInputConnection.setComposingText(text.toString(), newCursorPosition); } + @TargetApi(33) + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition, TextAttribute textAttribute) + { + return setComposingText(text, newCursorPosition); + } + + @TargetApi(33) + @Override + public boolean setComposingRegion(int start, int end, TextAttribute textAttribute) + { + return setComposingRegion(start, end); + } + + @TargetApi(33) + @Override + public boolean commitText(CharSequence text, int newCursorPosition, TextAttribute textAttribute) + { + return commitText(text, newCursorPosition); + } + + @TargetApi(34) + @Override + public boolean replaceText(int start, int end, CharSequence text, int newCursorPosition, TextAttribute textAttribute) + { + setClosing(false); + return QtNativeInputConnection.replaceText(start, end, text.toString(), newCursorPosition); + } + @Override public boolean setComposingRegion(int start, int end) { diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 62212ff63d7..24742160bf9 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -137,6 +137,23 @@ static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/) return res; } +static jboolean replaceText(JNIEnv *env, jobject /*thiz*/, jint start, jint end, jstring text, jint newCursorPosition) +{ + if (!m_androidInputContext) + return JNI_FALSE; + + jboolean isCopy; + const jchar *jstr = env->GetStringChars(text, &isCopy); + QString str(reinterpret_cast(jstr), env->GetStringLength(text)); + env->ReleaseStringChars(text, jstr); + + qCDebug(lcQpaInputMethods) << "@@@ REPLACE" << start << end << str << newCursorPosition; + jboolean res = JNI_FALSE; + runOnQtThread([&]{res = m_androidInputContext->replaceText(start, end, str, newCursorPosition);}); + + return res; +} + static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes) { if (!m_androidInputContext) @@ -336,6 +353,7 @@ static JNINativeMethod methods[] = { {"getSelectedText", "(I)Ljava/lang/String;", (void *)getSelectedText}, {"getTextAfterCursor", "(II)Ljava/lang/String;", (void *)getTextAfterCursor}, {"getTextBeforeCursor", "(II)Ljava/lang/String;", (void *)getTextBeforeCursor}, + {"replaceText", "(IILjava/lang/String;I)Z", (void *)replaceText}, {"setComposingText", "(Ljava/lang/String;I)Z", (void *)setComposingText}, {"setComposingRegion", "(II)Z", (void *)setComposingRegion}, {"setSelection", "(II)Z", (void *)setSelection}, @@ -1123,6 +1141,21 @@ jboolean QAndroidInputContext::finishComposingText() return JNI_TRUE; } +/* + Android docs say: This behaves like calling finishComposingText(), setSelection(start, end) + and then commitText(text, newCursorPosition, textAttribute) + https://developer.android.com/reference/android/view/inputmethod/InputConnection#replaceText(int,%20int,%20java.lang.CharSequence,%20int,%20android.view.inputmethod.TextAttribute) +*/ +jboolean QAndroidInputContext::replaceText(jint start, jint end, const QString text, jint newCursorPosition) +{ + if (!finishComposingText()) + return JNI_FALSE; + if (!setSelection(start, end)) + return JNI_FALSE; + + return commitText(text, newCursorPosition); +} + void QAndroidInputContext::reportFullscreenMode(jboolean enabled) { m_fullScreenMode = enabled; diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h index 038286c4b88..85409a1f962 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.h +++ b/src/plugins/platforms/android/qandroidinputcontext.h @@ -92,6 +92,7 @@ public: QString getSelectedText(jint flags); QString getTextAfterCursor(jint length, jint flags); QString getTextBeforeCursor(jint length, jint flags); + jboolean replaceText(jint start, jint end, const QString text, jint newCursorPosition); jboolean setComposingText(const QString &text, jint newCursorPosition); jboolean setComposingRegion(jint start, jint end); jboolean setSelection(jint start, jint end);