summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java7
-rw-r--r--src/plugins/platforms/android/src/qandroidinputcontext.cpp112
-rw-r--r--src/plugins/platforms/android/src/qandroidinputcontext.h2
3 files changed, 118 insertions, 3 deletions
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
index 3bcec030b5..f251369737 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
@@ -73,6 +73,7 @@ class QtNativeInputConnection
static native String getTextAfterCursor(int length, int flags);
static native String getTextBeforeCursor(int length, int flags);
static native boolean setComposingText(String text, int newCursorPosition);
+ static native boolean setComposingRegion(int start, int end);
static native boolean setSelection(int start, int end);
static native boolean selectAll();
static native boolean cut();
@@ -237,6 +238,12 @@ public class QtInputConnection extends BaseInputConnection
}
@Override
+ public boolean setComposingRegion(int start, int end)
+ {
+ return QtNativeInputConnection.setComposingRegion(start, end);
+ }
+
+ @Override
public boolean setSelection(int start, int end)
{
return QtNativeInputConnection.setSelection(start, end);
diff --git a/src/plugins/platforms/android/src/qandroidinputcontext.cpp b/src/plugins/platforms/android/src/qandroidinputcontext.cpp
index 1981ac0b75..386c8e006a 100644
--- a/src/plugins/platforms/android/src/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/src/qandroidinputcontext.cpp
@@ -54,6 +54,8 @@
#include <QTextCharFormat>
+#include <QDebug>
+
QT_BEGIN_NAMESPACE
static QAndroidInputContext *m_androidInputContext = 0;
@@ -78,6 +80,9 @@ static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint new
QString str(reinterpret_cast<const QChar *>(jstr), env->GetStringLength(text));
env->ReleaseStringChars(text, jstr);
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ COMMIT" << str;
+#endif
return m_androidInputContext->commitText(str, newCursorPosition);
}
@@ -86,6 +91,9 @@ static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint le
if (!m_androidInputContext)
return JNI_FALSE;
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ DELETE" << leftLength << rightLength;
+#endif
return m_androidInputContext->deleteSurroundingText(leftLength, rightLength);
}
@@ -94,6 +102,9 @@ static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/)
if (!m_androidInputContext)
return JNI_FALSE;
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ FINISH";
+#endif
return m_androidInputContext->finishComposingText();
}
@@ -110,6 +121,9 @@ static jobject getExtractedText(JNIEnv *env, jobject /*thiz*/, int hintMaxChars,
if (!m_androidInputContext)
return 0;
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ GETEX";
+#endif
const QAndroidInputContext::ExtractedText &extractedText =
m_androidInputContext->getExtractedText(hintMaxChars, hintMaxLines, flags);
@@ -133,6 +147,9 @@ static jstring getSelectedText(JNIEnv *env, jobject /*thiz*/, jint flags)
return 0;
const QString &text = m_androidInputContext->getSelectedText(flags);
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ GETSEL" << text;
+#endif
return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length()));
}
@@ -142,6 +159,9 @@ static jstring getTextAfterCursor(JNIEnv *env, jobject /*thiz*/, jint length, ji
return 0;
const QString &text = m_androidInputContext->getTextAfterCursor(length, flags);
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ GET" << length << text;
+#endif
return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length()));
}
@@ -151,6 +171,9 @@ static jstring getTextBeforeCursor(JNIEnv *env, jobject /*thiz*/, jint length, j
return 0;
const QString &text = m_androidInputContext->getTextBeforeCursor(length, flags);
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ GET" << length << text;
+#endif
return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length()));
}
@@ -164,14 +187,32 @@ static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, ji
QString str(reinterpret_cast<const QChar *>(jstr), env->GetStringLength(text));
env->ReleaseStringChars(text, jstr);
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ SET" << str;
+#endif
return m_androidInputContext->setComposingText(str, newCursorPosition);
}
+static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint end)
+{
+ if (!m_androidInputContext)
+ return JNI_FALSE;
+
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ SETR" << start << end;
+#endif
+ return m_androidInputContext->setComposingRegion(start, end);
+}
+
+
static jboolean setSelection(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint end)
{
if (!m_androidInputContext)
return JNI_FALSE;
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ SETSEL" << start << end;
+#endif
return m_androidInputContext->setSelection(start, end);
}
@@ -180,6 +221,9 @@ static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/)
if (!m_androidInputContext)
return JNI_FALSE;
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@ SELALL";
+#endif
return m_androidInputContext->selectAll();
}
@@ -188,6 +232,9 @@ static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/)
if (!m_androidInputContext)
return JNI_FALSE;
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@";
+#endif
return m_androidInputContext->cut();
}
@@ -196,6 +243,9 @@ static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/)
if (!m_androidInputContext)
return JNI_FALSE;
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@";
+#endif
return m_androidInputContext->copy();
}
@@ -204,6 +254,9 @@ static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/)
if (!m_androidInputContext)
return JNI_FALSE;
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@";
+#endif
return m_androidInputContext->copyURL();
}
@@ -212,6 +265,9 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/)
if (!m_androidInputContext)
return JNI_FALSE;
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ qDebug() << "@@@";
+#endif
return m_androidInputContext->paste();
}
@@ -226,6 +282,7 @@ static JNINativeMethod methods[] = {
{"getTextAfterCursor", "(II)Ljava/lang/String;", (void *)getTextAfterCursor},
{"getTextBeforeCursor", "(II)Ljava/lang/String;", (void *)getTextBeforeCursor},
{"setComposingText", "(Ljava/lang/String;I)Z", (void *)setComposingText},
+ {"setComposingRegion", "(II)Z", (void *)setComposingRegion},
{"setSelection", "(II)Z", (void *)setSelection},
{"selectAll", "()Z", (void *)selectAll},
{"cut", "()Z", (void *)cut},
@@ -235,7 +292,8 @@ static JNINativeMethod methods[] = {
};
-QAndroidInputContext::QAndroidInputContext():QPlatformInputContext()
+QAndroidInputContext::QAndroidInputContext()
+ : QPlatformInputContext(), m_blockUpdateSelection(false)
{
QtAndroid::AttachedJNIEnv env;
if (!env.jniEnv)
@@ -340,7 +398,7 @@ void QAndroidInputContext::commit()
void QAndroidInputContext::updateCursorPosition()
{
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
- if (!query.isNull()) {
+ if (!query.isNull() && !m_blockUpdateSelection) {
const int cursorPos = query->value(Qt::ImCursorPosition).toInt();
QtAndroidInput::updateSelection(cursorPos, cursorPos, -1, -1); //selection empty and no pre-edit text
}
@@ -557,7 +615,7 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur
sendInputMethodEvent(&event);
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
- if (!query.isNull()) {
+ if (!query.isNull() && !m_blockUpdateSelection) {
int cursorPos = query->value(Qt::ImCursorPosition).toInt();
int preeditLength = text.length();
QtAndroidInput::updateSelection(cursorPos+preeditLength, cursorPos+preeditLength, cursorPos, cursorPos+preeditLength);
@@ -566,6 +624,54 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur
return JNI_TRUE;
}
+// Android docs say:
+// * start may be after end, same meaning as if swapped
+// * this function must not trigger updateSelection
+// * if start == end then we should stop composing
+jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
+{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return JNI_FALSE;
+
+ if (start > end)
+ qSwap(start, end);
+
+ /*
+ start and end are cursor positions, not character positions,
+ i.e. selecting the first character is done by start == 0 and end == 1,
+ and start == end means no character selected
+
+ Therefore, the length of the region is end - start
+ */
+ int length = end - start;
+
+ bool updateSelectionWasBlocked = m_blockUpdateSelection;
+ m_blockUpdateSelection = true;
+
+ QString text = query->value(Qt::ImSurroundingText).toString();
+ m_composingText = text.mid(start, length);
+
+ //in the Qt text controls, cursor pos is the start of the preedit
+ int cursorPos = query->value(Qt::ImCursorPosition).toInt();
+ int relativeStart = start - cursorPos;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+
+ // Show compose text underlined
+ QTextCharFormat underlined;
+ underlined.setFontUnderline(true);
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,0, length,
+ QVariant(underlined)));
+
+ QInputMethodEvent event(m_composingText, attributes);
+ event.setCommitString(QString(), relativeStart, length);
+ sendInputMethodEvent(&event);
+
+ m_blockUpdateSelection = updateSelectionWasBlocked;
+ return JNI_TRUE;
+}
+
jboolean QAndroidInputContext::setSelection(jint start, jint end)
{
QList<QInputMethodEvent::Attribute> attributes;
diff --git a/src/plugins/platforms/android/src/qandroidinputcontext.h b/src/plugins/platforms/android/src/qandroidinputcontext.h
index 482aeffa50..d19dcc384b 100644
--- a/src/plugins/platforms/android/src/qandroidinputcontext.h
+++ b/src/plugins/platforms/android/src/qandroidinputcontext.h
@@ -105,6 +105,7 @@ public:
QString getTextAfterCursor(jint length, jint flags);
QString getTextBeforeCursor(jint length, jint flags);
jboolean setComposingText(const QString &text, jint newCursorPosition);
+ jboolean setComposingRegion(jint start, jint end);
jboolean setSelection(jint start, jint end);
jboolean selectAll();
jboolean cut();
@@ -125,6 +126,7 @@ private:
ExtractedText m_extractedText;
QString m_composingText;
QMetaObject::Connection m_updateCursorPosConnection;
+ bool m_blockUpdateSelection;
};
QT_END_NAMESPACE