diff options
author | Shawn Rutledge <shawn.rutledge@digia.com> | 2015-02-03 13:05:20 +0100 |
---|---|---|
committer | Daniel Molkentin <daniel@molkentin.de> | 2015-02-07 16:19:59 +0000 |
commit | f4b8697c40bd476ef6bf83418e144adce7c7d4a3 (patch) | |
tree | d5f7c03b627a459c5a6461ded2abc6d102c115ee /src/gui | |
parent | 45b60c01efc735ce9910d7724ee300855194ff33 (diff) |
Handle gracefully the removal and re-attachment of all QScreens
Don't crash; restore windows when all screens are removed and re-added.
xcb: on configure notify, check for screen change: it may be that a
window belonging to a screen which was removed has now gotten mapped
to the new screen. On screen change, send a synthetic expose event,
because the real expose events already happened.
Task-number: QTBUG-38326
Task-number: QTBUG-32973
Task-number: QTBUG-42985
Change-Id: If334f55c248468ad3c95e7066bb14eca377d2050
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qplatformwindow.cpp | 5 | ||||
-rw-r--r-- | src/gui/kernel/qscreen.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 14 | ||||
-rw-r--r-- | src/gui/kernel/qwindow_p.h | 5 |
5 files changed, 20 insertions, 10 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index d44a79b37e..92be903b41 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2583,6 +2583,8 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E return; QWindow *window = e->exposed.data(); + if (!window) + return; QWindowPrivate *p = qt_window_private(window); if (!p->receivedExpose) { @@ -2598,7 +2600,7 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E p->receivedExpose = true; } - p->exposed = e->isExposed; + p->exposed = e->isExposed && window->screen(); QExposeEvent exposeEvent(e->region); QCoreApplication::sendSpontaneousEvent(window, &exposeEvent); diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 167bd44f0e..763ab68868 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -83,7 +83,8 @@ QPlatformWindow *QPlatformWindow::parent() const */ QPlatformScreen *QPlatformWindow::screen() const { - return window()->screen()->handle(); + QScreen *scr = window()->screen(); + return scr ? scr->handle() : Q_NULLPTR; } /*! @@ -479,7 +480,7 @@ QString QPlatformWindow::formatWindowTitle(const QString &title, const QString & QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) const { QPlatformScreen *currentScreen = screen(); - if (!parent() && !currentScreen->geometry().intersects(newGeometry)) { + if (!parent() && currentScreen && !currentScreen->geometry().intersects(newGeometry)) { Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) { if (screen->geometry().intersects(newGeometry)) return screen; diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 8357e14354..0cc8f1082a 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -86,7 +86,7 @@ QScreen::~QScreen() if (this == primaryScreen) return; - bool movingFromVirtualSibling = primaryScreen->handle()->virtualSiblings().contains(handle()); + bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle()); // Move any leftover windows to the primary screen foreach (QWindow *window, QGuiApplication::topLevelWindows()) { diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index b679dd9bfc..773cce7a7f 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -338,7 +338,7 @@ inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const { Q_Q(const QWindow); const QScreen *oldScreen = q->screen(); - return oldScreen != newScreen && platformWindow + return oldScreen != newScreen && (platformWindow || !oldScreen) && !(oldScreen && oldScreen->virtualSiblings().contains(newScreen)); } @@ -373,10 +373,13 @@ void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate) } if (newScreen != topLevelScreen) { const bool shouldRecreate = recreate && windowRecreationRequired(newScreen); - if (shouldRecreate) + const bool shouldShow = visibilityOnDestroy && !topLevelScreen; + if (shouldRecreate && platformWindow) q->destroy(); connectToScreen(newScreen); - if (newScreen && shouldRecreate) + if (shouldShow) + q->setVisible(true); + else if (newScreen && shouldRecreate) create(true); emitScreenChangedRecursion(newScreen); } @@ -1600,6 +1603,7 @@ void QWindow::destroy() QGuiApplicationPrivate::tabletPressTarget = parent(); bool wasVisible = isVisible(); + d->visibilityOnDestroy = wasVisible && d->platformWindow; setVisible(false); @@ -1683,7 +1687,7 @@ bool QWindow::setMouseGrabEnabled(bool grab) QScreen *QWindow::screen() const { Q_D(const QWindow); - return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen; + return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen.data(); } /*! @@ -1703,7 +1707,7 @@ void QWindow::setScreen(QScreen *newScreen) Q_D(QWindow); if (!newScreen) newScreen = QGuiApplication::primaryScreen(); - d->setTopLevelScreen(newScreen, true /* recreate */); + d->setTopLevelScreen(newScreen, newScreen != 0); } /*! diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index c496d7716b..9151e76ea4 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -45,6 +45,7 @@ // We mean it. // +#include <QtGui/qscreen.h> #include <QtGui/qwindow.h> #include <qpa/qplatformwindow.h> @@ -73,6 +74,7 @@ public: , parentWindow(0) , platformWindow(0) , visible(false) + , visibilityOnDestroy(false) , exposed(false) , windowState(Qt::WindowNoState) , visibility(QWindow::Hidden) @@ -147,6 +149,7 @@ public: QWindow *parentWindow; QPlatformWindow *platformWindow; bool visible; + bool visibilityOnDestroy; bool exposed; QSurfaceFormat requestedFormat; QString windowTitle; @@ -175,7 +178,7 @@ public: int updateTimer; QPointer<QWindow> transientParent; - QScreen *topLevelScreen; + QPointer<QScreen> topLevelScreen; #ifndef QT_NO_CURSOR QCursor cursor; |