From 46a23b1fae7eadca3b8a5c3d459d234df106e94d Mon Sep 17 00:00:00 2001 From: Petri Virkkunen Date: Mon, 11 Mar 2024 14:04:01 +0200 Subject: [PATCH] Android: Implement interface for window-related backend Add QtWindowInterface interface, to access native functionality related to windows. QtActivityBase now follows QtNative.onAppStateDetailsChanged in order to register and unregister functionalities of QtActivityDelegate. Task-number: QTBUG-118874 Change-Id: Ifad33bd7aac7683081f026f0591ef496909be095 Reviewed-by: Assam Boudjelthia --- src/android/jar/CMakeLists.txt | 1 + .../qtproject/qt/android/QtActivityBase.java | 13 +++++++- .../qt/android/QtActivityDelegate.java | 30 ++++++++++++++----- .../qt/android/QtActivityDelegateBase.java | 5 ---- .../qt/android/QtEmbeddedDelegate.java | 10 ++++++- .../qt/android/QtWindowInterface.java | 11 +++++++ .../platforms/android/androidjnimain.cpp | 5 +++- .../android/qandroidplatformscreen.cpp | 20 ++++++++++--- 8 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java diff --git a/src/android/jar/CMakeLists.txt b/src/android/jar/CMakeLists.txt index 9d07e87a93a..707fe4ccfbb 100644 --- a/src/android/jar/CMakeLists.txt +++ b/src/android/jar/CMakeLists.txt @@ -41,6 +41,7 @@ set(java_sources src/org/qtproject/qt/android/QtEmbeddedViewInterface.java src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java src/org/qtproject/qt/android/BackendRegister.java + src/org/qtproject/qt/android/QtWindowInterface.java ) qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java index 3cb6ba220e8..c11130ebd7c 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java @@ -19,7 +19,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.Window; -public class QtActivityBase extends Activity +public class QtActivityBase extends Activity implements QtNative.AppStateDetailsListener { private String m_applicationParams = ""; private boolean m_isCustomThemeSet = false; @@ -96,6 +96,8 @@ public class QtActivityBase extends Activity m_delegate = new QtActivityDelegate(this); + QtNative.registerAppStateListener(this); + handleActivityRestart(); addReferrer(getIntent()); @@ -107,6 +109,14 @@ public class QtActivityBase extends Activity loader.getMainLibraryPath()); } + @Override + public void onAppStateDetailsChanged(QtNative.ApplicationStateDetails details) { + if (details.isStarted) + m_delegate.registerBackends(); + else + m_delegate.unregisterBackends(); + } + @Override protected void onStart() { @@ -153,6 +163,7 @@ public class QtActivityBase extends Activity { super.onDestroy(); if (!m_retainNonConfigurationInstance) { + QtNative.unregisterAppStateListener(this); QtNative.terminateQt(); QtNative.setActivity(null); QtNative.getQtThread().exit(); 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 1e1a36be3cc..169140afbde 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -26,20 +26,19 @@ import android.view.Menu; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowInsetsController; import android.widget.ImageView; import android.widget.PopupMenu; import java.util.HashMap; -class QtActivityDelegate extends QtActivityDelegateBase +class QtActivityDelegate extends QtActivityDelegateBase implements QtWindowInterface { private static final String QtTAG = "QtActivityDelegate"; private QtRootLayout m_layout = null; private ImageView m_splashScreen = null; private boolean m_splashScreenSticky = false; + private boolean m_backendsRegistered = false; private View m_dummyView = null; private HashMap m_nativeViews = new HashMap(); @@ -53,6 +52,22 @@ class QtActivityDelegate extends QtActivityDelegateBase setActivityBackgroundDrawable(); } + void registerBackends() + { + if (!m_backendsRegistered) { + m_backendsRegistered = true; + BackendRegister.registerBackend(QtWindowInterface.class, + (QtWindowInterface)QtActivityDelegate.this); + } + } + + void unregisterBackends() + { + if (m_backendsRegistered) { + m_backendsRegistered = false; + BackendRegister.unregisterBackend(QtWindowInterface.class); + } + } @UsedFromNativeCode @Override @@ -61,9 +76,8 @@ class QtActivityDelegate extends QtActivityDelegateBase return m_layout; } - @UsedFromNativeCode @Override - void setSystemUiVisibility(int systemUiVisibility) + public void setSystemUiVisibility(int systemUiVisibility) { QtNative.runAction(() -> { m_displayManager.setSystemUiVisibility(systemUiVisibility); @@ -310,7 +324,7 @@ class QtActivityDelegate extends QtActivityDelegateBase @UsedFromNativeCode @Override - void removeTopLevelWindow(final int id) + public void removeTopLevelWindow(final int id) { QtNative.runAction(()-> { if (m_topLevelWindows.containsKey(id)) { @@ -328,7 +342,7 @@ class QtActivityDelegate extends QtActivityDelegateBase @UsedFromNativeCode @Override - void bringChildToFront(final int id) + public void bringChildToFront(final int id) { QtNative.runAction(() -> { QtWindow window = m_topLevelWindows.get(id); @@ -339,7 +353,7 @@ class QtActivityDelegate extends QtActivityDelegateBase @UsedFromNativeCode @Override - void bringChildToBack(int id) + public void bringChildToBack(int id) { QtNative.runAction(() -> { QtWindow window = m_topLevelWindows.get(id); 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 6fd539d8dd5..9f8738b042d 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java @@ -55,11 +55,6 @@ abstract class QtActivityDelegateBase void hideSplashScreen(final int duration) {} void openContextMenu(final int x, final int y, final int w, final int h) {} void setActionBarVisibility(boolean visible) {} - void addTopLevelWindow(final QtWindow window) {} - void removeTopLevelWindow(final int id) {} - void bringChildToFront(final int id) {} - void bringChildToBack(int id) {} - void setSystemUiVisibility(int systemUiVisibility) {} QtActivityDelegateBase(Activity activity) { 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 ff694777d57..78e1b5e2654 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java @@ -22,12 +22,13 @@ import java.util.ArrayList; import java.util.HashMap; class QtEmbeddedDelegate extends QtActivityDelegateBase - implements QtNative.AppStateDetailsListener, QtEmbeddedViewInterface + implements QtNative.AppStateDetailsListener, QtEmbeddedViewInterface, QtWindowInterface { // TODO simplistic implementation with one QtView, expand to support multiple views QTBUG-117649 private QtView m_view; private QtNative.ApplicationStateDetails m_stateDetails; private boolean m_windowLoaded = false; + private boolean m_backendsRegistered = false; public QtEmbeddedDelegate(Activity context) { super(context); @@ -89,6 +90,13 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase public void onAppStateDetailsChanged(QtNative.ApplicationStateDetails details) { synchronized (this) { m_stateDetails = details; + if (details.isStarted && !m_backendsRegistered) { + m_backendsRegistered = true; + BackendRegister.registerBackend(QtWindowInterface.class, (QtWindowInterface)this); + } else if (!details.isStarted && m_backendsRegistered) { + m_backendsRegistered = false; + BackendRegister.unregisterBackend(QtWindowInterface.class); + } } } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java new file mode 100644 index 00000000000..1fb312786ff --- /dev/null +++ b/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java @@ -0,0 +1,11 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +package org.qtproject.qt.android; +@UsedFromNativeCode +interface QtWindowInterface { + default void addTopLevelWindow(final QtWindow window) { } + default void removeTopLevelWindow(final int id) { } + default void bringChildToFront(final int id) { } + default void bringChildToBack(int id) { } + default void setSystemUiVisibility(int systemUiVisibility) { } +} diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index b02b2a7d7c4..08a56039e43 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -94,6 +94,7 @@ static const char m_methodErrorMsg[] = "Can't find method \"%s%s\""; Q_CONSTINIT static QBasicAtomicInt startQtAndroidPluginCalled = Q_BASIC_ATOMIC_INITIALIZER(0); Q_DECLARE_JNI_CLASS(QtEmbeddedDelegateFactory, "org/qtproject/qt/android/QtEmbeddedDelegateFactory") +Q_DECLARE_JNI_CLASS(QtWindowInterface, "org/qtproject/qt/android/QtWindowInterface") namespace QtAndroid { @@ -184,7 +185,9 @@ namespace QtAndroid // TODO move calls from here to where they logically belong void setSystemUiVisibility(SystemUiVisibility uiVisibility) { - qtActivityDelegate().callMethod("setSystemUiVisibility", jint(uiVisibility)); + AndroidBackendRegister *reg = QtAndroid::backendRegister(); + reg->callInterface("setSystemUiVisibility", + jint(uiVisibility)); } // FIXME: avoid direct access to QtActivityDelegate diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 9e20b7ac4bd..4d752a3cc32 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -57,6 +57,7 @@ Q_DECLARE_JNI_CLASS(Resources, "android/content/res/Resources") Q_DECLARE_JNI_CLASS(Size, "android/util/Size") Q_DECLARE_JNI_CLASS(QtNative, "org/qtproject/qt/android/QtNative") Q_DECLARE_JNI_CLASS(QtDisplayManager, "org/qtproject/qt/android/QtDisplayManager") +Q_DECLARE_JNI_CLASS(QtWindowInterface, "org/qtproject/qt/android/QtWindowInterface") Q_DECLARE_JNI_CLASS(DisplayMode, "android/view/Display$Mode") @@ -162,7 +163,10 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window) return; m_windowStack.prepend(window); - QtAndroid::qtActivityDelegate().callMethod("addTopLevelWindow", window->nativeWindow()); + + AndroidBackendRegister *reg = QtAndroid::backendRegister(); + reg->callInterface("addTopLevelWindow", + window->nativeWindow()); if (window->window()->isVisible()) topVisibleWindowChanged(); @@ -175,7 +179,9 @@ void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window) if (m_windowStack.contains(window)) qWarning() << "Failed to remove window"; - QtAndroid::qtActivityDelegate().callMethod("removeTopLevelWindow", window->nativeViewId()); + AndroidBackendRegister *reg = QtAndroid::backendRegister(); + reg->callInterface("removeTopLevelWindow", + window->nativeViewId()); topVisibleWindowChanged(); } @@ -187,7 +193,10 @@ void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window) return; if (index > 0) { m_windowStack.move(index, 0); - QtAndroid::qtActivityDelegate().callMethod("bringChildToFront", window->nativeViewId()); + + AndroidBackendRegister *reg = QtAndroid::backendRegister(); + reg->callInterface("bringChildToFront", + window->nativeViewId()); } topVisibleWindowChanged(); } @@ -198,7 +207,10 @@ void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window) if (index == -1 || index == (m_windowStack.size() - 1)) return; m_windowStack.move(index, m_windowStack.size() - 1); - QtAndroid::qtActivityDelegate().callMethod("bringChildToBack", window->nativeViewId()); + + AndroidBackendRegister *reg = QtAndroid::backendRegister(); + reg->callInterface("bringChildToBack", + window->nativeViewId()); topVisibleWindowChanged(); }