Only show QWindows after QScreen destruction if coming from virtual sibling

For windows that were shown on an external screen (not a virtual sibling
of the primary screen), eg. on iOS, it doesn't make sense to re-show the
window when moved back to the primary screen.

By moving the logic into the QScreen destructor, we ensure that the code
path is hit both for the old and unsupported style way of destroying
QPlatformScreen by deleting it directly, and the new and safe way
of using QPlatformIntegration::destroyScreen(), while still allowing
clients to manage the windows themselves by emitting screenRemoved()
before applying our fallback logic.

[ChangeLog][QtGui][Important Behavior Changes] QWindows will no longer
be re-shown automatically when moved from a destroyed QScreen, unless
that QScreen was a virtual sibling of the primary screen.

Change-Id: If1105bc5ef41a5392854bb97d121c998bffa3606
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
bb10
Tor Arne Vestbø 2015-01-21 18:04:29 +01:00 committed by Tor Arne Vestbø
parent 38abd65377
commit a2b358e7f5
3 changed files with 30 additions and 29 deletions

View File

@ -72,8 +72,35 @@ QScreen::QScreen(QPlatformScreen *screen)
*/
QScreen::~QScreen()
{
if (qApp)
Q_EMIT qApp->screenRemoved(this);
if (!qApp)
return;
// Allow clients to manage windows that are affected by the screen going
// away, before we fall back to moving them to the primary screen.
emit qApp->screenRemoved(this);
if (QGuiApplication::closingDown())
return;
QScreen *primaryScreen = QGuiApplication::primaryScreen();
if (this == primaryScreen)
return;
bool movingFromVirtualSibling = primaryScreen->handle()->virtualSiblings().contains(handle());
// Move any leftover windows to the primary screen
foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
if (window->screen() != this)
continue;
const bool wasVisible = window->isVisible();
window->setScreen(primaryScreen);
// Re-show window if moved from a virtual sibling screen. Otherwise
// leave it up to the application developer to show the window.
if (movingFromVirtualSibling)
window->setVisible(wasVisible);
}
}
/*!

View File

@ -344,20 +344,14 @@ inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const
inline void QWindowPrivate::disconnectFromScreen()
{
if (topLevelScreen) {
Q_Q(QWindow);
QObject::disconnect(topLevelScreen, &QObject::destroyed, q, &QWindow::screenDestroyed);
if (topLevelScreen)
topLevelScreen = 0;
}
}
void QWindowPrivate::connectToScreen(QScreen *screen)
{
Q_Q(QWindow);
disconnectFromScreen();
topLevelScreen = screen;
if (topLevelScreen)
QObject::connect(topLevelScreen, &QObject::destroyed, q, &QWindow::screenDestroyed);
}
void QWindowPrivate::emitScreenChangedRecursion(QScreen *newScreen)
@ -1712,23 +1706,6 @@ void QWindow::setScreen(QScreen *newScreen)
d->setTopLevelScreen(newScreen, true /* recreate */);
}
void QWindow::screenDestroyed(QObject *object)
{
Q_D(QWindow);
if (d->parentWindow || QGuiApplication::closingDown())
return;
if (object == static_cast<QObject *>(d->topLevelScreen)) {
const bool wasVisible = isVisible();
setScreen(0);
// destroy() might have hidden our window, show it again.
// This might not be the best behavior if the new screen isn't a virtual sibling
// of the old one. This can be removed once platform plugins have the power to
// update the QScreen of its QWindows itself.
if (wasVisible && d->platformWindow)
setVisible(true);
}
}
/*!
\fn QWindow::screenChanged(QScreen *screen)

View File

@ -314,9 +314,6 @@ Q_SIGNALS:
Q_REVISION(1) void opacityChanged(qreal opacity);
private Q_SLOTS:
void screenDestroyed(QObject *screen);
protected:
virtual void exposeEvent(QExposeEvent *);
virtual void resizeEvent(QResizeEvent *);