Delay syncing internal window geometry to end of cycle
Summary: The syncing of the window geometry to the internal geometry can unfortunately cause a freeze in very special conditions: 1. create QML component 2. a Plasma::Dialog gets created 3. It creates the DialogShadows 4. This triggers QGlobalStatic creation which locks a non-recursive mutex 5. The creation of DialogShadows creates a Registry and triggers a roundtrip on the Wayland server 6. KWin processes all Wayland events 7. This triggers the creation of a ShellClient 8. The ShellClient has a PlasmaShellSurface which requested a position 9. The new geometry does not match the geometry of the Plasma::Dialog 10. ShellClient syncs the geometry to the Plasma::Dialog 11. Plasma::Dialog updates the theme because window geometry changed 12. This accesses the DialogShadows... which is still in the non recursive mutex and we have a freeze. By delaying the sync to the end of cycle we jump out of this deadly sequence. BUG: 384441 Test Plan: The freeze doesn't hit any more. It's possible that some test cases need adjustments. Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D7712
This commit is contained in:
parent
d1e0c6f9d7
commit
e0f95fd913
2 changed files with 5 additions and 4 deletions
|
@ -538,11 +538,11 @@ void InternalWindowTest::testMove()
|
||||||
// normal move should be synced
|
// normal move should be synced
|
||||||
internalClient->move(5, 10);
|
internalClient->move(5, 10);
|
||||||
QCOMPARE(internalClient->geometry(), QRect(5, 10, 100, 100));
|
QCOMPARE(internalClient->geometry(), QRect(5, 10, 100, 100));
|
||||||
QCOMPARE(win.geometry(), QRect(5, 10, 100, 100));
|
QTRY_COMPARE(win.geometry(), QRect(5, 10, 100, 100));
|
||||||
// another move should also be synced
|
// another move should also be synced
|
||||||
internalClient->move(10, 20);
|
internalClient->move(10, 20);
|
||||||
QCOMPARE(internalClient->geometry(), QRect(10, 20, 100, 100));
|
QCOMPARE(internalClient->geometry(), QRect(10, 20, 100, 100));
|
||||||
QCOMPARE(win.geometry(), QRect(10, 20, 100, 100));
|
QTRY_COMPARE(win.geometry(), QRect(10, 20, 100, 100));
|
||||||
|
|
||||||
// now move with a Geometry update blocker
|
// now move with a Geometry update blocker
|
||||||
{
|
{
|
||||||
|
@ -552,7 +552,7 @@ void InternalWindowTest::testMove()
|
||||||
QCOMPARE(win.geometry(), QRect(10, 20, 100, 100));
|
QCOMPARE(win.geometry(), QRect(10, 20, 100, 100));
|
||||||
}
|
}
|
||||||
// after destroying the blocker it should be synced
|
// after destroying the blocker it should be synced
|
||||||
QCOMPARE(win.geometry(), QRect(5, 10, 100, 100));
|
QTRY_COMPARE(win.geometry(), QRect(5, 10, 100, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InternalWindowTest::testSkipCloseAnimation_data()
|
void InternalWindowTest::testSkipCloseAnimation_data()
|
||||||
|
|
|
@ -543,7 +543,8 @@ void ShellClient::syncGeometryToInternalWindow()
|
||||||
const QRect windowRect = QRect(geom.topLeft() + QPoint(borderLeft(), borderTop()),
|
const QRect windowRect = QRect(geom.topLeft() + QPoint(borderLeft(), borderTop()),
|
||||||
geom.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
|
geom.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
|
||||||
if (m_internalWindow->geometry() != windowRect) {
|
if (m_internalWindow->geometry() != windowRect) {
|
||||||
m_internalWindow->setGeometry(windowRect);
|
// delay to end of cycle to prevent freeze, see BUG 384441
|
||||||
|
QTimer::singleShot(0, m_internalWindow, std::bind(static_cast<void (QWindow::*)(const QRect&)>(&QWindow::setGeometry), m_internalWindow, windowRect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue