Move screen management logic in ShellCorona

Previously shells, activities, shellcorona and corona all tried to
manage
which screen a containment was on.

This version moves all screen management into ShellCorona so we have a
central place for keeping tracking of containments, activities and
screens.
This commit is contained in:
David Edmundson 2013-12-12 17:10:36 +01:00
parent 56b2e75b2b
commit a26913ccac
15 changed files with 172 additions and 546 deletions

View File

@ -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<Applet *> 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

View File

@ -133,15 +133,6 @@ class PLASMA_EXPORT Containment : public Applet
*/
QList<Applet *> 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

View File

@ -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<Containment*> Corona::containments() const
{
return d->containments;

View File

@ -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<Containment*> 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

View File

@ -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");

View File

@ -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 <Applet *> loadingApplets;
QString wallpaper;
QHash<QString, ContainmentActions*> localActionPlugins;
int screen;
int lastScreen;
QString activityId;
Types::ContainmentType type;

View File

@ -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,

View File

@ -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<Plasma::Containment *>(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;

View File

@ -24,6 +24,7 @@
#include <QHash>
#include <kactivities/info.h>
#include <kconfiggroup.h>
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<int, Plasma::Containment*> m_containments;
KActivities::Info *m_info;
KActivities::Consumer *m_activityConsumer;
Plasma::Corona *m_corona;
bool m_current;
};

View File

@ -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;

View File

@ -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<int> 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;

View File

@ -44,7 +44,7 @@ class Panel : public Containment
Q_PROPERTY(QString type READ type)
Q_PROPERTY(QString formFactor READ formFactor)
Q_PROPERTY(QList<int> 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)

View File

@ -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();

View File

@ -76,8 +76,8 @@ public:
KConfigGroup desktopDefaultsConfig;
WorkspaceScripting::DesktopScriptEngine * scriptEngine;
QList<Plasma::Containment *> waitingPanels;
QSet<Plasma::Containment *> loadingDesktops;
QHash<QString, Activity*> activities;
QHash<QString, QHash<int, Plasma::Containment*> > 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<Plasma::Containment *>(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<Plasma::Containment *>(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; i<d->views.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; i<d->views.size(); i++) {
if (d->views[i]->containment() == containment) {
return i;
}
}
return -1;
}
void ShellCorona::activityOpened()
{
Activity* activity = qobject_cast<Activity*>(sender());
QList<Plasma::Containment*> cs = importLayout(activity->config());
for(Plasma::Containment *containment : cs) {
d->desktopContainments[activity->name()][containment->lastScreen()] = containment;
}
}
void ShellCorona::activityClosed()
{
Activity* activity = qobject_cast<Activity*>(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<Activity*>(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<Plasma::Containment*>(obj);
d->desktopContainments[containment->activity()].remove(containment->lastScreen());
});
}
// Desktop corona handler

View File

@ -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<Private> d;