qpa: Make screen geometry updates (full and available geometry) atomic

Updating the geometry and available geometry in two steps means that
QScreen will be in an inconsistent state when emitting the geometry
change signal, as the available geometry has not been updated yet.

Piggy-backing changes to the availableGeometry based on the virtual
geometry changing does not make sense, so we now tie geometry and
availableGeometry (and their size variants) to their own separate
geometryChanged and availableGeometryChanged signals.

Change-Id: Iee0ced642cbb91c470cb54bc507d2c0512482c13
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
This commit is contained in:
Tor Arne Vestbø 2014-07-28 15:37:05 +02:00
parent 2d2dc976d8
commit 2368e62f32
14 changed files with 58 additions and 93 deletions

View File

@ -1646,10 +1646,6 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
QGuiApplicationPrivate::reportGeometryChange( QGuiApplicationPrivate::reportGeometryChange(
static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e)); static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e));
break; break;
case QWindowSystemInterfacePrivate::ScreenAvailableGeometry:
QGuiApplicationPrivate::reportAvailableGeometryChange(
static_cast<QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *>(e));
break;
case QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInch: case QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInch:
QGuiApplicationPrivate::reportLogicalDotsPerInchChange( QGuiApplicationPrivate::reportLogicalDotsPerInchChange(
static_cast<QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *>(e)); static_cast<QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *>(e));
@ -2546,8 +2542,14 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate:
return; return;
QScreen *s = e->screen.data(); QScreen *s = e->screen.data();
bool geometryChanged = e->geometry != s->d_func()->geometry;
s->d_func()->geometry = e->geometry; s->d_func()->geometry = e->geometry;
bool availableGeometryChanged = e->availableGeometry != s->d_func()->availableGeometry;
s->d_func()->availableGeometry = e->availableGeometry;
if (geometryChanged) {
Qt::ScreenOrientation primaryOrientation = s->primaryOrientation(); Qt::ScreenOrientation primaryOrientation = s->primaryOrientation();
s->d_func()->updatePrimaryOrientation(); s->d_func()->updatePrimaryOrientation();
@ -2555,31 +2557,21 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate:
emit s->physicalSizeChanged(s->physicalSize()); emit s->physicalSizeChanged(s->physicalSize());
emit s->physicalDotsPerInchChanged(s->physicalDotsPerInch()); emit s->physicalDotsPerInchChanged(s->physicalDotsPerInch());
emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch()); emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch());
foreach (QScreen* sibling, s->virtualSiblings())
emit sibling->virtualGeometryChanged(sibling->virtualGeometry());
if (s->primaryOrientation() != primaryOrientation) if (s->primaryOrientation() != primaryOrientation)
emit s->primaryOrientationChanged(s->primaryOrientation()); emit s->primaryOrientationChanged(s->primaryOrientation());
if (s->d_func()->orientation == Qt::PrimaryOrientation) if (s->d_func()->orientation == Qt::PrimaryOrientation)
updateFilteredScreenOrientation(s); updateFilteredScreenOrientation(s);
} }
void QGuiApplicationPrivate::reportAvailableGeometryChange( if (availableGeometryChanged)
QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e) emit s->availableGeometryChanged(s->geometry());
{
// This operation only makes sense after the QGuiApplication constructor runs
if (QCoreApplication::startingUp())
return;
if (!e->screen)
return;
QScreen *s = e->screen.data();
s->d_func()->availableGeometry = e->availableGeometry;
if (geometryChanged || availableGeometryChanged) {
foreach (QScreen* sibling, s->virtualSiblings()) foreach (QScreen* sibling, s->virtualSiblings())
emit sibling->virtualGeometryChanged(sibling->virtualGeometry()); emit sibling->virtualGeometryChanged(sibling->virtualGeometry());
}
} }
void QGuiApplicationPrivate::reportLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e) void QGuiApplicationPrivate::reportLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e)

View File

@ -137,7 +137,6 @@ public:
static void reportScreenOrientationChange(QScreen *screen); static void reportScreenOrientationChange(QScreen *screen);
static void reportScreenOrientationChange(QWindowSystemInterfacePrivate::ScreenOrientationEvent *e); static void reportScreenOrientationChange(QWindowSystemInterfacePrivate::ScreenOrientationEvent *e);
static void reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e); static void reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e);
static void reportAvailableGeometryChange(QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e);
static void reportLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e); static void reportLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e);
static void reportRefreshRateChange(QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *e); static void reportRefreshRateChange(QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *e);
static void processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *tce); static void processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *tce);

View File

@ -69,11 +69,11 @@ class Q_GUI_EXPORT QScreen : public QObject
Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(int depth READ depth CONSTANT) Q_PROPERTY(int depth READ depth CONSTANT)
Q_PROPERTY(QSize size READ size NOTIFY geometryChanged) Q_PROPERTY(QSize size READ size NOTIFY geometryChanged)
Q_PROPERTY(QSize availableSize READ availableSize NOTIFY virtualGeometryChanged) Q_PROPERTY(QSize availableSize READ availableSize NOTIFY availableGeometryChanged)
Q_PROPERTY(QSize virtualSize READ virtualSize NOTIFY virtualGeometryChanged) Q_PROPERTY(QSize virtualSize READ virtualSize NOTIFY virtualGeometryChanged)
Q_PROPERTY(QSize availableVirtualSize READ availableVirtualSize NOTIFY virtualGeometryChanged) Q_PROPERTY(QSize availableVirtualSize READ availableVirtualSize NOTIFY virtualGeometryChanged)
Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged) Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged)
Q_PROPERTY(QRect availableGeometry READ availableGeometry NOTIFY virtualGeometryChanged) Q_PROPERTY(QRect availableGeometry READ availableGeometry NOTIFY availableGeometryChanged)
Q_PROPERTY(QRect virtualGeometry READ virtualGeometry NOTIFY virtualGeometryChanged) Q_PROPERTY(QRect virtualGeometry READ virtualGeometry NOTIFY virtualGeometryChanged)
Q_PROPERTY(QRect availableVirtualGeometry READ availableVirtualGeometry NOTIFY virtualGeometryChanged) Q_PROPERTY(QRect availableVirtualGeometry READ availableVirtualGeometry NOTIFY virtualGeometryChanged)
Q_PROPERTY(QSizeF physicalSize READ physicalSize NOTIFY physicalSizeChanged) Q_PROPERTY(QSizeF physicalSize READ physicalSize NOTIFY physicalSizeChanged)
@ -142,6 +142,7 @@ public:
Q_SIGNALS: Q_SIGNALS:
void geometryChanged(const QRect &geometry); void geometryChanged(const QRect &geometry);
void availableGeometryChanged(const QRect &geometry);
void physicalSizeChanged(const QSizeF &size); void physicalSizeChanged(const QSizeF &size);
void physicalDotsPerInchChanged(qreal dpi); void physicalDotsPerInchChanged(qreal dpi);
void logicalDotsPerInchChanged(qreal dpi); void logicalDotsPerInchChanged(qreal dpi);

View File

@ -493,17 +493,10 @@ void QWindowSystemInterface::handleScreenOrientationChange(QScreen *screen, Qt::
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
} }
void QWindowSystemInterface::handleScreenGeometryChange(QScreen *screen, const QRect &geometry) void QWindowSystemInterface::handleScreenGeometryChange(QScreen *screen, const QRect &geometry, const QRect &availableGeometry)
{ {
QWindowSystemInterfacePrivate::ScreenGeometryEvent *e = QWindowSystemInterfacePrivate::ScreenGeometryEvent *e =
new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screen, geometry); new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screen, geometry, availableGeometry);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
void QWindowSystemInterface::handleScreenAvailableGeometryChange(QScreen *screen, const QRect &availableGeometry)
{
QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e =
new QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent(screen, availableGeometry);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
} }

View File

@ -164,8 +164,7 @@ public:
// Changes to the screen // Changes to the screen
static void handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation newOrientation); static void handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation newOrientation);
static void handleScreenGeometryChange(QScreen *screen, const QRect &newGeometry); static void handleScreenGeometryChange(QScreen *screen, const QRect &newGeometry, const QRect &newAvailableGeometry);
static void handleScreenAvailableGeometryChange(QScreen *screen, const QRect &newAvailableGeometry);
static void handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal newDpiX, qreal newDpiY); static void handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal newDpiX, qreal newDpiY);
static void handleScreenRefreshRateChange(QScreen *screen, qreal newRefreshRate); static void handleScreenRefreshRateChange(QScreen *screen, qreal newRefreshRate);

View File

@ -279,17 +279,10 @@ public:
class ScreenGeometryEvent : public WindowSystemEvent { class ScreenGeometryEvent : public WindowSystemEvent {
public: public:
ScreenGeometryEvent(QScreen *s, const QRect &g) ScreenGeometryEvent(QScreen *s, const QRect &g, const QRect &ag)
: WindowSystemEvent(ScreenGeometry), screen(s), geometry(g) { } : WindowSystemEvent(ScreenGeometry), screen(s), geometry(g), availableGeometry(ag) { }
QPointer<QScreen> screen; QPointer<QScreen> screen;
QRect geometry; QRect geometry;
};
class ScreenAvailableGeometryEvent : public WindowSystemEvent {
public:
ScreenAvailableGeometryEvent(QScreen *s, const QRect &g)
: WindowSystemEvent(ScreenAvailableGeometry), screen(s), availableGeometry(g) { }
QPointer<QScreen> screen;
QRect availableGeometry; QRect availableGeometry;
}; };

View File

@ -171,8 +171,7 @@ void QFbScreen::setGeometry(const QRect &rect)
mGeometry = rect; mGeometry = rect;
mScreenImage = new QImage(mGeometry.size(), mFormat); mScreenImage = new QImage(mGeometry.size(), mFormat);
invalidateRectCache(); invalidateRectCache();
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry());
resizeMaximizedWindows(); resizeMaximizedWindows();
} }

View File

@ -221,7 +221,7 @@ void QAndroidPlatformScreen::setPhysicalSize(const QSize &size)
void QAndroidPlatformScreen::setSize(const QSize &size) void QAndroidPlatformScreen::setSize(const QSize &size)
{ {
m_size = size; m_size = size;
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
} }
void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect) void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect)
@ -233,8 +233,7 @@ void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect)
QRect oldGeometry = m_availableGeometry; QRect oldGeometry = m_availableGeometry;
m_availableGeometry = rect; m_availableGeometry = rect;
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry());
resizeMaximizedWindows(); resizeMaximizedWindows();
if (oldGeometry.width() == 0 && oldGeometry.height() == 0 && rect.width() > 0 && rect.height() > 0) { if (oldGeometry.width() == 0 && oldGeometry.height() == 0 && rect.width() > 0 && rect.height() > 0) {

View File

@ -137,10 +137,9 @@ void QCocoaScreen::updateGeometry()
m_name = QString::fromUtf8([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]); m_name = QString::fromUtf8([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
[deviceInfo release]; [deviceInfo release];
QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry()); QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second); QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second);
QWindowSystemInterface::handleScreenRefreshRateChange(screen(), m_refreshRate); QWindowSystemInterface::handleScreenRefreshRateChange(screen(), m_refreshRate);
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), availableGeometry());
} }
qreal QCocoaScreen::devicePixelRatio() const qreal QCocoaScreen::devicePixelRatio() const

View File

@ -238,30 +238,26 @@ QIOSScreen::~QIOSScreen()
void QIOSScreen::updateProperties() void QIOSScreen::updateProperties()
{ {
QRect previousGeometry = m_geometry;
QRect previousAvailableGeometry = m_availableGeometry;
bool inPortrait = UIInterfaceOrientationIsPortrait(m_uiWindow.rootViewController.interfaceOrientation); bool inPortrait = UIInterfaceOrientationIsPortrait(m_uiWindow.rootViewController.interfaceOrientation);
QRect geometry = inPortrait ? fromCGRect(m_uiScreen.bounds).toRect() m_geometry = inPortrait ? fromCGRect(m_uiScreen.bounds).toRect()
: QRect(m_uiScreen.bounds.origin.x, m_uiScreen.bounds.origin.y, : QRect(m_uiScreen.bounds.origin.x, m_uiScreen.bounds.origin.y,
m_uiScreen.bounds.size.height, m_uiScreen.bounds.size.width); m_uiScreen.bounds.size.height, m_uiScreen.bounds.size.width);
if (geometry != m_geometry) { m_availableGeometry = m_geometry;
m_geometry = geometry;
CGSize applicationFrameSize = m_uiScreen.applicationFrame.size;
int statusBarHeight = m_geometry.height() - (inPortrait ? applicationFrameSize.height : applicationFrameSize.width);
m_availableGeometry.adjust(0, statusBarHeight, 0, 0);
if (m_geometry != previousGeometry || m_availableGeometry != previousAvailableGeometry) {
const qreal millimetersPerInch = 25.4; const qreal millimetersPerInch = 25.4;
m_physicalSize = QSizeF(m_geometry.size()) / m_unscaledDpi * millimetersPerInch; m_physicalSize = QSizeF(m_geometry.size()) / m_unscaledDpi * millimetersPerInch;
QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry); QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry, m_availableGeometry);
}
QRect availableGeometry = geometry;
CGSize applicationFrameSize = m_uiScreen.applicationFrame.size;
int statusBarHeight = geometry.height() - (inPortrait ? applicationFrameSize.height : applicationFrameSize.width);
availableGeometry.adjust(0, statusBarHeight, 0, 0);
if (availableGeometry != m_availableGeometry) {
m_availableGeometry = availableGeometry;
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_availableGeometry);
} }
if (screen()) if (screen())

View File

@ -445,7 +445,7 @@ void QQnxScreen::setRotation(int rotation)
// Rotating only the primary screen is what we had in the navigator event handler before refactoring // Rotating only the primary screen is what we had in the navigator event handler before refactoring
if (m_primaryScreen) { if (m_primaryScreen) {
QWindowSystemInterface::handleScreenOrientationChange(screen(), orientation()); QWindowSystemInterface::handleScreenOrientationChange(screen(), orientation());
QWindowSystemInterface::handleScreenGeometryChange(screen(), m_currentGeometry); QWindowSystemInterface::handleScreenGeometryChange(screen(), m_currentGeometry, availableGeometry());
} }
// Flush everything, so that the windows rotations are applied properly. // Flush everything, so that the windows rotations are applied properly.
@ -705,7 +705,7 @@ void QQnxScreen::keyboardHeightChanged(int height)
m_keyboardHeight = height; m_keyboardHeight = height;
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), availableGeometry()); QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
} }
void QQnxScreen::addOverlayWindow(screen_window_t window) void QQnxScreen::addOverlayWindow(screen_window_t window)

View File

@ -346,15 +346,11 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData)
{ {
m_data.physicalSizeMM = newData.physicalSizeMM; m_data.physicalSizeMM = newData.physicalSizeMM;
if (m_data.geometry != newData.geometry) { if (m_data.geometry != newData.geometry || m_data.availableGeometry != newData.availableGeometry) {
m_data.geometry = newData.geometry; m_data.geometry = newData.geometry;
QWindowSystemInterface::handleScreenGeometryChange(screen(),
newData.geometry);
}
if (m_data.availableGeometry != newData.availableGeometry) {
m_data.availableGeometry = newData.availableGeometry; m_data.availableGeometry = newData.availableGeometry;
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), QWindowSystemInterface::handleScreenGeometryChange(screen(),
newData.availableGeometry); newData.geometry, newData.availableGeometry);
} }
if (!qFuzzyCompare(m_data.dpi.first, newData.dpi.first) if (!qFuzzyCompare(m_data.dpi.first, newData.dpi.first)
|| !qFuzzyCompare(m_data.dpi.second, newData.dpi.second)) { || !qFuzzyCompare(m_data.dpi.second, newData.dpi.second)) {

View File

@ -1032,8 +1032,7 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *
// a more advanced compositor is written. // a more advanced compositor is written.
d->logicalSize = logicalSize; d->logicalSize = logicalSize;
const QRect newGeometry = geometry(); const QRect newGeometry = geometry();
QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry); QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), newGeometry);
QPlatformScreen::resizeMaximizedWindows(); QPlatformScreen::resizeMaximizedWindows();
handleExpose(); handleExpose();

View File

@ -403,7 +403,7 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
case XCB_RANDR_ROTATION_REFLECT_Y: break; case XCB_RANDR_ROTATION_REFLECT_Y: break;
} }
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation); QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation);
QDpi ldpi = logicalDpi(); QDpi ldpi = logicalDpi();
@ -451,7 +451,7 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
m_geometry = QRect(xGeometry.topLeft()/dpr, xGeometry.size()/dpr); m_geometry = QRect(xGeometry.topLeft()/dpr, xGeometry.size()/dpr);
m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr); m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr);
QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), m_availableGeometry); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
} }
void QXcbScreen::updateRefreshRate() void QXcbScreen::updateRefreshRate()