https://invent.kde.org/plasma/plasma-workspace/-/commit/0a01c8910309fb9f289fe0aa58492e106d154548

From 0a01c8910309fb9f289fe0aa58492e106d154548 Mon Sep 17 00:00:00 2001
From: Marco Martin <notmart@gmail.com>
Date: Sun, 25 Sep 2022 16:47:31 -0500
Subject: [PATCH] Introduce a lock that blocks relayouts and config writes

The resize of the layout area can happen either by screen resolution
change or available screen area change (a panel appears or is resized)
This is not an atomic operation, as width and height are usually set in
2 different operations, and even worse the layout area is resized to
  match the available one with an animation, so many intermediate resizes
that should never cause a relayout happen.
In normal operation an event compression timer limits the actual
relayouts to hopefully one, but if the system is really slowed down
(for instance, startup) the timer may expire and cause relayouts in
non useful sizes, losing the needed configuration
In combination with

The lock blocks all relayout and config writes when the size of the
layout area doesn't correspond to corona availablescreenrect, which are
the only "settled" cases.

BUG:413645
--- a/components/containmentlayoutmanager/appletslayout.cpp
+++ b/components/containmentlayoutmanager/appletslayout.cpp
@@ -56,9 +56,10 @@ AppletsLayout::AppletsLayout(QQuickItem *parent)
     connect(m_layoutChangeTimer, &QTimer::timeout, this, [this]() {
         // We can't assume m_containment to be valid: if we load in a plasmoid that can run also
         // in "applet" mode, m_containment will never be valid
-        if (!m_containment) {
+        if (!m_containment || width() <= 0 || height() <= 0 || m_relayoutLock) {
             return;
         }
+
         const QString &serializedConfig = m_containment->config().readEntry(m_configKey, "");
         if ((m_layoutChanges & ConfigKeyChange) && !serializedConfig.isEmpty()) {
             if (!m_configKey.isEmpty() && m_containment) {
@@ -169,6 +170,27 @@ void AppletsLayout::setFallbackConfigKey(const QString &key)
     Q_EMIT fallbackConfigKeyChanged();
 }
 
+bool AppletsLayout::relayoutLock() const
+{
+    return m_relayoutLock;
+}
+
+void AppletsLayout::setRelayoutLock(bool lock)
+{
+    if (lock == m_relayoutLock) {
+        return;
+    }
+
+    m_relayoutLock = lock;
+
+    if (!lock && m_layoutChanges != NoChange) {
+        m_layoutChangeTimer->start();
+    }
+
+    Q_EMIT relayoutLockChanged();
+}
+
+
 QJSValue AppletsLayout::acceptsAppletCallback() const
 {
     return m_acceptsAppletCallback;
@@ -468,7 +490,7 @@ void AppletsLayout::geometryChanged(const QRectF &newGeometry, const QRectF &old
     }
 
     // Only do a layouting procedure if we received a valid size
-    if (!newGeometry.isEmpty()) {
+    if (!newGeometry.isEmpty() && newGeometry != oldGeometry) {
         m_layoutChanges |= SizeChange;
         m_layoutChangeTimer->start();
     }
--- a/components/containmentlayoutmanager/appletslayout.h
+++ b/components/containmentlayoutmanager/appletslayout.h
@@ -39,6 +39,8 @@ class AppletsLayout : public QQuickItem
     // from the screen size and plasma starts on an "unexpected" size
     Q_PROPERTY(QString fallbackConfigKey READ fallbackConfigKey WRITE setFallbackConfigKey NOTIFY fallbackConfigKeyChanged)
 
+    Q_PROPERTY(bool relayoutLock READ relayoutLock WRITE setRelayoutLock NOTIFY relayoutLockChanged)
+
     Q_PROPERTY(PlasmaQuick::AppletQuickItem *containment READ containment WRITE setContainment NOTIFY containmentChanged)
 
     Q_PROPERTY(QJSValue acceptsAppletCallback READ acceptsAppletCallback WRITE setAcceptsAppletCallback NOTIFY acceptsAppletCallbackChanged)
@@ -103,6 +105,9 @@ public:
     QString fallbackConfigKey() const;
     void setFallbackConfigKey(const QString &key);
 
+    bool relayoutLock() const;
+    void setRelayoutLock(bool lock);
+
     PlasmaQuick::AppletQuickItem *containment() const;
     void setContainment(PlasmaQuick::AppletQuickItem *containment);
 
@@ -162,6 +167,7 @@ Q_SIGNALS:
 
     void configKeyChanged();
     void fallbackConfigKeyChanged();
+    void relayoutLockChanged();
     void containmentChanged();
     void minimumItemWidthChanged();
     void minimumItemHeightChanged();
@@ -226,6 +232,7 @@ private:
     QPointF m_mouseDownPosition = QPoint(-1, -1);
     bool m_mouseDownWasEditMode = false;
     bool m_editMode = false;
+    bool m_relayoutLock = false;
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(AppletsLayout::LayoutChanges)
GitLab
