Do not delete window decorations before next update

When window decorations are turned on/off, a timing issue might happen
with accessing deleted decorations.
A boolean value, mWindowDecorationEnabled, will be used instead of
mWindowDecoration.

Pick-to: 6.3 6.2
Fixes: QTBUG-59627
Change-Id: I5514a408d89340fdbf481721ea2dc4bf62078852
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
Inho Lee 2021-09-20 20:00:49 +02:00
parent 699770b7c7
commit 0bbff7ff60
2 changed files with 24 additions and 18 deletions

View File

@ -327,7 +327,7 @@ void QWaylandWindow::setWindowTitle(const QString &title)
mShellSurface->setTitle(truncated.toString());
}
if (mWindowDecoration && window()->isVisible())
if (mWindowDecorationEnabled && window()->isVisible())
mWindowDecoration->update();
}
@ -335,7 +335,7 @@ void QWaylandWindow::setWindowIcon(const QIcon &icon)
{
mWindowIcon = icon;
if (mWindowDecoration && window()->isVisible())
if (mWindowDecorationEnabled && window()->isVisible())
mWindowDecoration->update();
}
@ -369,7 +369,7 @@ void QWaylandWindow::setGeometry(const QRect &rect)
setGeometry_helper(rect);
if (window()->isVisible() && rect.isValid()) {
if (mWindowDecoration)
if (mWindowDecorationEnabled)
mWindowDecoration->update();
if (mResizeAfterSwap && windowType() == Egl && mSentInitialResize)
@ -429,7 +429,7 @@ void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, cons
// 2) Following resizeFromApplyConfigure() calls should have sizeWithMargins equal to
// windowContentGeometry() which excludes shadows, therefore in this case we have to
// exclude them too in order not to accidentally apply smaller size to the window.
if (mWindowDecoration && (sizeWithMargins != surfaceSize()))
if (mWindowDecorationEnabled && (sizeWithMargins != surfaceSize()))
margins = mWindowDecoration->margins(QWaylandAbstractDecoration::ShadowsExcluded);
int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1);
@ -751,7 +751,7 @@ bool QWaylandWindow::waitForFrameSync(int timeout)
QMargins QWaylandWindow::frameMargins() const
{
if (mWindowDecoration)
if (mWindowDecorationEnabled)
return mWindowDecoration->margins();
else if (mShellSurface)
return mShellSurface->serverSideFrameMargins();
@ -761,7 +761,7 @@ QMargins QWaylandWindow::frameMargins() const
QMargins QWaylandWindow::clientSideMargins() const
{
return mWindowDecoration ? mWindowDecoration->margins() : QMargins{};
return mWindowDecorationEnabled ? mWindowDecoration->margins() : QMargins{};
}
/*!
@ -780,7 +780,7 @@ QRect QWaylandWindow::windowContentGeometry() const
{
QMargins shadowMargins;
if (mWindowDecoration)
if (mWindowDecorationEnabled)
shadowMargins = mWindowDecoration->margins(QWaylandAbstractDecoration::ShadowsOnly);
return QRect(QPoint(shadowMargins.left(), shadowMargins.top()), surfaceSize().shrunkBy(shadowMargins));
@ -904,9 +904,14 @@ bool QWaylandWindow::createDecoration()
if (!mShellSurface || !mShellSurface->wantsDecorations())
decoration = false;
bool hadDecoration = mWindowDecoration;
bool hadDecoration = mWindowDecorationEnabled;
if (decoration && !decorationPluginFailed) {
if (!mWindowDecoration) {
if (!mWindowDecorationEnabled) {
if (mWindowDecoration) {
delete mWindowDecoration;
mWindowDecoration = nullptr;
}
QStringList decorations = QWaylandDecorationFactory::keys();
if (decorations.empty()) {
qWarning() << "No decoration plugins available. Running with no decorations.";
@ -935,13 +940,13 @@ bool QWaylandWindow::createDecoration()
return false;
}
mWindowDecoration->setWaylandWindow(this);
mWindowDecorationEnabled = true;
}
} else {
delete mWindowDecoration;
mWindowDecoration = nullptr;
mWindowDecorationEnabled = false;
}
if (hadDecoration != (bool)mWindowDecoration) {
if (hadDecoration != mWindowDecorationEnabled) {
for (QWaylandSubSurface *subsurf : qAsConst(mChildren)) {
QPoint pos = subsurf->window()->geometry().topLeft();
QMargins m = frameMargins();
@ -962,7 +967,7 @@ bool QWaylandWindow::createDecoration()
QWaylandAbstractDecoration *QWaylandWindow::decoration() const
{
return mWindowDecoration;
return mWindowDecorationEnabled ? mWindowDecoration : nullptr;
}
static QWaylandWindow *closestShellSurfaceWindow(QWindow *window)
@ -993,7 +998,7 @@ QWaylandWindow *QWaylandWindow::transientParent() const
void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
{
if (e.type == QEvent::Leave) {
if (mWindowDecoration) {
if (mWindowDecorationEnabled) {
if (mMouseEventsInContentArea)
QWindowSystemInterface::handleLeaveEvent(window());
} else {
@ -1005,7 +1010,7 @@ void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylan
return;
}
if (mWindowDecoration) {
if (mWindowDecorationEnabled) {
handleMouseEventWithDecoration(inputDevice, e);
} else {
switch (e.type) {
@ -1045,7 +1050,7 @@ void QWaylandWindow::handleSwipeGesture(QWaylandInputDevice *inputDevice,
if (mGestureState != GestureNotActive)
qCWarning(lcQpaWaylandInput) << "Unexpected GestureStarted while already active";
if (mWindowDecoration && !mMouseEventsInContentArea) {
if (mWindowDecorationEnabled && !mMouseEventsInContentArea) {
// whole gesture sequence will be ignored
mGestureState = GestureActiveInDecoration;
return;
@ -1100,7 +1105,7 @@ void QWaylandWindow::handlePinchGesture(QWaylandInputDevice *inputDevice,
if (mGestureState != GestureNotActive)
qCWarning(lcQpaWaylandInput) << "Unexpected GestureStarted while already active";
if (mWindowDecoration && !mMouseEventsInContentArea) {
if (mWindowDecorationEnabled && !mMouseEventsInContentArea) {
// whole gesture sequence will be ignored
mGestureState = GestureActiveInDecoration;
return;
@ -1165,7 +1170,7 @@ void QWaylandWindow::handlePinchGesture(QWaylandInputDevice *inputDevice,
bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, QEventPoint::State state, Qt::KeyboardModifiers mods)
{
if (!mWindowDecoration)
if (!mWindowDecorationEnabled)
return false;
return mWindowDecoration->handleTouch(inputDevice, local, global, state, mods);
}

View File

@ -257,6 +257,7 @@ protected:
QList<QWaylandSubSurface *> mChildren;
QWaylandAbstractDecoration *mWindowDecoration = nullptr;
bool mWindowDecorationEnabled = false;
bool mMouseEventsInContentArea = false;
Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton;