diff options
Diffstat (limited to 'src/plugins/platforms/android/qandroidinputcontext.cpp')
-rw-r--r-- | src/plugins/platforms/android/qandroidinputcontext.cpp | 152 |
1 files changed, 90 insertions, 62 deletions
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 4c111be829..62212ff63d 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -80,9 +80,7 @@ static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug("@@@ BEGINBATCH"); -#endif + qCDebug(lcQpaInputMethods) << "@@@ BEGINBATCH"; jboolean res = JNI_FALSE; runOnQtThread([&res]{res = m_androidInputContext->beginBatchEdit();}); return res; @@ -93,9 +91,7 @@ static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug("@@@ ENDBATCH"); -#endif + qCDebug(lcQpaInputMethods) << "@@@ ENDBATCH"; jboolean res = JNI_FALSE; runOnQtThread([&res]{res = m_androidInputContext->endBatchEdit();}); @@ -113,9 +109,7 @@ 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 << newCursorPosition; -#endif + qCDebug(lcQpaInputMethods) << "@@@ COMMIT" << str << newCursorPosition; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->commitText(str, newCursorPosition);}); return res; @@ -126,9 +120,7 @@ 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 + qCDebug(lcQpaInputMethods) << "@@@ DELETE" << leftLength << rightLength; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->deleteSurroundingText(leftLength, rightLength);}); return res; @@ -139,9 +131,7 @@ static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug("@@@ FINISH"); -#endif + qCDebug(lcQpaInputMethods) << "@@@ FINISH"; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->finishComposingText();}); return res; @@ -165,9 +155,7 @@ static jobject getExtractedText(JNIEnv *env, jobject /*thiz*/, int hintMaxChars, QAndroidInputContext::ExtractedText extractedText; runOnQtThread([&]{extractedText = 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 + qCDebug(lcQpaInputMethods) << "@@@ 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; jobject object = env->NewObject(m_extractedTextClass, m_classConstructorMethodID); env->SetIntField(object, m_partialStartOffsetFieldID, extractedText.partialStartOffset); @@ -190,9 +178,7 @@ static jstring getSelectedText(JNIEnv *env, jobject /*thiz*/, jint flags) QString text; runOnQtThread([&]{text = m_androidInputContext->getSelectedText(flags);}); -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << "@@@ GETSEL" << text; -#endif + qCDebug(lcQpaInputMethods) << "@@@ GETSEL" << text; if (text.isEmpty()) return 0; return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length())); @@ -205,9 +191,7 @@ static jstring getTextAfterCursor(JNIEnv *env, jobject /*thiz*/, jint length, ji QString text; runOnQtThread([&]{text = m_androidInputContext->getTextAfterCursor(length, flags);}); -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << "@@@ GETA" << length << text; -#endif + qCDebug(lcQpaInputMethods) << "@@@ GETA" << length << text; return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length())); } @@ -218,9 +202,7 @@ static jstring getTextBeforeCursor(JNIEnv *env, jobject /*thiz*/, jint length, j QString text; runOnQtThread([&]{text = m_androidInputContext->getTextBeforeCursor(length, flags);}); -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << "@@@ GETB" << length << text; -#endif + qCDebug(lcQpaInputMethods) << "@@@ GETB" << length << text; return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length())); } @@ -234,9 +216,7 @@ 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 << newCursorPosition; -#endif + qCDebug(lcQpaInputMethods) << "@@@ SET" << str << newCursorPosition; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->setComposingText(str, newCursorPosition);}); return res; @@ -247,9 +227,7 @@ static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << "@@@ SETR" << start << end; -#endif + qCDebug(lcQpaInputMethods) << "@@@ SETR" << start << end; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->setComposingRegion(start, end);}); return res; @@ -261,9 +239,7 @@ static jboolean setSelection(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug() << "@@@ SETSEL" << start << end; -#endif + qCDebug(lcQpaInputMethods) << "@@@ SETSEL" << start << end; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->setSelection(start, end);}); return res; @@ -275,9 +251,7 @@ static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug("@@@ SELALL"); -#endif + qCDebug(lcQpaInputMethods) << "@@@ SELALL"; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->selectAll();}); return res; @@ -288,9 +262,7 @@ static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug("@@@"); -#endif + qCDebug(lcQpaInputMethods) << "@@@"; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->cut();}); return res; @@ -301,9 +273,7 @@ static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug("@@@"); -#endif + qCDebug(lcQpaInputMethods) << "@@@"; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->copy();}); return res; @@ -314,9 +284,7 @@ static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug("@@@"); -#endif + qCDebug(lcQpaInputMethods) << "@@@"; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->copyURL();}); return res; @@ -327,9 +295,7 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug("@@@ PASTE"); -#endif + qCDebug(lcQpaInputMethods) << "@@@ PASTE"; jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->paste();}); return res; @@ -340,14 +306,24 @@ static jboolean updateCursorPosition(JNIEnv */*env*/, jobject /*thiz*/) if (!m_androidInputContext) return JNI_FALSE; -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qDebug("@@@ UPDATECURSORPOS"); -#endif + qCDebug(lcQpaInputMethods) << "@@@ UPDATECURSORPOS"; runOnQtThread([&]{m_androidInputContext->updateCursorPosition();}); return true; } +static void reportFullscreenMode(JNIEnv */*env*/, jobject /*thiz*/, jboolean enabled) +{ + if (!m_androidInputContext) + return; + + runOnQtThread([&]{m_androidInputContext->reportFullscreenMode(enabled);}); +} + +static jboolean fullscreenMode(JNIEnv */*env*/, jobject /*thiz*/) +{ + return m_androidInputContext ? m_androidInputContext->fullscreenMode() : false; +} static JNINativeMethod methods[] = { {"beginBatchEdit", "()Z", (void *)beginBatchEdit}, @@ -368,7 +344,9 @@ static JNINativeMethod methods[] = { {"copy", "()Z", (void *)copy}, {"copyURL", "()Z", (void *)copyURL}, {"paste", "()Z", (void *)paste}, - {"updateCursorPosition", "()Z", (void *)updateCursorPosition} + {"updateCursorPosition", "()Z", (void *)updateCursorPosition}, + {"reportFullscreenMode", "(Z)V", (void *)reportFullscreenMode}, + {"fullscreenMode", "()Z", (void *)fullscreenMode} }; static QRect screenInputItemRectangle() @@ -385,6 +363,7 @@ QAndroidInputContext::QAndroidInputContext() , m_handleMode(Hidden) , m_batchEditNestingLevel(0) , m_focusObject(0) + , m_fullScreenMode(false) { QJniEnvironment env; jclass clazz = env.findClass(QtNativeInputConnectionClassName); @@ -567,12 +546,29 @@ void QAndroidInputContext::updateCursorPosition() } } +bool QAndroidInputContext::isImhNoTextHandlesSet() +{ + QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery(); + if (query.isNull()) + return false; + return query->value(Qt::ImHints).toUInt() & Qt::ImhNoTextHandles; +} + void QAndroidInputContext::updateSelectionHandles() { + if (m_fullScreenMode) { + QtAndroidInput::updateHandles(Hidden); + return; + } static bool noHandles = qEnvironmentVariableIntValue("QT_QPA_NO_TEXT_HANDLES"); if (noHandles || !m_focusObject) return; + if (isImhNoTextHandlesSet()) { + QtAndroidInput::updateHandles(Hidden); + return; + } + auto im = qGuiApp->inputMethod(); QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition | Qt::ImEnabled @@ -586,6 +582,11 @@ void QAndroidInputContext::updateSelectionHandles() bool readOnly = readOnlyVariant.toBool(); QPlatformWindow *qPlatformWindow = qGuiApp->focusWindow()->handle(); + if (!readOnly && ((m_handleMode & 0xff) == Hidden)) { + QtAndroidInput::updateHandles(Hidden); + return; + } + if ( cpos == anchor && (!readOnlyVariant.isValid() || readOnly)) { QtAndroidInput::updateHandles(Hidden); return; @@ -612,9 +613,8 @@ void QAndroidInputContext::updateSelectionHandles() if (!query.value(Qt::ImSurroundingText).toString().isEmpty()) buttons |= EditContext::SelectAllButton; QtAndroidInput::updateHandles(m_handleMode, editMenuPoint, buttons, cursorPointGlobal); - // The VK is hidden, reset the timer - if (m_hideCursorHandleTimer.isActive()) - m_hideCursorHandleTimer.start(); + m_hideCursorHandleTimer.start(); + return; } @@ -788,7 +788,15 @@ void QAndroidInputContext::touchDown(int x, int y) focusObjectStopComposing(); } - updateSelectionHandles(); + // Check if cursor is visible in focused window before updating handles + QPlatformWindow *window = qGuiApp->focusWindow()->handle(); + const QRectF curRect = cursorRectangle(); + const QPoint cursorGlobalPoint = window->mapToGlobal(QPoint(curRect.x(), curRect.y())); + const QRect windowRect = QPlatformInputContext::inputItemClipRectangle().toRect(); + const QRect windowGlobalRect = QRect(window->mapToGlobal(windowRect.topLeft()), windowRect.size()); + + if (windowGlobalRect.contains(cursorGlobalPoint.x(), cursorGlobalPoint.y())) + updateSelectionHandles(); } } @@ -895,6 +903,9 @@ void QAndroidInputContext::showInputPanel() if (query.isNull()) return; + if (!qGuiApp->focusWindow()->handle()) + return; // not a real window, probably VR/XR + disconnect(m_updateCursorPosConnection); m_updateCursorPosConnection = {}; @@ -1112,6 +1123,25 @@ jboolean QAndroidInputContext::finishComposingText() return JNI_TRUE; } +void QAndroidInputContext::reportFullscreenMode(jboolean enabled) +{ + m_fullScreenMode = enabled; + BatchEditLock batchEditLock(this); + if (!focusObjectStopComposing()) + return; + + if (enabled) + m_handleMode = Hidden; + + updateSelectionHandles(); +} + +// Called in calling thread's context +jboolean QAndroidInputContext::fullscreenMode() +{ + return m_fullScreenMode; +} + bool QAndroidInputContext::focusObjectIsComposing() const { return m_composingCursor != -1; @@ -1534,9 +1564,7 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end) } if (start < textOffset || end - textOffset > text.length()) { -#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - qWarning("setComposingRegion: failed to retrieve text from composing region"); -#endif + qCDebug(lcQpaInputMethods) << "Warning: setComposingRegion: failed to retrieve text from composing region"; return JNI_TRUE; } |