summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android
diff options
context:
space:
mode:
authorPiotr Mikolajczyk <piotr.mikolajczyk@qt.io>2022-11-25 12:43:26 +0100
committerPiotr Mikolajczyk <piotr.mikolajczyk@qt.io>2022-12-13 07:49:22 +0000
commit9ce8d4890fdeaa02cc8a7687158d7453bbc7fd49 (patch)
tree4096527766073d58f12ef4d1d2b8646e42a4dd30 /src/plugins/platforms/android
parent70b3df00f946f1ad278aa6c51eaba170eb9fd271 (diff)
Add handling of screen hotplug
When a display is connected to an Android device a notification is sent to the platform layer of the application. The QAndroidPlatformIntegration will create a platform screen and add it to QWindowSystem. Task-number: QAA-1257 Change-Id: Id2cf6b47363630c3b5c93c0bc778e2058d8372b3 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src/plugins/platforms/android')
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp23
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp65
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.h17
3 files changed, 101 insertions, 4 deletions
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 9ce899d4a3..5b066fb5a5 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -755,6 +755,24 @@ static void handleRefreshRateChanged(JNIEnv */*env*/, jclass /*cls*/, jfloat ref
m_androidPlatformIntegration->setRefreshRate(refreshRate);
}
+static void handleScreenAdded(JNIEnv */*env*/, jclass /*cls*/, jint displayId)
+{
+ if (m_androidPlatformIntegration)
+ m_androidPlatformIntegration->handleScreenAdded(displayId);
+}
+
+static void handleScreenChanged(JNIEnv */*env*/, jclass /*cls*/, jint displayId)
+{
+ if (m_androidPlatformIntegration)
+ m_androidPlatformIntegration->handleScreenChanged(displayId);
+}
+
+static void handleScreenRemoved(JNIEnv */*env*/, jclass /*cls*/, jint displayId)
+{
+ if (m_androidPlatformIntegration)
+ m_androidPlatformIntegration->handleScreenRemoved(displayId);
+}
+
static void handleUiDarkModeChanged(JNIEnv */*env*/, jobject /*thiz*/, jint newUiMode)
{
QAndroidPlatformIntegration::setAppearance(
@@ -795,7 +813,10 @@ static JNINativeMethod methods[] = {
{ "onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult },
{ "onNewIntent", "(Landroid/content/Intent;)V", (void *)onNewIntent },
{ "onBind", "(Landroid/content/Intent;)Landroid/os/IBinder;", (void *)onBind },
- { "handleRefreshRateChanged", "(F)V", (void *)handleRefreshRateChanged }
+ { "handleRefreshRateChanged", "(F)V", (void *)handleRefreshRateChanged },
+ { "handleScreenAdded", "(I)V", (void *)handleScreenAdded },
+ { "handleScreenChanged", "(I)V", (void *)handleScreenChanged },
+ { "handleScreenRemoved", "(I)V", (void *)handleScreenRemoved }
};
#define FIND_AND_CHECK_CLASS(CLASS_NAME) \
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index 0d5b473477..dec9082eca 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -61,6 +61,21 @@ Q_DECLARE_JNI_CLASS(Display, "android/view/Display")
Q_DECLARE_JNI_TYPE(List, "Ljava/util/List;")
+namespace {
+
+QAndroidPlatformScreen* createScreenForDisplayId(int displayId)
+{
+ const QJniObject display = QJniObject::callStaticObjectMethod<QtJniTypes::Display>(
+ QtJniTypes::className<QtJniTypes::QtNative>(),
+ "getDisplay",
+ displayId);
+ if (!display.isValid())
+ return nullptr;
+ return new QAndroidPlatformScreen(display);
+}
+
+} // anonymous namespace
+
void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteArray &resource)
{
if (resource=="JavaVM")
@@ -168,7 +183,7 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API)))
qFatal("Could not bind GL_ES API");
- static const int primaryDisplayId = QJniObject::getStaticField<jint>(
+ m_primaryDisplayId = QJniObject::getStaticField<jint>(
QtJniTypes::className<QtJniTypes::Display>(), "DEFAULT_DISPLAY");
const QJniObject nativeDisplaysList = QJniObject::callStaticObjectMethod<QtJniTypes::List>(
@@ -179,14 +194,15 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
for (int i = 0; i < numberOfAvailableDisplays; ++i) {
const QJniObject display =
nativeDisplaysList.callObjectMethod<jobject, jint>("get", jint(i));
-
- const bool isPrimary = (primaryDisplayId == display.callMethod<jint>("getDisplayId"));
+ const int displayId = display.callMethod<jint>("getDisplayId");
+ const bool isPrimary = (m_primaryDisplayId == displayId);
auto screen = new QAndroidPlatformScreen(display);
if (isPrimary)
m_primaryScreen = screen;
QWindowSystemInterface::handleScreenAdded(screen, isPrimary);
+ m_screens[displayId] = screen;
}
if (numberOfAvailableDisplays == 0) {
@@ -545,6 +561,49 @@ void QAndroidPlatformIntegration::setRefreshRate(qreal refreshRate)
QMetaObject::invokeMethod(m_primaryScreen, "setRefreshRate", Qt::AutoConnection,
Q_ARG(qreal, refreshRate));
}
+
+void QAndroidPlatformIntegration::handleScreenAdded(int displayId)
+{
+ auto result = m_screens.insert(displayId, nullptr);
+ if (result.first->second == nullptr) {
+ auto it = result.first;
+ it->second = createScreenForDisplayId(displayId);
+ if (it->second == nullptr)
+ return;
+ const bool isPrimary = (m_primaryDisplayId == displayId);
+ if (isPrimary)
+ m_primaryScreen = it->second;
+ QWindowSystemInterface::handleScreenAdded(it->second, isPrimary);
+ } else {
+ qWarning() << "Display with id" << displayId << "already exists.";
+ }
+}
+
+void QAndroidPlatformIntegration::handleScreenChanged(int displayId)
+{
+ auto it = m_screens.find(displayId);
+ if (it == m_screens.end() || it->second == nullptr) {
+ handleScreenAdded(displayId);
+ }
+ // We do not do anything more here as handling of change of
+ // rotation and refresh rate is done in QtActivityDelegate java class
+ // which calls QAndroidPlatformIntegration::setOrientation, and
+ // QAndroidPlatformIntegration::setRefreshRate accordingly.
+}
+
+void QAndroidPlatformIntegration::handleScreenRemoved(int displayId)
+{
+ auto it = m_screens.find(displayId);
+
+ if (it == m_screens.end())
+ return;
+
+ if (it->second != nullptr)
+ QWindowSystemInterface::handleScreenRemoved(it->second);
+
+ m_screens.erase(it);
+}
+
#if QT_CONFIG(vulkan)
QPlatformVulkanInstance *QAndroidPlatformIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h
index 4685ba32d4..8463dc8949 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.h
+++ b/src/plugins/platforms/android/qandroidplatformintegration.h
@@ -14,6 +14,8 @@
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformoffscreensurface.h>
#include <qpa/qplatformtheme.h>
+#include <private/qflatmap_p.h>
+#include <QtCore/qvarlengtharray.h>
#include <EGL/egl.h>
#include <memory>
@@ -75,6 +77,10 @@ public:
QPlatformFontDatabase *fontDatabase() const override;
+ void handleScreenAdded(int displayId);
+ void handleScreenChanged(int displayId);
+ void handleScreenRemoved(int displayId);
+
#ifndef QT_NO_CLIPBOARD
QPlatformClipboard *clipboard() const override;
#endif
@@ -132,6 +138,17 @@ private:
QAndroidPlatformNativeInterface *m_androidPlatformNativeInterface;
QAndroidPlatformServices *m_androidPlatformServices;
+ // Handling the multiple screens connected. Every display is identified
+ // with an unique (autoincremented) displayID. The values of this ID will
+ // not repeat during the OS runtime. We use this value as the key in the
+ // storage of screens.
+ QFlatMap<int, QAndroidPlatformScreen *, std::less<int>
+ , QVarLengthArray<int, 10>
+ , QVarLengthArray<QAndroidPlatformScreen *, 10> > m_screens;
+ // ID of the primary display, in documentation it is said to be always 0,
+ // but nevertheless it is retrieved
+ int m_primaryDisplayId = 0;
+
#ifndef QT_NO_CLIPBOARD
QPlatformClipboard *m_androidPlatformClipboard;
#endif