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>
This commit is contained in:
parent
9f983eac9f
commit
989d439d93
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user