From c6af7cf666d43c68c90ad829c3a55d84ee8e4a3e Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 16 Jan 2018 13:48:48 +0200 Subject: Android: Cleanup the threading handling Make sure all the call that are coming from Android UI thread are delegate to Qt thread. Change-Id: Ice1a25d01d107d7221b88c65b96dc1459c7f77f0 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../platforms/android/qandroidinputcontext.cpp | 221 ++++++++++----------- .../platforms/android/qandroidinputcontext.h | 12 +- 2 files changed, 108 insertions(+), 125 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 0fa0af8912..ea3e9c1441 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -98,6 +98,11 @@ static jfieldID m_selectionStartFieldID = 0; static jfieldID m_startOffsetFieldID = 0; static jfieldID m_textFieldID = 0; +static void runOnQtThread(const std::function &func) +{ + QMetaObject::invokeMethod(m_androidInputContext, "safeCall", Qt::BlockingQueuedConnection, Q_ARG(std::function, func)); +} + static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) { if (!m_androidInputContext) @@ -106,10 +111,9 @@ static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@ BEGINBATCH"); #endif - - return m_androidInputContext->beginBatchEdit(); - - return JNI_TRUE; + jboolean res; + runOnQtThread([&res]{res = m_androidInputContext->beginBatchEdit();}); + return res; } static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) @@ -121,9 +125,9 @@ static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) qDebug("@@@ ENDBATCH"); #endif - return m_androidInputContext->endBatchEdit(); - - return JNI_TRUE; + jboolean res; + runOnQtThread([&res]{res = m_androidInputContext->endBatchEdit();}); + return res; } @@ -140,7 +144,9 @@ static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint new #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ COMMIT" << str << newCursorPosition; #endif - return m_androidInputContext->commitText(str, newCursorPosition); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->commitText(str, newCursorPosition);}); + return res; } static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint leftLength, jint rightLength) @@ -151,7 +157,9 @@ static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint le #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ DELETE" << leftLength << rightLength; #endif - return m_androidInputContext->deleteSurroundingText(leftLength, rightLength); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->deleteSurroundingText(leftLength, rightLength);}); + return res; } static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/) @@ -162,7 +170,9 @@ static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@ FINISH"); #endif - return m_androidInputContext->finishComposingText(); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->finishComposingText();}); + return res; } static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes) @@ -170,7 +180,9 @@ static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes) if (!m_androidInputContext) return 0; - return m_androidInputContext->getCursorCapsMode(reqModes); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->getCursorCapsMode(reqModes);}); + return res; } static jobject getExtractedText(JNIEnv *env, jobject /*thiz*/, int hintMaxChars, int hintMaxLines, jint flags) @@ -178,8 +190,8 @@ static jobject getExtractedText(JNIEnv *env, jobject /*thiz*/, int hintMaxChars, if (!m_androidInputContext) return 0; - const QAndroidInputContext::ExtractedText &extractedText = - m_androidInputContext->getExtractedText(hintMaxChars, hintMaxLines, flags); + 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; @@ -204,7 +216,8 @@ static jstring getSelectedText(JNIEnv *env, jobject /*thiz*/, jint flags) if (!m_androidInputContext) return 0; - const QString &text = m_androidInputContext->getSelectedText(flags); + QString text; + runOnQtThread([&]{text = m_androidInputContext->getSelectedText(flags);}); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ GETSEL" << text; #endif @@ -218,7 +231,8 @@ static jstring getTextAfterCursor(JNIEnv *env, jobject /*thiz*/, jint length, ji if (!m_androidInputContext) return 0; - const QString &text = m_androidInputContext->getTextAfterCursor(length, flags); + QString text; + runOnQtThread([&]{text = m_androidInputContext->getTextAfterCursor(length, flags);}); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ GETA" << length << text; #endif @@ -230,7 +244,8 @@ static jstring getTextBeforeCursor(JNIEnv *env, jobject /*thiz*/, jint length, j if (!m_androidInputContext) return 0; - const QString &text = m_androidInputContext->getTextBeforeCursor(length, flags); + QString text; + runOnQtThread([&]{text = m_androidInputContext->getTextBeforeCursor(length, flags);}); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ GETB" << length << text; #endif @@ -250,7 +265,9 @@ static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, ji #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ SET" << str << newCursorPosition; #endif - return m_androidInputContext->setComposingText(str, newCursorPosition); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->setComposingText(str, newCursorPosition);}); + return res; } static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint end) @@ -261,7 +278,9 @@ static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ SETR" << start << end; #endif - return m_androidInputContext->setComposingRegion(start, end); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->setComposingRegion(start, end);}); + return res; } @@ -273,7 +292,10 @@ static jboolean setSelection(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ SETSEL" << start << end; #endif - return m_androidInputContext->setSelection(start, end); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->setSelection(start, end);}); + return res; + } static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/) @@ -284,7 +306,9 @@ static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@ SELALL"); #endif - return m_androidInputContext->selectAll(); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->selectAll();}); + return res; } static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/) @@ -295,7 +319,9 @@ static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@"); #endif - return m_androidInputContext->cut(); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->cut();}); + return res; } static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/) @@ -306,7 +332,9 @@ static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@"); #endif - return m_androidInputContext->copy(); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->copy();}); + return res; } static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/) @@ -317,7 +345,9 @@ static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@"); #endif - return m_androidInputContext->copyURL(); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->copyURL();}); + return res; } static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/) @@ -328,7 +358,9 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@ PASTE"); #endif - return m_androidInputContext->paste(); + jboolean res; + runOnQtThread([&]{res = m_androidInputContext->paste();}); + return res; } static jboolean updateCursorPosition(JNIEnv */*env*/, jobject /*thiz*/) @@ -339,7 +371,8 @@ static jboolean updateCursorPosition(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@ UPDATECURSORPOS"); #endif - m_androidInputContext->updateCursorPosition(); + + runOnQtThread([&]{m_androidInputContext->updateCursorPosition();}); return true; } @@ -517,7 +550,7 @@ void QAndroidInputContext::reset() m_batchEditNestingLevel = 0; m_handleMode = Hidden; if (qGuiApp->focusObject()) { - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(Qt::ImEnabled); + QSharedPointer query = focusObjectInputMethodQuery(Qt::ImEnabled); if (!query.isNull() && query->value(Qt::ImEnabled).toBool()) { QtAndroidInput::resetSoftwareKeyboard(); return; @@ -533,7 +566,7 @@ void QAndroidInputContext::commit() void QAndroidInputContext::updateCursorPosition() { - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (!query.isNull() && !m_blockUpdateSelection && !m_batchEditNestingLevel) { const int cursorPos = getAbsoluteCursorPosition(query); const int composeLength = m_composingText.length(); @@ -629,8 +662,10 @@ void QAndroidInputContext::updateSelectionHandles() */ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y) { - if (m_batchEditNestingLevel.load() || m_blockUpdateSelection) + if (m_batchEditNestingLevel.load() || m_blockUpdateSelection) { + qWarning() << "QAndroidInputContext::handleLocationChanged returned"; return; + } finishComposingText(); @@ -710,7 +745,7 @@ void QAndroidInputContext::touchDown(int x, int y) // The VK will appear in a moment, stop the timer m_hideCursorHandleTimer.stop(); finishComposingText(); - QMetaObject::invokeMethod(this, "updateSelectionHandles", Qt::QueuedConnection); + updateSelectionHandles(); } } @@ -748,7 +783,7 @@ void QAndroidInputContext::longPress(int x, int y) } if (cursor == anchor || cursor < 0 || cursor - anchor > 500) { m_handleMode = ShowCursor | ShowEditPopup; - QMetaObject::invokeMethod(this, "updateSelectionHandles", Qt::QueuedConnection); + updateSelectionHandles(); return; } QList imAttributes; @@ -758,7 +793,7 @@ void QAndroidInputContext::longPress(int x, int y) QGuiApplication::sendEvent(m_focusObject, &event); m_handleMode = ShowSelection | ShowEditPopup; - QMetaObject::invokeMethod(this, "updateSelectionHandles", Qt::QueuedConnection); + updateSelectionHandles(); } } @@ -783,7 +818,7 @@ void QAndroidInputContext::hideSelectionHandles() void QAndroidInputContext::update(Qt::InputMethodQueries queries) { - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(queries); + QSharedPointer query = focusObjectInputMethodQuery(queries); if (query.isNull()) return; #warning TODO extract the needed data from query @@ -815,7 +850,7 @@ void QAndroidInputContext::showInputPanel() connect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(showInputPanelLater(Qt::ApplicationState))); return; } - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return; @@ -839,6 +874,14 @@ void QAndroidInputContext::showInputPanelLater(Qt::ApplicationState state) showInputPanel(); } +void QAndroidInputContext::safeCall(const std::function &func, Qt::ConnectionType conType) +{ + if (qGuiApp->thread() == QThread::currentThread()) + func(); + else + QMetaObject::invokeMethod(this, "safeCall", conType, Q_ARG(std::function, func)); +} + void QAndroidInputContext::hideInputPanel() { QtAndroidInput::hideSoftwareKeyboard(); @@ -900,12 +943,12 @@ jboolean QAndroidInputContext::commitText(const QString &text, jint newCursorPos ScopedValueChangeBack svcb(m_blockUpdateSelection, true); QInputMethodEvent event; event.setCommitString(text); - sendInputMethodEventThreadSafe(&event); + sendInputMethodEvent(&event); clear(); // Qt has now put the cursor at the end of the text, corresponding to newCursorPosition == 1 if (newCursorPosition != 1) { - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (!query.isNull()) { QList attributes; const int localPos = query->value(Qt::ImCursorPosition).toInt(); @@ -924,7 +967,7 @@ jboolean QAndroidInputContext::commitText(const QString &text, jint newCursorPos jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint rightLength) { - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return JNI_TRUE; @@ -938,7 +981,7 @@ jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint right QInputMethodEvent event; event.setCommitString(QString(), -leftLength, leftLength+rightLength); - sendInputMethodEventThreadSafe(&event); + sendInputMethodEvent(&event); clear(); return JNI_TRUE; @@ -950,7 +993,7 @@ jboolean QAndroidInputContext::finishComposingText() if (m_composingText.isEmpty()) return JNI_TRUE; // not composing - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return JNI_FALSE; @@ -963,7 +1006,7 @@ jboolean QAndroidInputContext::finishComposingText() QInputMethodEvent event(QString(), attributes); event.setCommitString(m_composingText); - sendInputMethodEventThreadSafe(&event); + sendInputMethodEvent(&event); clear(); return JNI_TRUE; @@ -972,7 +1015,7 @@ jboolean QAndroidInputContext::finishComposingText() jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/) { jint res = 0; - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return res; @@ -995,7 +1038,7 @@ const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedTex // updateExtractedText(View, int, ExtractedText) whenever you call // updateSelection(View, int, int, int, int)." QTBUG-37980 - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return m_extractedText; @@ -1040,7 +1083,7 @@ const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedTex QString QAndroidInputContext::getSelectedText(jint /*flags*/) { - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return QString(); @@ -1050,13 +1093,13 @@ QString QAndroidInputContext::getSelectedText(jint /*flags*/) QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/) { //### the preedit text could theoretically be after the cursor - QVariant textAfter = queryFocusObjectThreadSafe(Qt::ImTextAfterCursor, QVariant(length)); + QVariant textAfter = QInputMethod::queryFocusObject(Qt::ImTextAfterCursor, QVariant(length)); if (textAfter.isValid()) { return textAfter.toString().left(length); } //compatibility code for old controls that do not implement the new API - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return QString(); @@ -1070,12 +1113,12 @@ QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/) QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/) { - QVariant textBefore = queryFocusObjectThreadSafe(Qt::ImTextBeforeCursor, QVariant(length)); + QVariant textBefore = QInputMethod::queryFocusObject(Qt::ImTextBeforeCursor, QVariant(length)); if (textBefore.isValid()) return textBefore.toString().rightRef(length) + m_composingText; //compatibility code for old controls that do not implement the new API - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return QString(); @@ -1101,7 +1144,7 @@ QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/) jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCursorPosition) { - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return JNI_FALSE; @@ -1123,7 +1166,7 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur QVariant(underlined))); QInputMethodEvent event(m_composingText, attributes); - sendInputMethodEventThreadSafe(&event); + sendInputMethodEvent(&event); QMetaObject::invokeMethod(this, "keyDown"); @@ -1147,7 +1190,7 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end) if (wasComposing) finishComposingText(); - QSharedPointer query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return JNI_FALSE; @@ -1192,10 +1235,10 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end) QInputMethodEvent event(m_composingText, attributes); event.setCommitString(QString(), relativeStart, length); - sendInputMethodEventThreadSafe(&event); + sendInputMethodEvent(&event); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL - QSharedPointer query2 = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query2 = focusObjectInputMethodQuery(); if (!query2.isNull()) { qDebug() << "Setting. Prev local cpos:" << localPos << "block pos:" < query = focusObjectInputMethodQueryThreadSafe(); + QSharedPointer query = focusObjectInputMethodQuery(); if (query.isNull()) return JNI_FALSE; @@ -1238,7 +1281,7 @@ jboolean QAndroidInputContext::setSelection(jint start, jint end) end - start)); } QInputMethodEvent event(m_composingText, attributes); - sendInputMethodEventThreadSafe(&event); + sendInputMethodEvent(&event); updateCursorPosition(); return JNI_TRUE; } @@ -1292,65 +1335,24 @@ void QAndroidInputContext::sendShortcut(const QKeySequence &sequence) } } -Q_INVOKABLE QVariant QAndroidInputContext::queryFocusObjectUnsafe(Qt::InputMethodQuery query, QVariant argument) -{ - return QInputMethod::queryFocusObject(query, argument); -} - -QVariant QAndroidInputContext::queryFocusObjectThreadSafe(Qt::InputMethodQuery query, QVariant argument) -{ - QVariant retval; +QSharedPointer QAndroidInputContext::focusObjectInputMethodQuery(Qt::InputMethodQueries queries) { if (!qGuiApp) - return retval; - const bool inMainThread = qGuiApp->thread() == QThread::currentThread(); - if (QAndroidEventDispatcherStopper::stopped() && !inMainThread) - return retval; - AndroidDeadlockProtector protector; - if (!inMainThread && !protector.acquire()) - return retval; - - QMetaObject::invokeMethod(this, "queryFocusObjectUnsafe", - inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection, - Q_RETURN_ARG(QVariant, retval), - Q_ARG(Qt::InputMethodQuery, query), - Q_ARG(QVariant, argument)); - - return retval; -} - -QSharedPointer QAndroidInputContext::focusObjectInputMethodQueryThreadSafe(Qt::InputMethodQueries queries) { - QSharedPointer retval; - if (!qGuiApp) - return QSharedPointer(); - const bool inMainThread = qGuiApp->thread() == QThread::currentThread(); - if (QAndroidEventDispatcherStopper::stopped() && !inMainThread) - return QSharedPointer(); - AndroidDeadlockProtector protector; - if (!inMainThread && !protector.acquire()) - return QSharedPointer(); - - QInputMethodQueryEvent *queryEvent = 0; - QMetaObject::invokeMethod(this, "focusObjectInputMethodQueryUnsafe", - inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection, - Q_RETURN_ARG(QInputMethodQueryEvent*, queryEvent), - Q_ARG(Qt::InputMethodQueries, queries)); + return {}; - return QSharedPointer(queryEvent); -} - -QInputMethodQueryEvent *QAndroidInputContext::focusObjectInputMethodQueryUnsafe(Qt::InputMethodQueries queries) -{ QObject *focusObject = qGuiApp->focusObject(); if (!focusObject) - return 0; + return {}; QInputMethodQueryEvent *ret = new QInputMethodQueryEvent(queries); QCoreApplication::sendEvent(focusObject, ret); - return ret; + return QSharedPointer(ret); } -void QAndroidInputContext::sendInputMethodEventUnsafe(QInputMethodEvent *event) +void QAndroidInputContext::sendInputMethodEvent(QInputMethodEvent *event) { + if (!qGuiApp) + return; + QObject *focusObject = qGuiApp->focusObject(); if (!focusObject) return; @@ -1358,19 +1360,4 @@ void QAndroidInputContext::sendInputMethodEventUnsafe(QInputMethodEvent *event) QCoreApplication::sendEvent(focusObject, event); } -void QAndroidInputContext::sendInputMethodEventThreadSafe(QInputMethodEvent *event) -{ - if (!qGuiApp) - return; - const bool inMainThread = qGuiApp->thread() == QThread::currentThread(); - if (QAndroidEventDispatcherStopper::stopped() && !inMainThread) - return; - AndroidDeadlockProtector protector; - if (!inMainThread && !protector.acquire()) - return; - QMetaObject::invokeMethod(this, "sendInputMethodEventUnsafe", - inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection, - Q_ARG(QInputMethodEvent*, event)); -} - QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h index 71c6a2b1e9..bd3edb30f0 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.h +++ b/src/plugins/platforms/android/qandroidinputcontext.h @@ -42,6 +42,7 @@ #define ANDROIDINPUTCONTEXT_H #include +#include #include #include #include @@ -135,6 +136,7 @@ public: jboolean paste(); public slots: + void safeCall(const std::function &func, Qt::ConnectionType conType = Qt::BlockingQueuedConnection); void updateCursorPosition(); void updateSelectionHandles(); void handleLocationChanged(int handleId, int x, int y); @@ -147,14 +149,8 @@ private slots: void showInputPanelLater(Qt::ApplicationState); private: - void sendInputMethodEventThreadSafe(QInputMethodEvent *event); - Q_INVOKABLE void sendInputMethodEventUnsafe(QInputMethodEvent *event); - - QSharedPointer focusObjectInputMethodQueryThreadSafe(Qt::InputMethodQueries queries = Qt::ImQueryAll); - Q_INVOKABLE QInputMethodQueryEvent *focusObjectInputMethodQueryUnsafe(Qt::InputMethodQueries queries); - - Q_INVOKABLE QVariant queryFocusObjectUnsafe(Qt::InputMethodQuery query, QVariant argument); - QVariant queryFocusObjectThreadSafe(Qt::InputMethodQuery query, QVariant argument); + void sendInputMethodEvent(QInputMethodEvent *event); + QSharedPointer focusObjectInputMethodQuery(Qt::InputMethodQueries queries = Qt::ImQueryAll); private: ExtractedText m_extractedText; -- cgit v1.2.3