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 <assam.boudjelthia@qt.io>
This commit is contained in:
Ivan Solovev 2022-02-23 14:41:47 +01:00
parent eec317a138
commit 285ea13286
5 changed files with 48 additions and 11 deletions

View File

@ -657,11 +657,13 @@ static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, jint screenWid
qRound(double(screenHeightPixels) / ydpi * 25.4), screenWidthPixels, qRound(double(screenHeightPixels) / ydpi * 25.4), screenWidthPixels,
screenHeightPixels); screenHeightPixels);
} else { } else {
m_androidPlatformIntegration->setPhysicalSize(qRound(double(screenWidthPixels) / xdpi * 25.4), const QSize physicalSize(qRound(double(screenWidthPixels) / xdpi * 25.4),
qRound(double(screenHeightPixels) / ydpi * 25.4)); qRound(double(screenHeightPixels) / ydpi * 25.4));
m_androidPlatformIntegration->setScreenSize(screenWidthPixels, screenHeightPixels); const QSize screenSize(screenWidthPixels, screenHeightPixels);
m_androidPlatformIntegration->setAvailableGeometry(QRect(availableLeftPixels, availableTopPixels, const QRect availableGeometry(availableLeftPixels, availableTopPixels,
availableWidthPixels, availableHeightPixels)); availableWidthPixels, availableHeightPixels);
m_androidPlatformIntegration->setScreenSizeParameters(physicalSize, screenSize,
availableGeometry);
m_androidPlatformIntegration->setRefreshRate(refreshRate); m_androidPlatformIntegration->setRefreshRate(refreshRate);
} }
} }

View File

@ -199,9 +199,8 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
m_primaryScreen = new QAndroidPlatformScreen(); m_primaryScreen = new QAndroidPlatformScreen();
QWindowSystemInterface::handleScreenAdded(m_primaryScreen); QWindowSystemInterface::handleScreenAdded(m_primaryScreen);
m_primaryScreen->setPhysicalSize(m_defaultPhysicalSize); m_primaryScreen->setSizeParameters(m_defaultPhysicalSize, m_defaultScreenSize,
m_primaryScreen->setSize(m_defaultScreenSize); m_defaultAvailableGeometry);
m_primaryScreen->setAvailableGeometry(m_defaultAvailableGeometry);
m_mainThread = QThread::currentThread(); m_mainThread = QThread::currentThread();
@ -492,9 +491,8 @@ void QAndroidPlatformIntegration::setScreenOrientation(Qt::ScreenOrientation cur
void QAndroidPlatformIntegration::flushPendingUpdates() void QAndroidPlatformIntegration::flushPendingUpdates()
{ {
m_primaryScreen->setPhysicalSize(m_defaultPhysicalSize); m_primaryScreen->setSizeParameters(m_defaultPhysicalSize, m_defaultScreenSize,
m_primaryScreen->setSize(m_defaultScreenSize); m_defaultAvailableGeometry);
m_primaryScreen->setAvailableGeometry(m_defaultAvailableGeometry);
} }
#ifndef QT_NO_ACCESSIBILITY #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))); 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) void QAndroidPlatformIntegration::setRefreshRate(qreal refreshRate)
{ {
if (m_primaryScreen) if (m_primaryScreen)

View File

@ -99,6 +99,12 @@ public:
void setAvailableGeometry(const QRect &availableGeometry); void setAvailableGeometry(const QRect &availableGeometry);
void setPhysicalSize(int width, int height); void setPhysicalSize(int width, int height);
void setScreenSize(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); void setRefreshRate(qreal refreshRate);
bool isVirtualDesktop() { return true; } bool isVirtualDesktop() { return true; }

View File

@ -283,6 +283,24 @@ void QAndroidPlatformScreen::setSize(const QSize &size)
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry()); 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) void QAndroidPlatformScreen::setRefreshRate(qreal refreshRate)
{ {
if (refreshRate == m_refreshRate) if (refreshRate == m_refreshRate)

View File

@ -93,6 +93,8 @@ public slots:
void setPhysicalSize(const QSize &size); void setPhysicalSize(const QSize &size);
void setAvailableGeometry(const QRect &rect); void setAvailableGeometry(const QRect &rect);
void setSize(const QSize &size); void setSize(const QSize &size);
void setSizeParameters(const QSize &physicalSize, const QSize &size,
const QRect &availableGeometry);
void setRefreshRate(qreal refreshRate); void setRefreshRate(qreal refreshRate);
protected: protected: