From 0c6911e5cde24c45d6f2c08b6e71064bdd1eccfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 31 Jan 2017 13:34:41 +0100 Subject: [PATCH] QWindow: don't destroy foreign windows Calling QWindow::destroy() is documented to "release the native platform resources associated with this window.", but in the case of foreign windows we do not control the native platform resource, so we shouldn't destroy the platform window until the QWindow is destroyed. This also allows code paths to defer to the platform window to answer questions like winId() instead of having to duplicate the ID on the QWindow side in _q_foreignWinId. Change-Id: Ie00ee570bdddde958d97d49edcba2bc1bf519a99 Reviewed-by: Lars Knoll --- src/gui/kernel/qwindow.cpp | 55 +++++++++++++++++++++++--------------- src/gui/kernel/qwindow_p.h | 1 + 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 1491cff9975..47277abea30 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -208,7 +208,8 @@ QWindow::QWindow(QWindowPrivate &dd, QWindow *parent) */ QWindow::~QWindow() { - destroy(); + Q_D(QWindow); + d->destroy(); QGuiApplicationPrivate::window_list.removeAll(this); if (!QGuiApplicationPrivate::is_app_closing) QGuiApplicationPrivate::instance()->modalWindowList.removeOne(this); @@ -1762,42 +1763,54 @@ void QWindow::destroy() if (!d->platformWindow) return; - QObjectList childrenWindows = children(); + if (d->platformWindow->isForeignWindow()) + return; + + d->destroy(); +} + +void QWindowPrivate::destroy() +{ + if (!platformWindow) + return; + + Q_Q(QWindow); + QObjectList childrenWindows = q->children(); for (int i = 0; i < childrenWindows.size(); i++) { QObject *object = childrenWindows.at(i); if (object->isWindowType()) { QWindow *w = static_cast(object); - w->destroy(); + qt_window_private(w)->destroy(); } } - if (QGuiApplicationPrivate::focus_window == this) - QGuiApplicationPrivate::focus_window = parent(); - if (QGuiApplicationPrivate::currentMouseWindow == this) - QGuiApplicationPrivate::currentMouseWindow = parent(); - if (QGuiApplicationPrivate::currentMousePressWindow == this) - QGuiApplicationPrivate::currentMousePressWindow = parent(); + if (QGuiApplicationPrivate::focus_window == q) + QGuiApplicationPrivate::focus_window = q->parent(); + if (QGuiApplicationPrivate::currentMouseWindow == q) + QGuiApplicationPrivate::currentMouseWindow = q->parent(); + if (QGuiApplicationPrivate::currentMousePressWindow == q) + QGuiApplicationPrivate::currentMousePressWindow = q->parent(); for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i) - if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == this) - QGuiApplicationPrivate::tabletDevicePoints[i].target = parent(); + if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == q) + QGuiApplicationPrivate::tabletDevicePoints[i].target = q->parent(); - bool wasVisible = isVisible(); - d->visibilityOnDestroy = wasVisible && d->platformWindow; + bool wasVisible = q->isVisible(); + visibilityOnDestroy = wasVisible && platformWindow; - setVisible(false); + q->setVisible(false); QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed); - QGuiApplication::sendEvent(this, &e); + QGuiApplication::sendEvent(q, &e); - delete d->platformWindow; - d->resizeEventPending = true; - d->receivedExpose = false; - d->exposed = false; - d->platformWindow = 0; + delete platformWindow; + resizeEventPending = true; + receivedExpose = false; + exposed = false; + platformWindow = 0; if (wasVisible) - d->maybeQuitOnLastWindowClosed(); + maybeQuitOnLastWindowClosed(); } /*! diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index 95c6abf4287..d1727a1c577 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -137,6 +137,7 @@ public: bool windowRecreationRequired(QScreen *newScreen) const; void create(bool recursive); + void destroy(); void setTopLevelScreen(QScreen *newScreen, bool recreate); void connectToScreen(QScreen *topLevelScreen); void disconnectFromScreen();