diff options
author | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-02-20 16:59:54 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-24 17:10:33 +0100 |
commit | 989d439d93341fc8f046a5a6cefe6ed39625b908 (patch) | |
tree | 22ae71728eb23be237e933c14aff11f6681cc437 /src/plugins | |
parent | 9f983eac9f926b4ea3ee4ec860f58dc33a5b7fe7 (diff) |
Windows: Clear transient relationship before destroying windows.
Windows differs from the other platforms in that transient
parent relationship is not just a window property but also
implies ownership; windows will destroy their transient
children in DestroyWindow(), which interferes with Qt.
Explicitly clear the relationship in QWindowsWindow::destroy()
to prevent this.
Task-number: QTBUG-36666
Task-number: QTBUG-35499
Change-Id: I5e72524ef57422831f60484993f6c8d7c80c8601
Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.cpp | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 39b36a29cb..d77f587b92 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -924,11 +924,23 @@ void QWindowsWindow::fireExpose(const QRegion ®ion, bool force) QWindowSystemInterface::handleExposeEvent(window(), region); } +static inline QWindow *findTransientChild(const QWindow *parent) +{ + foreach (QWindow *w, QGuiApplication::topLevelWindows()) + if (w->transientParent() == parent) + return w; + return 0; +} + void QWindowsWindow::destroyWindow() { qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << m_data.hwnd; if (m_data.hwnd) { // Stop event dispatching before Window is destroyed. setFlag(WithinDestroy); + // Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666) + if (QWindow *transientChild = findTransientChild(window())) + if (QWindowsWindow *tw = QWindowsWindow::baseWindowOf(transientChild)) + tw->updateTransientParent(); QWindowsContext *context = QWindowsContext::instance(); if (context->windowUnderMouse() == window()) context->clearWindowUnderMouse(); @@ -1102,6 +1114,18 @@ QPoint QWindowsWindow::mapFromGlobal(const QPoint &pos) const return pos; } +#ifndef Q_OS_WINCE +static inline HWND transientParentHwnd(HWND hwnd) +{ + if (GetAncestor(hwnd, GA_PARENT) == GetDesktopWindow()) { + const HWND rootOwnerHwnd = GetAncestor(hwnd, GA_ROOTOWNER); + if (rootOwnerHwnd != hwnd) // May return itself for toplevels. + return rootOwnerHwnd; + } + return 0; +} +#endif // !Q_OS_WINCE + // Update the transient parent for a toplevel window. The concept does not // really exist on Windows, the relationship is set by passing a parent along with !WS_CHILD // to window creation or by setting the parent using GWL_HWNDPARENT (as opposed to @@ -1112,12 +1136,13 @@ void QWindowsWindow::updateTransientParent() const if (window()->type() == Qt::Popup) return; // QTBUG-34503, // a popup stays on top, no parent, see also WindowCreationData::fromWindow(). // Update transient parent. - const HWND oldTransientParent = - GetAncestor(m_data.hwnd, GA_PARENT) == GetDesktopWindow() ? GetAncestor(m_data.hwnd, GA_ROOTOWNER) : HWND(0); + const HWND oldTransientParent = transientParentHwnd(m_data.hwnd); HWND newTransientParent = 0; if (const QWindow *tp = window()->transientParent()) - newTransientParent = QWindowsWindow::handleOf(tp); - if (newTransientParent && newTransientParent != oldTransientParent) + if (const QWindowsWindow *tw = QWindowsWindow::baseWindowOf(tp)) + if (!tw->testFlag(WithinDestroy)) // Prevent destruction by parent window (QTBUG-35499, QTBUG-36666) + newTransientParent = tw->handle(); + if (newTransientParent != oldTransientParent) SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, (LONG_PTR)newTransientParent); #endif // !Q_OS_WINCE } |