From f3e6d3ca196aaef28478c27fd6a3caaed3cdbdff Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 22 Nov 2023 15:05:52 +0200 Subject: [PATCH] Ignore decoration changes of closed windows Ideally the decoration of a closed window should not change. However, it seems like it can happen when resuming the session. When switching to another VT, the touchpad input device is removed, but the touch input device is still kept on my machine. This results in the tablet mode changing temporarily and triggering recalculation of new borders in breeze decoration. It's a no-no thing to do if the window is closed. We need to guard against this case. But in long term, we need to reroute all decoration state updates through kwin so it can block state updates when the window is closed. It's also needed for double buffered state. How to improve handling of tablet mode detection when switching between VTs needs a separate investigation. CCBUG: 477166 --- src/window.cpp | 30 +++++++++++++++++++++++------- src/x11window.cpp | 18 +++++++++++++++--- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index d60ff3db32..be9ca43b2f 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -2625,20 +2625,32 @@ void Window::setDecoration(std::shared_ptr decoration) } if (decoration) { QMetaObject::invokeMethod(decoration.get(), QOverload<>::of(&KDecoration2::Decoration::update), Qt::QueuedConnection); - connect(decoration.get(), &KDecoration2::Decoration::shadowChanged, this, &Window::updateShadow); - connect(decoration.get(), &KDecoration2::Decoration::bordersChanged, - this, &Window::updateDecorationInputShape); - connect(decoration.get(), &KDecoration2::Decoration::resizeOnlyBordersChanged, - this, &Window::updateDecorationInputShape); + connect(decoration.get(), &KDecoration2::Decoration::shadowChanged, this, [this]() { + if (!isDeleted()) { + updateShadow(); + } + }); connect(decoration.get(), &KDecoration2::Decoration::bordersChanged, this, [this]() { + if (isDeleted()) { + return; + } GeometryUpdatesBlocker blocker(this); const QRectF oldGeometry = moveResizeGeometry(); if (!isShade()) { checkWorkspacePosition(oldGeometry); } + updateDecorationInputShape(); + }); + connect(decoration.get(), &KDecoration2::Decoration::resizeOnlyBordersChanged, this, [this]() { + if (!isDeleted()) { + updateDecorationInputShape(); + } + }); + connect(decoratedClient()->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged, this, [this]() { + if (!isDeleted()) { + updateDecorationInputShape(); + } }); - connect(decoratedClient()->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged, - this, &Window::updateDecorationInputShape); } m_decoration.decoration = decoration; updateDecorationInputShape(); @@ -3658,6 +3670,10 @@ void Window::sendToOutput(Output *newOutput) void Window::checkWorkspacePosition(QRectF oldGeometry, const VirtualDesktop *oldDesktop) { + if (isDeleted()) { + qCWarning(KWIN_CORE) << "Window::checkWorkspacePosition: called for a closed window. Consider this a bug"; + return; + } if (isDock() || isDesktop() || !isPlaceable()) { return; } diff --git a/src/x11window.cpp b/src/x11window.cpp index 724f49e096..8b2fce35f4 100644 --- a/src/x11window.cpp +++ b/src/x11window.cpp @@ -1340,9 +1340,21 @@ void X11Window::createDecoration() { std::shared_ptr decoration(Workspace::self()->decorationBridge()->createDecoration(this)); if (decoration) { - connect(decoration.get(), &KDecoration2::Decoration::resizeOnlyBordersChanged, this, &X11Window::updateInputWindow); - connect(decoration.get(), &KDecoration2::Decoration::bordersChanged, this, &X11Window::updateFrameExtents); - connect(decoratedClient()->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged, this, &X11Window::updateInputWindow); + connect(decoration.get(), &KDecoration2::Decoration::resizeOnlyBordersChanged, this, [this]() { + if (!isDeleted()) { + updateInputWindow(); + } + }); + connect(decoration.get(), &KDecoration2::Decoration::bordersChanged, this, [this]() { + if (!isDeleted()) { + updateFrameExtents(); + } + }); + connect(decoratedClient()->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged, this, [this]() { + if (!isDeleted()) { + updateInputWindow(); + } + }); } setDecoration(decoration);