From 285ea132861f8b8d1b5d1ea0f966c141da985953 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Wed, 23 Feb 2022 14:41:47 +0100 Subject: [PATCH] Android: set all QScreen's geometry-related parameters together Screen has 3 parameters: - physical size - screen size (or screen geometry) - available geometry Before this patch, they were reported in 3 different methods. Screen size update and available geometry update both were generating the "screen geometry changed" event, that updated the user-visible parameters. As a result, at some point we could end up in an intermediate state, when screen size was already updated, but available geometry was not yet updated. This was specially visible while changing the screen orientation: at some point screen geometry could be reported for the new orientation, while the available geometry - still for old orientation. This patch introduces a new method to set all geometry-related parameters together and generate only one "screen geometry changed" event. This allows to maintain consistency between 'geometry' and 'availableGeometry' properties of QScreen. Task-number: QTBUG-94459 Pick-to: 6.3 6.2 5.15 Change-Id: I844f6d0db87df8d5e6e9bcce5d27126384a5a0de Reviewed-by: Assam Boudjelthia --- .../platforms/android/androidjnimain.cpp | 12 ++++++----- .../android/qandroidplatformintegration.cpp | 21 +++++++++++++------ .../android/qandroidplatformintegration.h | 6 ++++++ .../android/qandroidplatformscreen.cpp | 18 ++++++++++++++++ .../android/qandroidplatformscreen.h | 2 ++ 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 280cfa2c538..ac1b29ba5b4 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -657,11 +657,13 @@ static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, jint screenWid qRound(double(screenHeightPixels) / ydpi * 25.4), screenWidthPixels, screenHeightPixels); } else { - m_androidPlatformIntegration->setPhysicalSize(qRound(double(screenWidthPixels) / xdpi * 25.4), - qRound(double(screenHeightPixels) / ydpi * 25.4)); - m_androidPlatformIntegration->setScreenSize(screenWidthPixels, screenHeightPixels); - m_androidPlatformIntegration->setAvailableGeometry(QRect(availableLeftPixels, availableTopPixels, - availableWidthPixels, availableHeightPixels)); + const QSize physicalSize(qRound(double(screenWidthPixels) / xdpi * 25.4), + qRound(double(screenHeightPixels) / ydpi * 25.4)); + const QSize screenSize(screenWidthPixels, screenHeightPixels); + const QRect availableGeometry(availableLeftPixels, availableTopPixels, + availableWidthPixels, availableHeightPixels); + m_androidPlatformIntegration->setScreenSizeParameters(physicalSize, screenSize, + availableGeometry); m_androidPlatformIntegration->setRefreshRate(refreshRate); } } diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 8f2b7970f1f..2a080db51df 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -199,9 +199,8 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ m_primaryScreen = new QAndroidPlatformScreen(); QWindowSystemInterface::handleScreenAdded(m_primaryScreen); - m_primaryScreen->setPhysicalSize(m_defaultPhysicalSize); - m_primaryScreen->setSize(m_defaultScreenSize); - m_primaryScreen->setAvailableGeometry(m_defaultAvailableGeometry); + m_primaryScreen->setSizeParameters(m_defaultPhysicalSize, m_defaultScreenSize, + m_defaultAvailableGeometry); m_mainThread = QThread::currentThread(); @@ -492,9 +491,8 @@ void QAndroidPlatformIntegration::setScreenOrientation(Qt::ScreenOrientation cur void QAndroidPlatformIntegration::flushPendingUpdates() { - m_primaryScreen->setPhysicalSize(m_defaultPhysicalSize); - m_primaryScreen->setSize(m_defaultScreenSize); - m_primaryScreen->setAvailableGeometry(m_defaultAvailableGeometry); + m_primaryScreen->setSizeParameters(m_defaultPhysicalSize, m_defaultScreenSize, + m_defaultAvailableGeometry); } #ifndef QT_NO_ACCESSIBILITY @@ -522,6 +520,17 @@ void QAndroidPlatformIntegration::setScreenSize(int width, int height) QMetaObject::invokeMethod(m_primaryScreen, "setSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height))); } +void QAndroidPlatformIntegration::setScreenSizeParameters(const QSize &physicalSize, + const QSize &screenSize, + const QRect &availableGeometry) +{ + if (m_primaryScreen) { + QMetaObject::invokeMethod(m_primaryScreen, "setSizeParameters", Qt::AutoConnection, + Q_ARG(QSize, physicalSize), Q_ARG(QSize, screenSize), + Q_ARG(QRect, availableGeometry)); + } +} + void QAndroidPlatformIntegration::setRefreshRate(qreal refreshRate) { if (m_primaryScreen) diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index 4fffed651b7..bd950ae68e3 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -99,6 +99,12 @@ 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 &physicalSize, 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 59c8f396afe..75967f5678c 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -283,6 +283,24 @@ void QAndroidPlatformScreen::setSize(const QSize &size) QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry()); } +void QAndroidPlatformScreen::setSizeParameters(const QSize &physicalSize, 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_physicalSize = physicalSize; + m_size = size; + // 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()); + } +} + void QAndroidPlatformScreen::setRefreshRate(qreal refreshRate) { if (refreshRate == m_refreshRate) diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h index e0de85277a8..4a06bb20bd9 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.h +++ b/src/plugins/platforms/android/qandroidplatformscreen.h @@ -93,6 +93,8 @@ public slots: void setPhysicalSize(const QSize &size); void setAvailableGeometry(const QRect &rect); void setSize(const QSize &size); + void setSizeParameters(const QSize &physicalSize, const QSize &size, + const QRect &availableGeometry); void setRefreshRate(qreal refreshRate); protected: