File 0001-Revert-System-for-nested-containments.patch of Package libplasma6

From aa94f60c81e51424abb8c373c09d84dc0722bb55 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Kettunen?= <bjorn.kettunen@thaodan.de>
Date: Wed, 19 Nov 2025 22:32:28 +0200
Subject: [PATCH] Revert "System for nested containments"

This reverts commit 3ad38c1677df6e466d29c51594168aebb5c47c89.
---
 src/plasma/applet.cpp                | 26 +++++++-------------
 src/plasma/containment.cpp           | 36 +++++++++++++---------------
 src/plasma/private/applet_p.cpp      | 30 +++++++++++++----------
 src/plasma/private/containment_p.cpp |  6 +++++
 src/plasmaquick/appletquickitem.cpp  |  2 +-
 src/plasmaquick/configview.cpp       | 15 ++++++++----
 6 files changed, 61 insertions(+), 54 deletions(-)

diff --git a/src/plasma/applet.cpp b/src/plasma/applet.cpp
index 2ed8c9ff6..f32c2e6d8 100644
--- a/src/plasma/applet.cpp
+++ b/src/plasma/applet.cpp
@@ -714,17 +714,7 @@ Types::FormFactor Applet::formFactor() const
         return Plasma::Types::Planar;
     }
 
-    // Let's try to return the higher level formfactor in case of
-    // nested containments.
-    // c->containment() is guaranteed to exist except during teardown.
-    // if c is a toplevel containment,
-    // c == c->containment() else if is a nested one, it will be containment's
-    // containment
-    Containment *topC = c->containment();
-    if (topC) {
-        return topC->d->formFactor;
-    }
-    return c->d->formFactor;
+    return c ? c->d->formFactor : Plasma::Types::Planar;
 }
 
 Types::ContainmentDisplayHints Applet::containmentDisplayHints() const
@@ -737,7 +727,7 @@ Types::ContainmentDisplayHints Applet::containmentDisplayHints() const
 Containment *Applet::containment() const
 {
     Containment *c = qobject_cast<Containment *>(const_cast<Applet *>(this));
-    if (c && c->isContainment() && c->containmentType() != Containment::CustomEmbedded) {
+    if (c && c->isContainment()) {
         return c;
     } else {
         c = nullptr;
@@ -929,12 +919,14 @@ void Applet::timerEvent(QTimerEvent *event)
 
 bool Applet::isContainment() const
 {
-    // normal "acting as a containment" condition
-    const Containment *cont = qobject_cast<const Containment *>(this);
-    if (!cont) {
-        return false;
+    // HACK: this is a special case for the systray
+    // containment in an applet that is not a containment
+    Applet *pa = qobject_cast<Applet *>(parent());
+    if (pa && !pa->isContainment()) {
+        return true;
     }
-    return qobject_cast<Corona *>(parent()) || cont->containmentType() == Containment::CustomEmbedded;
+    // normal "acting as a containment" condition
+    return qobject_cast<const Containment *>(this) && qobject_cast<Corona *>(parent());
 }
 
 QString Applet::translationDomain() const
diff --git a/src/plasma/containment.cpp b/src/plasma/containment.cpp
index 74d2520e0..eed9bba0a 100644
--- a/src/plasma/containment.cpp
+++ b/src/plasma/containment.cpp
@@ -121,6 +121,13 @@ void Containment::init()
             setInternalAction(QStringLiteral("lock widgets"), lockDesktopAction);
         }
     }
+
+    // HACK: this is valid only in the systray case
+    connect(this, &Containment::configureRequested, this, [this](Plasma::Applet *a) {
+        if (Plasma::Applet *p = qobject_cast<Plasma::Applet *>(parent())) {
+            Q_EMIT p->containment()->configureRequested(a);
+        }
+    });
 }
 
 // helper function for sorting the list of applets
@@ -282,9 +289,12 @@ Plasma::Containment::Type Containment::containmentType() const
 
 Corona *Containment::corona() const
 {
-    // We are not sure where the corona parent is in the hierarchy,
-    // because of nested containment, those of type CustomEmbedded
-    // will have containment->containment->corona
+    // We are not sure where the corona parent is in the hyerarchy, because of... the systray.
+    // We are iterating over the parent tree here rather than casting the parent
+    // to applet then asking ofr its containment and corona, as this might break during
+    // teardown, as this can be invoked during dtor of one of the ancestors,
+    // see https://bugs.kde.org/show_bug.cgi?id=477067 where it happens during destruction
+    // of the panel (containment of the applet that contains the systray containment)
     for (auto candidate = parent(); candidate; candidate = candidate->parent()) {
         if (auto c = qobject_cast<Corona *>(candidate)) {
             return c;
@@ -368,6 +378,7 @@ void Containment::addApplet(Applet *applet, const QRectF &geometryHint)
         // qCDebug(LOG_PLASMA) << "already have this applet!";
     }
 #endif
+
     Containment *currentContainment = applet->containment();
 
     if (currentContainment && currentContainment != this) {
@@ -405,10 +416,6 @@ void Containment::addApplet(Applet *applet, const QRectF &geometryHint)
         applet->setParent(this);
     }
 
-    Containment *asCont = qobject_cast<Containment *>(applet);
-    if (asCont && asCont->containmentType() == Containment::CustomEmbedded) {
-        asCont->init();
-    }
     // make sure the applets are sorted by id
     const auto position = std::lower_bound(d->applets.begin(), d->applets.end(), applet, [](Plasma::Applet *a1, Plasma::Applet *a2) {
         return a1->id() < a2->id();
@@ -428,15 +435,11 @@ void Containment::addApplet(Applet *applet, const QRectF &geometryHint)
     if (!currentContainment) {
         const bool isNew = applet->d->mainConfigGroup()->entryMap().isEmpty();
 
-        // If the applet is a nested containment restore even if new, to
-        // have the same behavior of Corona::addContainment
-        if (!isNew || applet->isContainment()) {
+        if (!isNew) {
             applet->restore(*applet->d->mainConfigGroup());
         }
 
-        if (!asCont || asCont->containmentType() != Containment::CustomEmbedded) {
-            applet->init();
-        }
+        applet->init();
 
         if (isNew) {
             applet->save(*applet->d->mainConfigGroup());
@@ -468,9 +471,7 @@ QList<Applet *> Containment::applets() const
 int Containment::screen() const
 {
     Q_ASSERT(corona());
-    if (Containment *pc = qobject_cast<Containment *>(parent()); pc && isContainment()) {
-        return pc->screen();
-    } else if (Corona *c = corona()) {
+    if (Corona *c = corona()) {
         return c->screenForContainment(this);
     } else {
         return -1;
@@ -479,9 +480,6 @@ int Containment::screen() const
 
 int Containment::lastScreen() const
 {
-    if (Containment *pc = qobject_cast<Containment *>(parent()); pc) {
-        return pc->lastScreen();
-    }
     return d->lastScreen;
 }
 
diff --git a/src/plasma/private/applet_p.cpp b/src/plasma/private/applet_p.cpp
index 4b3c9ec97..4242b4eca 100644
--- a/src/plasma/private/applet_p.cpp
+++ b/src/plasma/private/applet_p.cpp
@@ -208,6 +208,16 @@ void AppletPrivate::setDestroyed(bool destroyed)
         for (Applet *a : lstApplets) {
             a->d->setDestroyed(destroyed);
         }
+    } else {
+        const auto children = q->children();
+        for (QObject *child : children) {
+            // Some non-containment applets can have another applet as child to
+            // emulate nested containments, such as the systray and grouping plasmoid
+            Plasma::Applet *applet = qobject_cast<Plasma::Applet *>(child);
+            if (applet) {
+                applet->d->setDestroyed(destroyed);
+            }
+        }
     }
     Q_EMIT q->configNeedsSaving();
 }
@@ -423,18 +433,12 @@ void AppletPrivate::propagateConfigChanged()
 
 void AppletPrivate::setUiReady()
 {
-    // If we a re a containment, call setUiReady
-    Containment *thisContainment = qobject_cast<Containment *>(q);
-    if (thisContainment && thisContainment->isContainment()) {
-        thisContainment->d->setUiReady();
-    }
-
-    // If we are inside a containment, call appletLoaded on the containment
-    // Note that q->containment() might be a different containment
-    // also for a containment as is possible to have nested containments, such as the systemtray
-    Containment *parentContainment = q->containment();
-    if (parentContainment && parentContainment != thisContainment) {
-        parentContainment->d->appletLoaded(q);
+    // am i the containment?
+    Containment *c = qobject_cast<Containment *>(q);
+    if (c && c->isContainment()) {
+        c->d->setUiReady();
+    } else if (Containment *cc = q->containment()) {
+        cc->d->appletLoaded(q);
     }
 }
 
@@ -486,7 +490,7 @@ KConfigGroup *AppletPrivate::mainConfigGroup()
         parentApplet = qobject_cast<Plasma::Applet *>(c->parent());
     }
 
-    if (q->isContainment() && static_cast<Containment *>(q)->containmentType() != Containment::CustomEmbedded) {
+    if (q->isContainment()) {
         Corona *corona = static_cast<Containment *>(q)->corona();
         KConfigGroup containmentConfig;
         // qCDebug(LOG_PLASMA) << "got a corona, baby?" << (QObject*)corona << (QObject*)q;
diff --git a/src/plasma/private/containment_p.cpp b/src/plasma/private/containment_p.cpp
index b9fa81e0d..82dc5b0be 100644
--- a/src/plasma/private/containment_p.cpp
+++ b/src/plasma/private/containment_p.cpp
@@ -34,6 +34,12 @@ ContainmentPrivate::ContainmentPrivate(Containment *c)
     , uiReady(false)
     , appletsUiReady(false)
 {
+    // if the parent is an applet (i.e we are the systray)
+    // we want to follow screen changed signals from the parent's containment
+    auto appletParent = qobject_cast<Plasma::Applet *>(c->parent());
+    if (appletParent) {
+        QObject::connect(appletParent->containment(), &Containment::screenChanged, c, &Containment::screenChanged);
+    }
     activityInfo = new KActivities::Info(activityId, q);
     QObject::connect(activityInfo, &KActivities::Info::nameChanged, q, &Containment::activityNameChanged);
 }
diff --git a/src/plasmaquick/appletquickitem.cpp b/src/plasmaquick/appletquickitem.cpp
index c9f5c9074..7ac69a221 100644
--- a/src/plasmaquick/appletquickitem.cpp
+++ b/src/plasmaquick/appletquickitem.cpp
@@ -630,7 +630,7 @@ AppletQuickItem *AppletQuickItem::itemForApplet(Plasma::Applet *applet)
     qmlObject->completeInitialization();
 
     // A normal applet has UI ready as soon as is loaded, a containment, only when also the wallpaper is loaded
-    if (!pc || !pc->isContainment() || pc->containmentType() == Plasma::Containment::CustomEmbedded) {
+    if (!pc || !pc->isContainment()) {
         applet->updateConstraints(Plasma::Applet::UiReadyConstraint);
         applet->flushPendingConstraintsEvents();
     }
diff --git a/src/plasmaquick/configview.cpp b/src/plasmaquick/configview.cpp
index 7760a796f..eb37594e3 100644
--- a/src/plasmaquick/configview.cpp
+++ b/src/plasmaquick/configview.cpp
@@ -96,11 +96,18 @@ void ConfigViewPrivate::init()
     q->setColor(Qt::transparent);
     updateTitle();
 
-    if (!applet.data()->containment()->corona()->kPackage().isValid()) {
-        qCWarning(LOG_PLASMAQUICK) << "Invalid home screen package";
+    // systray case
+    if (!applet.data()->containment()->corona()) {
+        Plasma::Applet *a = qobject_cast<Plasma::Applet *>(applet.data()->containment()->parent());
+        if (a) {
+            corona = a->containment()->corona();
+        }
+    } else {
+        if (!applet.data()->containment()->corona()->kPackage().isValid()) {
+            qCWarning(LOG_PLASMAQUICK) << "Invalid home screen package";
+        }
+        corona = applet.data()->containment()->corona();
     }
-    corona = applet.data()->containment()->corona();
-
     if (!corona) {
         qCWarning(LOG_PLASMAQUICK) << "Cannot find a Corona, this should never happen!";
         return;
-- 
2.51.1

openSUSE Build Service is sponsored by