diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java index 1fee857a58a..25ac59ec32d 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -138,6 +138,7 @@ class QtActivityDelegate extends QtActivityDelegateBase r.width(), kbHeight); return true; }); + registerGlobalFocusChangeListener(m_layout); m_inputDelegate.setEditPopupMenu(new EditPopupMenu(m_activity, m_layout)); } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java index 5c36c5fd059..8625c1f6016 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java @@ -133,6 +133,26 @@ abstract class QtActivityDelegateBase setUpLayout(); } + protected void registerGlobalFocusChangeListener(final View view) { + view.getViewTreeObserver().addOnGlobalFocusChangeListener(this::onGlobalFocusChanged); + } + + private void onGlobalFocusChanged(View oldFocus, View newFocus) { + if (newFocus instanceof QtEditText) { + final QtWindow newWindow = (QtWindow) newFocus.getParent(); + QtWindow.windowFocusChanged(true, newWindow.getId()); + m_inputDelegate.setFocusedView((QtEditText) newFocus); + } else { + int id = -1; + if (oldFocus instanceof QtEditText) { + final QtWindow oldWindow = (QtWindow) oldFocus.getParent(); + id = oldWindow.getId(); + } + QtWindow.windowFocusChanged(false, id); + m_inputDelegate.setFocusedView(null); + } + } + public void hideSplashScreen() { hideSplashScreen(0); diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java index cab542622bc..66a3f6c9494 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java @@ -135,6 +135,7 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase implements QtNative.AppS void setView(QtView view) { m_view = view; + registerGlobalFocusChangeListener(m_view); } public void setRootWindowRef(long ref) { diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java index d126ba3dc15..2f8f9cfbdcd 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java @@ -24,6 +24,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface { private final QtEditText m_editText; private static native void setSurface(int windowId, Surface surface); + static native void windowFocusChanged(boolean hasFocus, int id); public QtWindow(Context context, QtWindow parentWindow) { @@ -31,6 +32,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface { setId(View.generateViewId()); m_editText = new QtEditText(context); setParent(parentWindow); + setFocusableInTouchMode(true); QtNative.runAction(() -> { m_gestureDetector = diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp index 289884020e8..e4d7b4c7ec8 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp @@ -342,10 +342,28 @@ void QAndroidPlatformWindow::setSurface(JNIEnv *env, jobject object, jint window } } +void QAndroidPlatformWindow::windowFocusChanged(JNIEnv *env, jobject object, + jboolean focus, jint windowId) +{ + Q_UNUSED(env) + Q_UNUSED(object) + QWindow* window = QtAndroid::windowFromId(windowId); + Q_ASSERT_X(window, "QAndroidPlatformWindow", "windowFocusChanged event window should exist"); + if (focus) { + QWindowSystemInterface::handleFocusWindowChanged(window); + } else if (!focus && window == qGuiApp->focusWindow()) { + // Clear focus if current window has lost focus + QWindowSystemInterface::handleFocusWindowChanged(nullptr); + } +} + bool QAndroidPlatformWindow::registerNatives(QJniEnvironment &env) { if (!env.registerNativeMethods(QtJniTypes::Traits::className(), - {Q_JNI_NATIVE_SCOPED_METHOD(setSurface, QAndroidPlatformWindow)})) { + { + Q_JNI_NATIVE_SCOPED_METHOD(setSurface, QAndroidPlatformWindow), + Q_JNI_NATIVE_SCOPED_METHOD(windowFocusChanged, QAndroidPlatformWindow) + })) { qCCritical(lcQpaWindow) << "RegisterNatives failed for" << QtJniTypes::Traits::className(); return false; diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h index 1896316bf6d..3f1e8ac992c 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.h +++ b/src/plugins/platforms/android/qandroidplatformwindow.h @@ -93,6 +93,8 @@ protected: private: static void setSurface(JNIEnv *env, jobject obj, jint windowId, QtJniTypes::Surface surface); Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(setSurface) + static void windowFocusChanged(JNIEnv *env, jobject object, jboolean focus, jint windowId); + Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(windowFocusChanged) }; QT_END_NAMESPACE