diff --git a/src/plasma/containment.cpp b/src/plasma/containment.cpp index eae63074b..71c417a61 100644 --- a/src/plasma/containment.cpp +++ b/src/plasma/containment.cpp @@ -178,9 +178,6 @@ void Containment::restore(KConfigGroup &group) restoreContents(group); setImmutability((Types::ImmutabilityType)group.readEntry("immutability", (int)Types::Mutable)); - //qDebug() << "setScreen from restore"; - d->setScreen(group.readEntry("screen", d->screen)); - KConfigGroup cfg = KConfigGroup(corona()->config(), "ActionPlugins"); cfg = KConfigGroup(&cfg, QString::number(containmentType())); @@ -230,7 +227,7 @@ void Containment::save(KConfigGroup &g) const // locking is saved in Applet::save Applet::save(group); - group.writeEntry("screen", d->screen); +// group.writeEntry("screen", d->screen); group.writeEntry("lastScreen", d->lastScreen); group.writeEntry("formfactor", (int)d->formFactor); group.writeEntry("location", (int)d->location); @@ -429,14 +426,9 @@ QList Containment::applets() const return d->applets; } -void Containment::setScreen(int newScreen) -{ - d->setScreen(newScreen); -} - int Containment::screen() const { - return d->screen; + return corona()->screenForContainment(this); } int Containment::lastScreen() const @@ -546,6 +538,23 @@ QString Containment::activity() const return d->activityId; } +void Containment::reactToScreenChange() +{ + int newScreen = screen(); + + KConfigGroup c = config(); + if (newScreen >= 0) { + d->lastScreen = newScreen; + c.writeEntry("lastScreen", d->lastScreen); + } + emit configNeedsSaving(); + emit screenChanged(newScreen); + + if (newScreen >= 0) { + emit activate(); + } +} + } // Plasma namespace diff --git a/src/plasma/containment.h b/src/plasma/containment.h index 874fb3977..1d747c673 100644 --- a/src/plasma/containment.h +++ b/src/plasma/containment.h @@ -133,15 +133,6 @@ class PLASMA_EXPORT Containment : public Applet */ QList applets() const; - /** - * Sets the physical screen this Containment is associated with. - * - * @param screen the screen number this containment is the desktop for, or -1 - * if it is not serving as the desktop for any screen - * @param desktop the virtual desktop to also associate this this screen with - */ - void setScreen(int screen); - /** * @return the screen number this containment is serving as the desktop for * or -1 if none @@ -243,14 +234,12 @@ Q_SIGNALS: void showAddWidgetsInterface(const QPointF &pos); /** - * This signal indicates that a containment has been newly + * This signal indicates that a containment has been * associated (or dissociated) with a physical screen. * - * @param wasScreen the screen it was associated with - * @param isScreen the screen it is now associated with - * @param containment the containment switching screens + * @param newScreen the screen it is now associated with */ - void screenChanged(int wasScreen, int isScreen, Plasma::Containment *containment); + void screenChanged(int newScreen); /** * Emitted when the user wants to configure/change the containment, or an applet inside it. @@ -317,6 +306,8 @@ Q_SIGNALS: */ void setDrawWallpaper(bool drawWallpaper); + void reactToScreenChange(); + protected: /** * Called when the contents of the containment should be saved. By default this saves diff --git a/src/plasma/corona.cpp b/src/plasma/corona.cpp index 13dd4d394..c746c138d 100644 --- a/src/plasma/corona.cpp +++ b/src/plasma/corona.cpp @@ -175,22 +175,6 @@ Containment *Corona::containmentForScreen(int screen) const return 0; } -Containment *Corona::containmentForScreen(int screen, const QString &defaultPluginIfNonExistent) -{ - Containment *containment = containmentForScreen(screen); - if (!containment && !defaultPluginIfNonExistent.isEmpty()) { - // screen requests are allowed to bypass immutability - if (screen >= 0 && screen < numScreens()) { - containment = d->addContainment(defaultPluginIfNonExistent, QVariantList(), 0); - if (containment) { - containment->setScreen(screen); - } - } - } - - return containment; -} - QList Corona::containments() const { return d->containments; diff --git a/src/plasma/corona.h b/src/plasma/corona.h index e089939dc..b96ec206d 100644 --- a/src/plasma/corona.h +++ b/src/plasma/corona.h @@ -99,17 +99,6 @@ public: */ Containment *containmentForScreen(int screen) const; - /** - * Returns the Containment for a given physical screen and desktop, creating one - * if none exists - * - * @param screen number of the physical screen to locate - * @param defaultPluginIfNonExistent the plugin to load by default; "null" is an empty - * Containment and "default" creates the default plugin - * @since 4.6 - */ - Containment *containmentForScreen(int screen, const QString &defaultPluginIfNonExistent); - /** * Returns the number of screens available to plasma. * Subclasses should override this method as the default @@ -168,6 +157,12 @@ public: */ void exportLayout(KConfigGroup &config, QList containments); + /** + * @returns the id of the screen which is showing @p containment + * -1 is returned if the containment is not associated with a screen. + */ + virtual int screenForContainment(const Containment *containment) const = 0; + public Q_SLOTS: /** * Load applet layout from a config file. The results will be added to the diff --git a/src/plasma/private/containment_p.cpp b/src/plasma/private/containment_p.cpp index a03b53176..477486e2a 100644 --- a/src/plasma/private/containment_p.cpp +++ b/src/plasma/private/containment_p.cpp @@ -71,85 +71,6 @@ void ContainmentPrivate::addDefaultActions(KActionCollection *actions, Containme appletBrowserAction->setData(Plasma::Types::AddAction); } -void ContainmentPrivate::setScreen(int newScreen) -{ - // What we want to do in here is: - // * claim the screen as our own - // * signal whatever may be watching this containment about the switch - // * if we are a full screen containment, then: - // * resize to match the screen if we're that kind of containment - // * kick other full-screen containments off this screen - // * if we had a screen, then give our screen to the containment - // we kick out - // - // a screen of -1 means no associated screen. - Corona *corona = q->corona(); - Q_ASSERT(corona); - - //if it's an offscreen widget, don't allow to claim a screen, after all it's *off*screen - //TODO: port away qgv - /* should decide in a different way if this is a dashboard containment - if (corona->offscreenWidgets().contains(q)) { - return; - }*/ - - if (newScreen < -1) { - newScreen = -1; - } - - //qDebug() << activity() << "setting screen to " << newScreen << "and type is" << type; - - Containment *swapScreensWith(0); - const bool isDesktopContainment = type == Plasma::Types::DesktopContainment || - type == Plasma::Types::CustomContainment; - if (isDesktopContainment) { - if (newScreen > -1) { - // sanity check to make sure someone else doesn't have this screen already! - Containment *currently = corona->containmentForScreen(newScreen); - if (currently && currently != q) { -#ifndef NDEBUG - // qDebug() << "currently is on screen" << currently->screen() -// << "desktop" << currently->desktop() -// << "and is" << currently->activity() -// << (QObject*)currently << "i'm" << (QObject*)q; -#endif - currently->setScreen(-1); - swapScreensWith = currently; - } - } - } - - int oldScreen = screen; - screen = newScreen; - - q->updateConstraints(Plasma::Types::ScreenConstraint); - - if (oldScreen != newScreen) { -#ifndef NDEBUG - // qDebug() << "going to signal change for" << q - // << ", old screen & desktop:" << oldScreen - // << ", new:" << screen << desktop; -#endif - KConfigGroup c = q->config(); - c.writeEntry("screen", screen); - if (newScreen != -1) { - lastScreen = newScreen; - c.writeEntry("lastScreen", lastScreen); - } - emit q->configNeedsSaving(); - emit q->screenChanged(oldScreen, newScreen, q); - } - - if (swapScreensWith) { - //qDebug() << "setScreen due to swap, part 2"; - swapScreensWith->setScreen(oldScreen); - } - - if (newScreen >= 0) { - emit q->activate(); - } -} - KConfigGroup ContainmentPrivate::containmentActionsConfig() const { KConfigGroup cfg = KConfigGroup(q->corona()->config(), "ActionPlugins"); diff --git a/src/plasma/private/containment_p.h b/src/plasma/private/containment_p.h index 6c92d98d8..597f26ece 100644 --- a/src/plasma/private/containment_p.h +++ b/src/plasma/private/containment_p.h @@ -49,7 +49,6 @@ public: : q(c), formFactor(Types::Planar), location(Types::Floating), - screen(-1), // no screen lastScreen(-1), // never had a screen type(Plasma::Types::NoContainmentType), drawWallpaper(false) @@ -67,7 +66,6 @@ public: void triggerShowAddWidgets(); void checkStatus(Plasma::Types::ItemStatus status); - void setScreen(int newScreen); /** * Called when constraints have been updated on this containment to provide @@ -103,7 +101,6 @@ public: QSet loadingApplets; QString wallpaper; QHash localActionPlugins; - int screen; int lastScreen; QString activityId; Types::ContainmentType type; diff --git a/src/plasmaquick/plasmaquickview.cpp b/src/plasmaquick/plasmaquickview.cpp index 54bc7ae7b..f46959379 100644 --- a/src/plasmaquick/plasmaquickview.cpp +++ b/src/plasmaquick/plasmaquickview.cpp @@ -74,6 +74,7 @@ void PlasmaQuickViewPrivate::setContainment(Plasma::Containment *cont) //FIXME:we need a way to reparent to *NO* graphics item, but this makes Qt crash oldGraphicObject->setParent(containment.data()); } + containment.data()->reactToScreenChange(); } containment = cont; @@ -88,6 +89,7 @@ void PlasmaQuickViewPrivate::setContainment(Plasma::Containment *cont) emit q->containmentChanged(); if (cont) { + cont->reactToScreenChange(); QObject::connect(cont, &Plasma::Containment::locationChanged, q, &PlasmaQuickView::locationChanged); QObject::connect(cont, &Plasma::Containment::formFactorChanged, diff --git a/src/shell/activity.cpp b/src/shell/activity.cpp index e7e20f0c1..0b5493ed0 100644 --- a/src/shell/activity.cpp +++ b/src/shell/activity.cpp @@ -42,10 +42,9 @@ Activity::Activity(const QString &id, Plasma::Corona *parent) : QObject(parent), m_id(id), - m_plugin("org.kde.desktopcontainment"), + m_plugin("org.kde.desktopcontainment"),//FIXME ask the corona m_info(new KActivities::Info(id, this)), m_activityConsumer(new KActivities::Consumer(this)), - m_corona(parent), m_current(false) { m_name = m_info->name(); @@ -53,23 +52,13 @@ Activity::Activity(const QString &id, Plasma::Corona *parent) connect(m_info, SIGNAL(infoChanged()), this, SLOT(activityChanged())); connect(m_info, SIGNAL(stateChanged(KActivities::Info::State)), this, SIGNAL(stateChanged())); - connect(m_info, SIGNAL(started()), this, SLOT(opened())); - connect(m_info, SIGNAL(stopped()), this, SLOT(closed())); - connect(m_info, SIGNAL(removed()), this, SLOT(removed())); + connect(m_info, SIGNAL(started()), this, SIGNAL(opened())); + connect(m_info, SIGNAL(stopped()), this, SIGNAL(closed())); + connect(m_info, SIGNAL(removed()), this, SIGNAL(removed())); + connect(m_info, SIGNAL(removed()), this, SLOT(cleanupActivity())); connect(m_activityConsumer, SIGNAL(currentActivityChanged(QString)), this, SLOT(checkIfCurrent())); checkIfCurrent(); - - //find your containments - foreach (Plasma::Containment *cont, m_corona->containments()) { - if ((cont->containmentType() == Plasma::Types::DesktopContainment || - cont->containmentType() == Plasma::Types::CustomContainment) && - cont->activity() == id) { - insertContainment(cont); - } - } - - //qDebug() << m_containments.size(); } Activity::~Activity() @@ -126,112 +115,17 @@ void Activity::remove() KActivities::Controller().removeActivity(m_id); } -void Activity::removed() +void Activity::cleanupActivity() { - if (! m_containments.isEmpty()) { - //FIXME only m_corona has authority to remove properly - qDebug() << "!!!!! if your widgets are locked you've hit a BUG now"; - foreach (Plasma::Containment *c, m_containments) { - c->destroy(); - } - } - const QString name = "activities/" + m_id; QFile::remove(QStandardPaths::writableLocation(QStandardPaths::DataLocation)+QChar('/')+name); } -Plasma::Containment* Activity::containmentForScreen(int screen) -{ - Plasma::Containment *containment = m_containments.value(screen); - - if (!containment) { - qDebug() << "adding containment for" << screen; - // first look to see if there are any unnasigned containments that are candidates for - // being sucked into this Activity - containment = m_corona->containmentForScreen(-1); - - if (containment && m_containments.key(containment, -2) == -2 ) { - containment->setScreen(screen); - } - - if (!containment) { - // we ask for the containment for the screen with a default plugin, because - // this allows the corona to either grab one for us that already exists matching - // screen, or create a new one. this also works regardless of immutability - containment = m_corona->containmentForScreen(screen, m_plugin); - - if (!containment || !containment->activity().isEmpty()) { - // possibly a plugin failure, let's go for the default - containment = m_corona->containmentForScreen(screen, "org.kde.desktopcontainment"); - } - - Q_ASSERT(containment); - if (!containment) { - // we failed to even get the default; we're screwed. - return 0; - } - - //we don't want to steal contaiments from other activities - if (containment->activity() != m_id) { - // we got a containment, but it belongs to some other activity; let's unassign it - // from a screen and grab a new one - containment->setScreen(-1); - containment = m_corona->containmentForScreen(screen, m_plugin); - - if (!containment) { - // possibly a plugin failure, let's go for the default - containment = m_corona->containmentForScreen(screen, "org.kde.desktopcontainment"); - } - - if (containment) { - containment->setScreen(screen); - } - } - } - - if (containment) { - insertContainment(containment, screen); - m_corona->requestConfigSync(); - } - } else if (containment->screen() != screen) { - // ensure the containment _also_ knows which screen we think it is on; - // can happen when swapping between activities without stopping them first - containment->setScreen(screen); - } - - QAction *closeAction = containment->actions()->action("remove"); - if (closeAction) { - closeAction->setEnabled(false); - closeAction->setVisible(false); - } - - return containment; -} - void Activity::activate() { KActivities::Controller().setCurrentActivity(m_id); } -void Activity::ensureActive() -{ - if (m_containments.isEmpty()) { - opened(); - } - - checkScreens(); -} - -void Activity::checkScreens() -{ - //ensure there's a containment for every screen & desktop. - int numScreens = m_corona->numScreens(); - - for (int screen = 0; screen < numScreens; ++screen) { - containmentForScreen(screen); - } -} - void Activity::setName(const QString &name) { m_name = name; @@ -242,85 +136,18 @@ void Activity::setIcon(const QString &icon) m_icon = icon; } -void Activity::save(KConfig &external) -{ - foreach (const QString &group, external.groupList()) { - KConfigGroup cg(&external, group); - cg.deleteGroup(); - } - - //TODO: multi-screen saving/restoring, where each screen can be - // independently restored: put each screen's containments into a - // different group, e.g. [Screens][0][Containments], [Screens][1][Containments], etc - KConfigGroup dest(&external, "Containments"); - KConfigGroup dummy; - foreach (Plasma::Containment *c, m_containments) { - c->save(dummy); - KConfigGroup group(&dest, QString::number(c->id())); - c->config().copyTo(&group); - } - - external.sync(); -} - void Activity::close() { KActivities::Controller().stopActivity(m_id); } -void Activity::closed() +KConfigGroup Activity::config() const { const QString name = "activities/" + m_id; KConfig external(name, KConfig::SimpleConfig, QStandardPaths::GenericDataLocation); //passing an empty string for the group name turns a kconfig into a kconfiggroup - KConfigGroup group = external.group(QString()); - m_corona->exportLayout(group, m_containments.values()); - - //hrm, shouldn't the containments' deleted signals have done this for us? - if (!m_containments.isEmpty()) { - qDebug() << "isn't close supposed to *remove* containments??"; - m_containments.clear(); - } -} - -void Activity::insertContainment(Plasma::Containment* cont) -{ - int screen = cont->lastScreen(); - - qDebug() << screen; - if (screen == -1) { - //the migration can't set lastScreen, so maybe we need to assign the containment here - qDebug() << "found a lost one"; - screen = 0; - } - - if (m_containments.contains(screen)) { - //this almost certainly means someone has been meddling where they shouldn't - //but we should protect them from harm anyways - qDebug() << "@!@!@!@!@!@@@@rejecting containment!!!"; - cont->setActivity(QString()); - return; - } - - insertContainment(cont, screen); -} - -void Activity::insertContainment(Plasma::Containment* containment, int screen) -{ - //ensure it's hooked up - containment->setActivity(m_id); - - m_containments.insert(screen, containment); - connect(containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed(QObject*))); -} - -void Activity::containmentDestroyed(QObject *object) -{ - //safe here because we are not accessing it - Plasma::Containment *deletedCont = static_cast(object); - - m_containments.remove(m_containments.key(deletedCont)); + return external.group(QString()); } void Activity::open() @@ -328,38 +155,6 @@ void Activity::open() KActivities::Controller().startActivity(m_id); } -void Activity::opened() -{ - if (!m_containments.isEmpty()) { - qDebug() << "already open!"; - return; - } - - const QString fileName = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QString("/activities/" + m_id); - qDebug() << "&&&&&&&&&&&&&&&" << fileName; - if (QFile::exists(fileName)) { - { - KConfig external(fileName, KConfig::SimpleConfig); - - foreach (Plasma::Containment *newContainment, m_corona->importLayout(external.group(QByteArray()))) { - insertContainment(newContainment); - //ensure it's hooked up (if something odd happened we don't want orphan containments) - newContainment->setActivity(m_id); - } - } - - QFile::remove(fileName); - } - - if (m_containments.isEmpty()) { - //TODO check if we need more for screens/desktops - qDebug() << "open failed (bad file?). creating new containment"; - checkScreens(); - } - - m_corona->requireConfigSync(); -} - void Activity::setDefaultPlugin(const QString &plugin) { m_plugin = plugin; diff --git a/src/shell/activity.h b/src/shell/activity.h index 1cb0dd038..e58bdf9fe 100644 --- a/src/shell/activity.h +++ b/src/shell/activity.h @@ -24,6 +24,7 @@ #include #include +#include class QSize; class QString; @@ -81,22 +82,6 @@ public: */ KActivities::Info::State state(); - /** - * save (copy) the activity out to an @p external config - */ - void save(KConfig &external); - - /** - * return the containment that belongs on @p screen and @p desktop - * or null if none exists - */ - Plasma::Containment* containmentForScreen(int screen); - - /** - * make this activity's containments the active ones, loading them if necessary - */ - void ensureActive(); - /** * set the plugin to use when creating new containments */ @@ -107,11 +92,17 @@ public: */ const KActivities::Info * info() const; + KConfigGroup config() const; + Q_SIGNALS: void infoChanged(); void stateChanged(); void currentStatusChanged(); + void removed(); + void opened(); + void closed(); + public Q_SLOTS: void setName(const QString &name); void setIcon(const QString &icon); @@ -137,27 +128,17 @@ public Q_SLOTS: void open(); private Q_SLOTS: - void containmentDestroyed(QObject *object); void activityChanged(); void checkIfCurrent(); - - void removed(); - void opened(); - void closed(); + void cleanupActivity(); private: - void insertContainment(Plasma::Containment* cont); - void insertContainment(Plasma::Containment* containment, int screen); - void checkScreens(); - QString m_id; QString m_name; QString m_icon; QString m_plugin; - QHash m_containments; KActivities::Info *m_info; KActivities::Consumer *m_activityConsumer; - Plasma::Corona *m_corona; bool m_current; }; diff --git a/src/shell/scripting/containment.cpp b/src/shell/scripting/containment.cpp index bfaf60973..e6c395e84 100644 --- a/src/shell/scripting/containment.cpp +++ b/src/shell/scripting/containment.cpp @@ -82,13 +82,6 @@ int Containment::screen() const return d->containment.data()->screen(); } -void Containment::setScreen(int screen) -{ - if (d->containment) { - d->containment.data()->setScreen(screen); - } -} - QString Containment::wallpaperPlugin() const { return d->wallpaperPlugin; diff --git a/src/shell/scripting/containment.h b/src/shell/scripting/containment.h index 390777ec4..777f1a71e 100644 --- a/src/shell/scripting/containment.h +++ b/src/shell/scripting/containment.h @@ -37,6 +37,7 @@ namespace WorkspaceScripting class Containment : public Applet { Q_OBJECT + ///FIXME: add NOTIFY Q_PROPERTY(QString version READ version) Q_PROPERTY(QStringList configKeys READ configKeys) Q_PROPERTY(QStringList configGroups READ configGroups) @@ -50,7 +51,7 @@ class Containment : public Applet Q_PROPERTY(QString type READ type) Q_PROPERTY(QString formFactor READ formFactor) Q_PROPERTY(QList widgetIds READ widgetIds) - Q_PROPERTY(int screen READ screen WRITE setScreen) + Q_PROPERTY(int screen READ screen) Q_PROPERTY(int id READ id) public: @@ -66,7 +67,6 @@ public: void setName(const QString &name); int screen() const; - void setScreen(int screen); Plasma::Applet *applet() const; Plasma::Containment *containment() const; diff --git a/src/shell/scripting/panel.h b/src/shell/scripting/panel.h index 99da56735..5b5f971ea 100644 --- a/src/shell/scripting/panel.h +++ b/src/shell/scripting/panel.h @@ -44,7 +44,7 @@ class Panel : public Containment Q_PROPERTY(QString type READ type) Q_PROPERTY(QString formFactor READ formFactor) Q_PROPERTY(QList widgetIds READ widgetIds) - Q_PROPERTY(int screen READ screen WRITE setScreen) + Q_PROPERTY(int screen READ screen) Q_PROPERTY(QString location READ location WRITE setLocation) Q_PROPERTY(int id READ id) diff --git a/src/shell/scripting/scriptengine.cpp b/src/shell/scripting/scriptengine.cpp index dd99e9742..29735a0e8 100644 --- a/src/shell/scripting/scriptengine.cpp +++ b/src/shell/scripting/scriptengine.cpp @@ -140,7 +140,6 @@ QScriptValue ScriptEngine::createContainment(const QString &type, const QString // some defaults c->setFormFactor(Plasma::Types::Horizontal); c->setLocation(Plasma::Types::TopEdge); - c->setScreen(env->defaultPanelScreen()); } c->updateConstraints(Plasma::Types::AllConstraints | Plasma::Types::StartupCompletedConstraint); c->flushPendingConstraintsEvents(); diff --git a/src/shell/shellcorona.cpp b/src/shell/shellcorona.cpp index d7dce45c8..c25b2c035 100644 --- a/src/shell/shellcorona.cpp +++ b/src/shell/shellcorona.cpp @@ -76,8 +76,8 @@ public: KConfigGroup desktopDefaultsConfig; WorkspaceScripting::DesktopScriptEngine * scriptEngine; QList waitingPanels; - QSet loadingDesktops; QHash activities; + QHash > desktopContainments; QTimer *waitingPanelsTimer; QAction *addPanelAction; QMenu *addPanelsMenu; @@ -103,16 +103,8 @@ ShellCorona::ShellCorona(QObject *parent) connect(&d->appConfigSyncTimer, &QTimer::timeout, this, &ShellCorona::syncAppConfig); - //FIXME deprecate QDesktopWidget (can probably just remove these) - connect(d->desktopWidget, &QDesktopWidget::resized, - this, &ShellCorona::screenResized ); - connect(d->desktopWidget, &QDesktopWidget::workAreaResized, - this, &ShellCorona::workAreaResized); - connect(this, &ShellCorona::containmentAdded, this, &ShellCorona::handleContainmentAdded); - connect(this, &ShellCorona::screenOwnerChanged, - this, &ShellCorona::updateScreenOwner); d->scriptEngine = new WorkspaceScripting::DesktopScriptEngine(this, true); @@ -171,8 +163,11 @@ void ShellCorona::setShell(const QString &shell) package.setPath(shell); setPackage(package); - load(); - //TODO: panel views should be synced here: either creating views for panels without, or deleting views for panels that don't have one anymore + if (d->activityConsumer->serviceStatus() == KActivities::Consumer::Unknown) { + connect(d->activityConsumer, SIGNAL(serviceStatusChanged(Consumer::ServiceStatus)), SLOT(load()), Qt::UniqueConnection); + } else { + load(); + } } QString ShellCorona::shell() const @@ -182,16 +177,36 @@ QString ShellCorona::shell() const void ShellCorona::load() { - if (d->shell.isEmpty()) return; + if (d->shell.isEmpty() || d->activityConsumer->serviceStatus() == KActivities::Consumer::Unknown) + return; + disconnect(d->activityConsumer, SIGNAL(serviceStatusChanged(Consumer::ServiceStatus)), this, SLOT(load())); loadLayout("plasma-" + d->shell + "-appletsrc"); + checkActivities(); if (containments().isEmpty()) { loadDefaultLayout(); + foreach(Plasma::Containment* containment, containments()) { + containment->setActivity(d->activityConsumer->currentActivity()); + } } processUpdateScripts(); - checkActivities(); + foreach(Plasma::Containment* containment, containments()) { + if (containment->formFactor() == Plasma::Types::Horizontal || + containment->formFactor() == Plasma::Types::Vertical) { + if (!d->waitingPanels.contains(containment)) { + d->waitingPanels << containment; + } + } else { + //FIXME ideally fix this, or at least document the crap out of it + int screen = containment->lastScreen(); + if (screen < 0) { + screen = d->desktopContainments[containment->activity()].count(); + } + d->desktopContainments[containment->activity()][screen] = containment; + } + } for (QScreen *screen : QGuiApplication::screens()) { screenAdded(screen); @@ -199,13 +214,14 @@ void ShellCorona::load() connect(qApp, &QGuiApplication::screenAdded, this, &ShellCorona::screenAdded); - checkScreens(); + if (!d->waitingPanels.isEmpty()) { + d->waitingPanelsTimer->start(); + } } void ShellCorona::unload() { if (d->shell.isEmpty()) return; - qDeleteAll(containments()); } @@ -239,55 +255,11 @@ void ShellCorona::processUpdateScripts() } } -Activity* ShellCorona::activity(const QString &id) -{ - if (!d->activities.contains(id)) { - //the add signal comes late sometimes - activityAdded(id); - } - return d->activities.value(id); -} - KActivities::Controller *ShellCorona::activityController() { return d->activityController; } -void ShellCorona::checkScreens() -{ - // quick sanity check to ensure we have containments for each screen - int num = numScreens(); - for (int i = 0; i < num; ++i) { - checkScreen(i); - } -} - -void ShellCorona::checkScreen(int screen) -{ - //TODO: restore activities - Activity *currentActivity = activity(d->activityController->currentActivity()); - //ensure the desktop(s) have a containment and view - Plasma::Containment *c = currentActivity->containmentForScreen(screen); - - //TODO: remove following when activities are restored - if (!c) { - c = createContainment(d->desktopDefaultsConfig.readEntry("Containment", "org.kde.desktopcontainment")); - } - - if (!c) { - return; - } - - c->setScreen(screen); - if (screen >= 0 || d->views.count() >= screen + 1) { - d->views[screen]->setContainment(c); - } else { - qWarning() << "Invalid screen"; - } - c->flushPendingConstraintsEvents(); - requestApplicationConfigSync(); -} - int ShellCorona::numScreens() const { return d->desktopWidget->screenCount(); @@ -316,115 +288,64 @@ PanelView *ShellCorona::panelView(Plasma::Containment *containment) const ///// SLOTS -void ShellCorona::screenCountChanged(int newCount) -{ - qDebug() << "New screen count" << newCount; -} - -void ShellCorona::screenResized(int screen) -{ - qDebug() << "Screen resized" << screen; -} - -void ShellCorona::workAreaResized(int screen) -{ - qDebug() << "Work area resized" << screen; -} - void ShellCorona::screenAdded(QScreen *screen) { DesktopView *view = new DesktopView(this, screen); d->views << view; view->show(); + int screenNum = d->views.count()-1; + QString currentActivity = d->activityController->currentActivity(); + Plasma::Containment *containment = d->desktopContainments[currentActivity][screenNum]; + if(!containment) { + containment = createContainmentForActivity(currentActivity, screenNum); + } + view->setContainment(containment); + connect(screen, SIGNAL(destroyed(QObject*)), SLOT(screenRemoved(QObject*))); } +Plasma::Containment* ShellCorona::createContainmentForActivity(const QString& activity, int screenNum) +{ + Plasma::Containment* containment = createContainment(d->desktopDefaultsConfig.readEntry("Containment", "org.kde.desktopcontainment")); + containment->setActivity(activity); + d->desktopContainments[activity][screenNum] = containment; + return containment; +} + void ShellCorona::screenRemoved(QObject *screen) { for (auto i = d->views.begin(); i != d->views.end() ; i++) { if ((*i)->screen() == screen) { (*i)->deleteLater(); d->views.erase(i); + (*i)->containment()->reactToScreenChange(); break; } } } -void ShellCorona::checkLoadingDesktopsComplete() -{ - Plasma::Containment *c = qobject_cast(sender()); - if (c) { - disconnect(c, &Plasma::Containment::uiReadyChanged, - this, &ShellCorona::checkLoadingDesktopsComplete); - d->loadingDesktops.remove(c); - } - - if (d->loadingDesktops.isEmpty()) { - d->waitingPanelsTimer->start(); - } else { - d->waitingPanelsTimer->stop(); - } -} - void ShellCorona::createWaitingPanels() { foreach (Plasma::Containment *cont, d->waitingPanels) { d->panelViews[cont] = new PanelView(this); + + + //keep screen suggestions within bounds of screens we actually have + int screen = cont->lastScreen(); + screen = qMax(screen, 0); + screen = qMin(screen, QGuiApplication::screens().size() -1); + + d->panelViews[cont]->setScreen(QGuiApplication::screens()[screen]); d->panelViews[cont]->setContainment(cont); } d->waitingPanels.clear(); } -void ShellCorona::updateScreenOwner(int wasScreen, int isScreen, Plasma::Containment *containment) -{ - qDebug() << "Was screen" << wasScreen << "Is screen" << isScreen <<"Containment" << containment << containment->title(); - - if (containment->formFactor() == Plasma::Types::Horizontal || - containment->formFactor() == Plasma::Types::Vertical) { - - if (isScreen >= 0) { - if (!d->waitingPanels.contains(containment)) { - d->waitingPanels << containment; - } - } else { - if (d->panelViews.contains(containment)) { - d->panelViews[containment]->setContainment(0); - d->panelViews[containment]->deleteLater(); - d->panelViews.remove(containment); - d->waitingPanels.removeAll(containment); - } - } - checkLoadingDesktopsComplete(); - - //Desktop view - } else { - - if (containment->isUiReady()) { - d->loadingDesktops.remove(containment); - checkLoadingDesktopsComplete(); - } else { - d->loadingDesktops.insert(containment); - connect(containment, &Plasma::Containment::uiReadyChanged, - this, &ShellCorona::checkLoadingDesktopsComplete); - } - - if (isScreen < 0 || d->views.count() < isScreen + 1) { - qWarning() << "Invalid screen"; - return; - } - - d->views[isScreen]->setContainment(containment); - } -} - void ShellCorona::handleContainmentAdded(Plasma::Containment* c) { connect(c, &Plasma::Containment::showAddWidgetsInterface, this, &ShellCorona::toggleWidgetExplorer); - connect(c, &QObject::destroyed, [=] (QObject *o) { - d->loadingDesktops.remove(static_cast(o)); - }); } void ShellCorona::toggleWidgetExplorer() @@ -473,13 +394,11 @@ void ShellCorona::setDashboardShown(bool show) void ShellCorona::checkActivities() { - qDebug() << "containments to start with" << containments().count(); - KActivities::Consumer::ServiceStatus status = d->activityController->serviceStatus(); //qDebug() << "$%$%$#%$%$%Status:" << status; if (status != KActivities::Consumer::Running) { //panic and give up - better than causing a mess - qDebug() << "No ActivityManager? Help, I've fallen and I can't get up!"; + qDebug() << "ShellCorona::checkActivities is called whilst activity daemon is still connecting"; return; } @@ -505,11 +424,14 @@ void ShellCorona::checkActivities() void ShellCorona::currentActivityChanged(const QString &newActivity) { - Activity *act = activity(newActivity); - qDebug() << "Activity changed:" << newActivity << act; + qDebug() << "Activity changed:" << newActivity; - if (act) { - act->ensureActive(); + for(int i = 0; iviews.count(); ++i) { + Plasma::Containment* c = d->desktopContainments[newActivity][i]; + if(!c) { + c = createContainmentForActivity(newActivity, i); + } + d->views[i]->setContainment(c); } } @@ -522,9 +444,6 @@ void ShellCorona::activityAdded(const QString &id) } Activity *a = new Activity(id, this); - if (a->isCurrent()) { - a->ensureActive(); - } d->activities.insert(id, a); } @@ -619,8 +538,6 @@ void ShellCorona::addPanel(const QString &plugin) panel->setFormFactor(Plasma::Types::Horizontal); break; } - panel->setScreen(0); - d->waitingPanels << panel; d->waitingPanelsTimer->start(); @@ -636,6 +553,54 @@ void ShellCorona::printScriptMessage(const QString &message) qDebug() << message; } +int ShellCorona::screenForContainment(const Plasma::Containment *containment) const +{ + for (int i=0; iviews.size(); i++) { + if (d->views[i]->containment() == containment) { + return i; + } + } + return -1; +} + +void ShellCorona::activityOpened() +{ + Activity* activity = qobject_cast(sender()); + QList cs = importLayout(activity->config()); + for(Plasma::Containment *containment : cs) { + d->desktopContainments[activity->name()][containment->lastScreen()] = containment; + } +} + +void ShellCorona::activityClosed() +{ + Activity* activity = qobject_cast(sender()); + KConfigGroup cg = activity->config(); + exportLayout(cg, d->desktopContainments.value(activity->name()).values()); +} + +void ShellCorona::activityRemoved() +{ + //when an activity is removed delete all associated desktop containments + Activity* activity = qobject_cast(sender()); + + QHash< int, Plasma::Containment* > containmentHash = d->desktopContainments.take(activity->name()); + for(auto a : containmentHash) { + a->destroy(); + } +} + +void ShellCorona::insertContainment(const QString &activity, int screenNum, Plasma::Containment* containment) +{ + d->desktopContainments[activity][screenNum] = containment; + connect(containment, &QObject::destroyed, [=](QObject *obj) { + auto containment = qobject_cast(obj); + d->desktopContainments[containment->activity()].remove(containment->lastScreen()); + }); +} + + + // Desktop corona handler diff --git a/src/shell/shellcorona.h b/src/shell/shellcorona.h index 347ff92bb..b10bf6a4d 100644 --- a/src/shell/shellcorona.h +++ b/src/shell/shellcorona.h @@ -62,8 +62,6 @@ public: PanelView *panelView(Plasma::Containment *containment) const; - Activity* activity(const QString &id); - KActivities::Controller *activityController(); public Q_SLOTS: @@ -83,13 +81,8 @@ public Q_SLOTS: QString shell() const; protected Q_SLOTS: - void screenCountChanged(int newCount); - void screenResized(int screen); - void workAreaResized(int screen); - void screenAdded(QScreen *screen); void screenRemoved(QObject *screen); - void updateScreenOwner(int wasScreen, int isScreen, Plasma::Containment *containment); void printScriptError(const QString &error); void printScriptMessage(const QString &message); @@ -114,8 +107,9 @@ protected Q_SLOTS: */ void processUpdateScripts(); + int screenForContainment(const Plasma::Containment *containment) const; + private Q_SLOTS: - void checkLoadingDesktopsComplete(); void createWaitingPanels(); void handleContainmentAdded(Plasma::Containment *c); void toggleWidgetExplorer(); @@ -131,16 +125,16 @@ private Q_SLOTS: void addPanel(QAction *action); void addPanel(const QString &plugin); + void activityOpened(); + void activityClosed(); + void activityRemoved(); + private: /** - * Ensures we have the necessary containments for every screen + * @returns a new containment associated with the specified @p activity and @p screen. */ - void checkScreens(); - - /** - * Ensures we have the necessary containments for the given screen - */ - void checkScreen(int screen); + Plasma::Containment* createContainmentForActivity(const QString& activity, int screenNum); + void insertContainment(const QString &activity, int screenNum, Plasma::Containment *containment); class Private; const QScopedPointer d;