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 <lars.knoll@qt.io>
This commit is contained in:
Tor Arne Vestbø 2017-01-31 13:34:41 +01:00
parent a57f2128b1
commit 0c6911e5cd
2 changed files with 35 additions and 21 deletions

View File

@ -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<QWindow*>(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();
}
/*!

View File

@ -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();