From 7dcf58eedbeb0cbfbf01f3aabfb72f8546f96cdf Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Mon, 6 Jan 2025 21:21:21 +0200 Subject: [PATCH] Android: separate setting screen size from setDisplayMetrics() The screen size doens't need to be updated each time the layout size is changed, they don't always happen together. The screen size change happens less often than the layout/available size. Thus, do handle only layout change under setDisplayMetrics() and move screen size changes to onDisplayChanged() callback where it logically belongs. Along the way rename setDisplayMetrics() to handleLayoutSizeChanged() to reflect what it actually does now after the cleanups. Task-number: QTBUG-132720 Change-Id: I9dfcfe4a0d2c0be36fb0a5fbf5975c7d466ddef2 Reviewed-by: Petri Virkkunen --- .../qt/android/QtDisplayManager.java | 12 +---- .../qt/android/QtEmbeddedDelegate.java | 3 +- .../qtproject/qt/android/QtRootLayout.java | 4 +- .../qt/android/QtServiceEmbeddedDelegate.java | 2 +- .../platforms/android/androidjnimain.cpp | 22 ++++---- .../android/qandroidplatformintegration.cpp | 30 +++++------ .../android/qandroidplatformintegration.h | 5 -- .../android/qandroidplatformscreen.cpp | 52 +++++++++---------- .../android/qandroidplatformscreen.h | 4 +- 9 files changed, 56 insertions(+), 78 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java index 17678a7c758..551385653c7 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java @@ -32,8 +32,7 @@ import android.content.res.Resources.Theme; class QtDisplayManager { // screen methods - static native void setDisplayMetrics(int screenWidthPixels, int screenHeightPixels, - int availableWidthPixels, int availableHeightPixels); + static native void handleLayoutSizeChanged(int availableWidth, int availableHeight); static native void handleOrientationChanged(int newRotation, int nativeOrientation); static native void handleRefreshRateChanged(float refreshRate); static native void handleUiDarkModeChanged(int newUiMode); @@ -290,15 +289,6 @@ class QtDisplayManager { } } - static void setApplicationDisplayMetrics(Activity activity, int width, int height) - { - if (activity == null) - return; - - Size displaySize = getDisplaySize(activity, QtDisplayManager.getDisplay(activity)); - setDisplayMetrics(displaySize.getWidth(), displaySize.getHeight(), width, height); - } - @UsedFromNativeCode static float getXDpi(final DisplayMetrics metrics) { if (metrics.xdpi < android.util.DisplayMetrics.DENSITY_LOW) 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 fbd3162264b..6b48cf5b44b 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtEmbeddedDelegate.java @@ -113,8 +113,7 @@ class QtEmbeddedDelegate extends QtActivityDelegateBase if (ready) { QtNative.runAction(() -> { DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); - QtDisplayManager.setApplicationDisplayMetrics(m_activity, metrics.widthPixels, - metrics.heightPixels); + QtDisplayManager.handleLayoutSizeChanged(metrics.widthPixels, metrics.heightPixels); }); } } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java b/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java index 71fb750b9e9..761c5fbea20 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtRootLayout.java @@ -23,10 +23,10 @@ class QtRootLayout extends QtLayout protected void onSizeChanged(int w, int h, int oldw, int oldh) { Activity activity = (Activity) getContext(); - if (activity == null) + if (activity == null || (w == oldw && h == oldh)) return; - QtDisplayManager.setApplicationDisplayMetrics(activity, w, h); + QtDisplayManager.handleLayoutSizeChanged(w, h); } @Override diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java index 08e098c6188..52ca1d92709 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceEmbeddedDelegate.java @@ -40,7 +40,7 @@ class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.App final int maxWidth = metrics.widthPixels; final int maxHeight = metrics.heightPixels; - QtDisplayManager.setDisplayMetrics(maxWidth, maxHeight, maxWidth, maxHeight); + QtDisplayManager.handleLayoutSizeChanged(maxWidth, maxHeight); QtDisplayManager.updateRefreshRate(m_service); QtDisplayManager.handleScreenDensityChanged(metrics.density); diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index f2c317ad1bf..ab42b62d04f 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -565,24 +565,24 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/) sem_post(&m_exitSemaphore); } -static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, - jint screenWidthPixels, jint screenHeightPixels, - jint availableWidthPixels, jint availableHeightPixels) +static void handleLayoutSizeChanged(JNIEnv * /*env*/, jclass /*clazz*/, + jint availableWidth, jint availableHeight) { - m_availableWidthPixels = availableWidthPixels; - m_availableHeightPixels = availableHeightPixels; + if (m_availableWidthPixels == availableWidth && m_availableHeightPixels == availableHeight) + return; - const QSize screenSize(screenWidthPixels, screenHeightPixels); - // available geometry always starts from top left - const QRect availableGeometry(0, 0, availableWidthPixels, availableHeightPixels); + m_availableWidthPixels = availableWidth; + m_availableHeightPixels = availableHeight; QMutexLocker lock(&m_platformMutex); + // available geometry always starts from top left + const QRect availableGeometry(0, 0, availableWidth, availableHeight); if (m_androidPlatformIntegration) - m_androidPlatformIntegration->setScreenSizeParameters(screenSize, availableGeometry); + m_androidPlatformIntegration->setAvailableGeometry(availableGeometry); else if (QAndroidPlatformScreen::defaultAvailableGeometry().isNull()) QAndroidPlatformScreen::defaultAvailableGeometry() = availableGeometry; } -Q_DECLARE_JNI_NATIVE_METHOD(setDisplayMetrics) +Q_DECLARE_JNI_NATIVE_METHOD(handleLayoutSizeChanged) static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state) { @@ -785,7 +785,7 @@ static bool registerNatives(QJniEnvironment &env) success &= env.registerNativeMethods( QtJniTypes::Traits::className(), { - Q_JNI_NATIVE_METHOD(setDisplayMetrics), + Q_JNI_NATIVE_METHOD(handleLayoutSizeChanged), Q_JNI_NATIVE_METHOD(handleOrientationChanged), Q_JNI_NATIVE_METHOD(handleRefreshRateChanged), Q_JNI_NATIVE_METHOD(handleScreenAdded), diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 8cd67b27b51..7c9e5193a92 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -499,10 +499,8 @@ void QAndroidPlatformIntegration::setScreenOrientation(Qt::ScreenOrientation cur void QAndroidPlatformIntegration::flushPendingUpdates() { - if (m_primaryScreen) { - m_primaryScreen->setSizeParameters( - m_primaryScreen->geometry().size(), m_primaryScreen->availableGeometry()); - } + if (m_primaryScreen) + m_primaryScreen->setAvailableGeometry(m_primaryScreen->availableGeometry()); } #if QT_CONFIG(accessibility) @@ -542,15 +540,6 @@ void QAndroidPlatformIntegration::updateColorScheme(Qt::ColorScheme colorScheme) [] () { QAndroidPlatformTheme::instance()->updateColorScheme();}); } -void QAndroidPlatformIntegration::setScreenSizeParameters(const QSize &screenSize, - const QRect &availableGeometry) -{ - if (m_primaryScreen) { - QMetaObject::invokeMethod(m_primaryScreen, "setSizeParameters", Qt::AutoConnection, - Q_ARG(QSize, screenSize), Q_ARG(QRect, availableGeometry)); - } -} - void QAndroidPlatformIntegration::setRefreshRate(qreal refreshRate) { if (m_primaryScreen) @@ -581,10 +570,17 @@ void QAndroidPlatformIntegration::handleScreenChanged(int 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. + + if (QAndroidPlatformScreen *screen = it->second) { + QSize size = QAndroidPlatformScreen::sizeForDisplayId(displayId); + if (screen->geometry().size() != size) { + screen->setPhysicalSizeFromPixels(size); + screen->setSize(size); + } + } + + // We do not do handle changes in rotation, refresh rate and density + // as they are done under QtDisplayManager. } void QAndroidPlatformIntegration::handleScreenRemoved(int displayId) diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index b42727cd699..22f2a6e672b 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -66,11 +66,6 @@ public: void setAvailableGeometry(const QRect &availableGeometry); void setPhysicalSize(int width, int height); void setScreenSize(int width, int height); - // The 3 methods above were replaced by a new one, so that we could have - // a better control over "geometry changed" event handling. Technically - // they are no longer used and can be removed. Not doing it now, because - // I'm not sure if it might be helpful to have them or not. - void setScreenSizeParameters(const QSize &screenSize, const QRect &availableGeometry); void setRefreshRate(qreal refreshRate); bool isVirtualDesktop() { return true; } diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 65c50103623..b1037b9544b 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -82,14 +82,10 @@ QAndroidPlatformScreen::QAndroidPlatformScreen(const QJniObject &displayObject) m_name = displayObject.callObjectMethod("getName").toString(); m_refreshRate = displayObject.callMethod("getRefreshRate"); m_displayId = displayObject.callMethod("getDisplayId"); - - const auto context = QNativeInterface::QAndroidApplication::context(); - const auto sizeObj = QtJniTypes::QtDisplayManager::callStaticMethod( - "getDisplaySize", context, - displayObject.object()); - m_size = QSize(sizeObj.callMethod("getWidth"), sizeObj.callMethod("getHeight")); + m_size = sizeForDisplayId(m_displayId); m_availableGeometry = defaultAvailableGeometry(); + const auto context = QNativeInterface::QAndroidApplication::context(); const auto resources = context.callMethod("getResources"); const auto metrics = resources.callMethod("getDisplayMetrics"); m_xdpi = QtJniTypes::QtDisplayManager::callStaticMethod("getXDpi", metrics); @@ -98,8 +94,7 @@ QAndroidPlatformScreen::QAndroidPlatformScreen(const QJniObject &displayObject) // Potentially densityDpi could be used instead of xpdi/ydpi to do the calculation, // but the results are not consistent with devices specs. // (https://issuetracker.google.com/issues/194120500) - m_physicalSize.setWidth(qRound(m_size.width() / m_xdpi * 25.4)); - m_physicalSize.setHeight(qRound(m_size.height() / m_ydpi * 25.4)); + setPhysicalSizeFromPixels(m_size); if (QNativeInterface::QAndroidApplication::sdkVersion() >= 23) { const QJniObject currentMode = displayObject.callObjectMethod("getMode"); @@ -126,6 +121,19 @@ QAndroidPlatformScreen::~QAndroidPlatformScreen() { } +QSize QAndroidPlatformScreen::sizeForDisplayId(int displayId) +{ + using namespace QtJniTypes; + const auto context = QNativeInterface::QAndroidApplication::context(); + const auto display = QtDisplayManager::callStaticMethod( + "getDisplay", context, displayId); + const auto sizeObj = QtDisplayManager::callStaticMethod( + "getDisplaySize", context, display); + + return QSize(sizeObj.callMethod("getWidth"), sizeObj.callMethod("getHeight")); + +} + QWindow *QAndroidPlatformScreen::topVisibleWindow() const { for (QAndroidPlatformWindow *w : m_windowStack) { @@ -213,28 +221,18 @@ void QAndroidPlatformScreen::setPhysicalSize(const QSize &size) m_physicalSize = size; } +void QAndroidPlatformScreen::setPhysicalSizeFromPixels(const QSize &size) +{ + m_physicalSize = QSize( + qRound(double(size.width()) / m_xdpi * 25.4), + qRound(double(size.height()) / m_ydpi * 25.4)); +} + void QAndroidPlatformScreen::setSize(const QSize &size) { m_size = size; - QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry()); -} - -void QAndroidPlatformScreen::setSizeParameters(const QSize &size, const QRect &availableGeometry) -{ - // The goal of this method is to set all geometry-related parameters - // at the same time and generate only one screen geometry change event. - m_size = size; - m_physicalSize = QSize(qRound(double(size.width()) / m_xdpi * 25.4), - qRound(double(size.height()) / m_ydpi * 25.4)); - // If available geometry has changed, the event will be handled in - // setAvailableGeometry. Otherwise we need to explicitly handle it to - // retain the behavior, because setSize() does the handling unconditionally. - if (m_availableGeometry != availableGeometry) { - setAvailableGeometry(availableGeometry); - } else { - QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), - this->availableGeometry()); - } + QWindowSystemInterface::handleScreenGeometryChange( + QPlatformScreen::screen(), geometry(), availableGeometry()); } int QAndroidPlatformScreen::displayId() const diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h index d77d53ede5d..51fd3c66201 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.h +++ b/src/plugins/platforms/android/qandroidplatformscreen.h @@ -17,7 +17,6 @@ QT_BEGIN_NAMESPACE class QAndroidPlatformWindow; - class QAndroidPlatformScreen : public QObject, public QPlatformScreen, public QNativeInterface::QAndroidScreen @@ -49,12 +48,13 @@ public: int displayId() const override; static QRect &defaultAvailableGeometry(); + static QSize sizeForDisplayId(int displayId); public slots: void setPhysicalSize(const QSize &size); + void setPhysicalSizeFromPixels(const QSize &size); void setAvailableGeometry(const QRect &rect); void setSize(const QSize &size); - void setSizeParameters(const QSize &size, const QRect &availableGeometry); void setRefreshRate(qreal refreshRate); void setOrientation(Qt::ScreenOrientation orientation);