Skip to content

Commit

Permalink
Revert "MAYA-132611: Crash when docking the Select a light source (qt…
Browse files Browse the repository at this point in the history
…#102)" (qt#105)

#28746 was made to use an older artifact for Maya 2025.2 to save precious hours that would have been otherwise spent on waiting for the Qt build to complete. This PR aims to solve it properly by reverting the offending change specifically. This also allows us to resolve MAYA-132068

This reverts commit aaca5d7.
  • Loading branch information
senthilauto2023 authored and GitHub Enterprise committed Jul 24, 2024
1 parent f2b8467 commit 886d1f5
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 293 deletions.
148 changes: 39 additions & 109 deletions src/widgets/kernel/qwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ using namespace QNativeInterface::Private;
using namespace Qt::StringLiterals;

Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
Q_LOGGING_CATEGORY(lcWidgetWindow, "qt.widgets.window", QtWarningMsg);

static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
{
Expand Down Expand Up @@ -1027,23 +1026,6 @@ void QWidgetPrivate::createRecursively()
}
}

/*!
\internal
Returns the closest parent widget that has a QWindow window handle
\note This behavior is different from nativeParentWidget(), which
returns the closest parent that has a QWindow window handle with
a created QPlatformWindow, and hence native window (winId).
*/
QWidget *QWidgetPrivate::closestParentWidgetWithWindowHandle() const
{
Q_Q(const QWidget);
QWidget *parent = q->parentWidget();
while (parent && !parent->windowHandle())
parent = parent->parentWidget();
return parent;
}

QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
{
if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
Expand All @@ -1053,7 +1035,6 @@ QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
}
}
if (mode == WindowHandleMode::Closest) {
// FIXME: Use closestParentWidgetWithWindowHandle instead
if (auto nativeParent = q_func()->nativeParentWidget()) {
if (auto window = nativeParent->windowHandle())
return window;
Expand Down Expand Up @@ -10880,61 +10861,57 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)

setWinId(0);

if (parent != newparent) {
QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
if (q->windowHandle()) {
q->windowHandle()->setFlags(f);
QWidget *parentWithWindow =
newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : nullptr;
if (parentWithWindow) {
QWidget *topLevel = parentWithWindow->window();
if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) {
q->windowHandle()->setTransientParent(topLevel->windowHandle());
q->windowHandle()->setParent(nullptr);
} else {
q->windowHandle()->setTransientParent(nullptr);
q->windowHandle()->setParent(parentWithWindow->windowHandle());
}
} else {
q->windowHandle()->setTransientParent(nullptr);
q->windowHandle()->setParent(nullptr);
}
}
}

if (!newparent) {
f |= Qt::Window;
if (parent)
targetScreen = q->parentWidget()->window()->screen();
}

const bool destroyWindow = (
// Reparenting top level to child
(oldFlags & Qt::Window) && !(f & Qt::Window)
// And we can dispose of the window
&& wasCreated && !q->testAttribute(Qt::WA_NativeWindow)
);

if (parent != newparent) {
// Update object parent now, so we can resolve new parent window below
QObjectPrivate::setParent_helper(newparent);

if (q->windowHandle())
q->windowHandle()->setFlags(f);

// If the widget itself or any of its children have been created,
// we need to reparent their QWindows as well.
QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
// But if the widget is about to be destroyed we must skip the
// widget itself, and only reparent children.
if (destroyWindow)
reparentWidgetWindowChildren(parentWithWindow);
else
reparentWidgetWindows(parentWithWindow, f);
}

bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);

if (destroyWindow) {
// Reparenting toplevel to child
if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
if (extra && extra->hasWindowContainer)
QWindowContainer::toplevelAboutToBeDestroyed(q);

// There shouldn't be any QWindow children left, but if there
// are, re-parent them now, before we destroy.
if (!q->windowHandle()->children().isEmpty()) {
QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
for (QObject *child : q->windowHandle()->children()) {
if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
<< "before destroying" << this;
childWindow->setParent(newParentWindow);
}
}
}
QWindow *newParentWindow = newparent->windowHandle();
if (!newParentWindow)
if (QWidget *npw = newparent->nativeParentWidget())
newParentWindow = npw->windowHandle();

// We have reparented any child windows of the widget we are
// about to destroy to the new parent window handle, so we can
// safely destroy this widget without destroying sub windows.
q->destroy(true, false);
for (QObject *child : q->windowHandle()->children()) {
QWindow *childWindow = qobject_cast<QWindow *>(child);
if (!childWindow)
continue;

QWidgetWindow *childWW = qobject_cast<QWidgetWindow *>(childWindow);
QWidget *childWidget = childWW ? childWW->widget() : nullptr;
if (!childWW || (childWidget && childWidget->testAttribute(Qt::WA_NativeWindow)))
childWindow->setParent(newParentWindow);
}
q->destroy();
}

adjustFlags(f, q);
Expand All @@ -10960,53 +10937,6 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
}
}

void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
{
if (QWindow *window = windowHandle()) {
// Reparent this QWindow, and all QWindow children will follow
if (parentWithWindow) {
// The reparented widget has not updated its window flags yet,
// so we can't ask the widget directly. And we can't use the
// QWindow flags, as unlike QWidgets the QWindow flags always
// reflect Qt::Window, even for child windows. And we can't use
// QWindow::isTopLevel() either, as that depends on the parent,
// which we are in the process of updating. So we propagate the
// new flags of the reparented window from setParent_sys().
if (windowFlags & Qt::Window) {
// Top level windows can only have transient parents,
// and the transient parent must be another top level.
QWidget *topLevel = parentWithWindow->window();
auto *transientParent = topLevel->windowHandle();
Q_ASSERT(transientParent);
qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
window->setTransientParent(transientParent);
window->setParent(nullptr);
} else {
auto *parentWindow = parentWithWindow->windowHandle();
qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
window->setTransientParent(nullptr);
window->setParent(parentWindow);
}
} else {
qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
window->setTransientParent(nullptr);
window->setParent(nullptr);
}
} else {
reparentWidgetWindowChildren(parentWithWindow);
}
}

void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
{
for (auto *child : std::as_const(children)) {
if (auto *childWidget = qobject_cast<QWidget*>(child)) {
auto *childPrivate = QWidgetPrivate::get(childWidget);
childPrivate->reparentWidgetWindows(parentWithWindow);
}
}
}

/*!
Scrolls the widget including its children \a dx pixels to the
right and \a dy downward. Both \a dx and \a dy may be negative.
Expand Down
4 changes: 0 additions & 4 deletions src/widgets/kernel/qwidget_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,6 @@ class Q_WIDGETS_EXPORT QWidgetPrivate : public QObjectPrivate
void showChildren(bool spontaneous);
void hideChildren(bool spontaneous);
void setParent_sys(QWidget *parent, Qt::WindowFlags);
void reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags = {});
void reparentWidgetWindowChildren(QWidget *parentWithWindow);
void scroll_sys(int dx, int dy);
void scroll_sys(int dx, int dy, const QRect &r);
void deactivateWidgetCleanup();
Expand Down Expand Up @@ -635,8 +633,6 @@ class Q_WIDGETS_EXPORT QWidgetPrivate : public QObjectPrivate

std::string flagsForDumping() const override;

QWidget *closestParentWidgetWithWindowHandle() const;

// Variables.
// Regular pointers (keep them together to avoid gaps on 64 bit architectures).
std::unique_ptr<QWExtra> extra;
Expand Down
Loading

0 comments on commit 886d1f5

Please sign in to comment.