Merge branch 'davidedmundson/containmentcleanup2'

This commit is contained in:
David Edmundson 2013-12-17 16:44:54 +01:00
commit a36c2787b9
22 changed files with 273 additions and 653 deletions

View File

@ -25,7 +25,7 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QTimer> #include <QTimer>
#include <QQuickWindow> #include <QQuickWindow>
#include <QScreen>
#include <QDebug> #include <QDebug>
static const int PressAndHoldDelay = 800; static const int PressAndHoldDelay = 800;
@ -107,12 +107,12 @@ void MouseEventListener::hoverMoveEvent(QHoverEvent * event)
} }
QQuickWindow *w = window(); QQuickWindow *w = window();
QPoint screenPos = QPoint(); QPoint screenPos;
if (w) { if (w) {
w->mapToGlobal(event->pos()); screenPos = w->mapToGlobal(event->pos());
} }
KDeclarativeMouseEvent dme(event->pos().x(), event->pos().y(), screenPos.x(), screenPos.y(), Qt::NoButton, Qt::NoButton, event->modifiers()); KDeclarativeMouseEvent dme(event->pos().x(), event->pos().y(), screenPos.x(), screenPos.y(), Qt::NoButton, Qt::NoButton, event->modifiers(), 0);
emit positionChanged(&dme); emit positionChanged(&dme);
} }
@ -137,8 +137,8 @@ void MouseEventListener::mousePressEvent(QMouseEvent *me)
} }
m_buttonDownPos[me->button()] = me->pos(); m_buttonDownPos[me->button()] = me->pos();
KDeclarativeMouseEvent dme(me->pos().x(), me->pos().y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers()); KDeclarativeMouseEvent dme(me->pos().x(), me->pos().y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers(), screenForGlobalPos(me->globalPos()));
m_pressAndHoldEvent = new KDeclarativeMouseEvent(me->pos().x(), me->pos().y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers()); m_pressAndHoldEvent = new KDeclarativeMouseEvent(me->pos().x(), me->pos().y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers(), screenForGlobalPos(me->globalPos()));
emit pressed(&dme); emit pressed(&dme);
m_pressed = true; m_pressed = true;
@ -152,7 +152,7 @@ void MouseEventListener::mouseMoveEvent(QMouseEvent *me)
return; return;
} }
KDeclarativeMouseEvent dme(me->pos().x(), me->pos().y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers()); KDeclarativeMouseEvent dme(me->pos().x(), me->pos().y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers(), screenForGlobalPos(me->globalPos()));
emit positionChanged(&dme); emit positionChanged(&dme);
} }
@ -163,7 +163,7 @@ void MouseEventListener::mouseReleaseEvent(QMouseEvent *me)
return; return;
} }
KDeclarativeMouseEvent dme(me->pos().x(), me->pos().y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers()); KDeclarativeMouseEvent dme(me->pos().x(), me->pos().y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers(), screenForGlobalPos(me->globalPos()));
m_pressed = false; m_pressed = false;
emit released(&dme); emit released(&dme);
@ -217,8 +217,8 @@ bool MouseEventListener::childMouseEventFilter(QQuickItem *item, QEvent *event)
//the parent will receive events in its own coordinates //the parent will receive events in its own coordinates
const QPointF myPos = item->mapToItem(this, me->pos()); const QPointF myPos = item->mapToItem(this, me->pos());
KDeclarativeMouseEvent dme(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers()); KDeclarativeMouseEvent dme(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers(), screenForGlobalPos(me->globalPos()));
m_pressAndHoldEvent = new KDeclarativeMouseEvent(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers()); m_pressAndHoldEvent = new KDeclarativeMouseEvent(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers(), screenForGlobalPos(me->globalPos()));
//qDebug() << "pressed in sceneEventFilter"; //qDebug() << "pressed in sceneEventFilter";
m_buttonDownPos[me->button()] = me->pos(); m_buttonDownPos[me->button()] = me->pos();
emit pressed(&dme); emit pressed(&dme);
@ -236,14 +236,14 @@ bool MouseEventListener::childMouseEventFilter(QQuickItem *item, QEvent *event)
const QPointF myPos = item->mapToItem(this, he->pos()); const QPointF myPos = item->mapToItem(this, he->pos());
QQuickWindow *w = window(); QQuickWindow *w = window();
QPoint screenPos = QPoint(); QPoint screenPos;
if (w) { if (w) {
w->mapToGlobal(myPos.toPoint()); screenPos = w->mapToGlobal(myPos.toPoint());
} }
KDeclarativeMouseEvent dme(myPos.x(), myPos.y(), screenPos.x(), screenPos.y(), Qt::NoButton, Qt::NoButton, he->modifiers()); KDeclarativeMouseEvent dme(myPos.x(), myPos.y(), screenPos.x(), screenPos.y(), Qt::NoButton, Qt::NoButton, he->modifiers(), 0);
//qDebug() << "positionChanged..." << dme.x() << dme.y(); //qDebug() << "positionChanged..." << dme.x() << dme.y();
m_pressAndHoldEvent = new KDeclarativeMouseEvent(myPos.x(), myPos.y(), screenPos.x(), screenPos.y(), Qt::NoButton, Qt::NoButton, he->modifiers()); m_pressAndHoldEvent = new KDeclarativeMouseEvent(myPos.x(), myPos.y(), screenPos.x(), screenPos.y(), Qt::NoButton, Qt::NoButton, he->modifiers(),0);
emit positionChanged(&dme); emit positionChanged(&dme);
break; break;
} }
@ -255,9 +255,9 @@ bool MouseEventListener::childMouseEventFilter(QQuickItem *item, QEvent *event)
} }
const QPointF myPos = item->mapToItem(this, me->pos()); const QPointF myPos = item->mapToItem(this, me->pos());
KDeclarativeMouseEvent dme(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers()); KDeclarativeMouseEvent dme(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers(), screenForGlobalPos(me->globalPos()));
//qDebug() << "positionChanged..." << dme.x() << dme.y(); //qDebug() << "positionChanged..." << dme.x() << dme.y();
m_pressAndHoldEvent = new KDeclarativeMouseEvent(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers()); m_pressAndHoldEvent = new KDeclarativeMouseEvent(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers(), screenForGlobalPos(me->globalPos()));
emit positionChanged(&dme); emit positionChanged(&dme);
break; break;
} }
@ -266,7 +266,7 @@ bool MouseEventListener::childMouseEventFilter(QQuickItem *item, QEvent *event)
QMouseEvent *me = static_cast<QMouseEvent *>(event); QMouseEvent *me = static_cast<QMouseEvent *>(event);
const QPointF myPos = item->mapToItem(this, me->pos()); const QPointF myPos = item->mapToItem(this, me->pos());
KDeclarativeMouseEvent dme(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers()); KDeclarativeMouseEvent dme(myPos.x(), myPos.y(), me->screenPos().x(), me->screenPos().y(), me->button(), me->buttons(), me->modifiers(), screenForGlobalPos(me->globalPos()));
m_pressed = false; m_pressed = false;
emit released(&dme); emit released(&dme);
@ -292,5 +292,16 @@ bool MouseEventListener::childMouseEventFilter(QQuickItem *item, QEvent *event)
// return false; // return false;
} }
QScreen* MouseEventListener::screenForGlobalPos(const QPoint& globalPos)
{
foreach(QScreen *screen, QGuiApplication::screens()) {
if (screen->geometry().contains(globalPos)) {
return screen;
}
}
return 0;
}
#include "mouseeventlistener.moc" #include "mouseeventlistener.moc"

View File

@ -33,19 +33,22 @@ class KDeclarativeMouseEvent : public QObject
Q_PROPERTY(int button READ button) Q_PROPERTY(int button READ button)
Q_PROPERTY(Qt::MouseButtons buttons READ buttons) Q_PROPERTY(Qt::MouseButtons buttons READ buttons)
Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers) Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers)
Q_PROPERTY(QScreen* screen READ screen CONSTANT)
public: public:
KDeclarativeMouseEvent(int x, int y, int screenX, int screenY, KDeclarativeMouseEvent(int x, int y, int screenX, int screenY,
Qt::MouseButton button, Qt::MouseButton button,
Qt::MouseButtons buttons, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers) Qt::KeyboardModifiers modifiers,
QScreen* screen)
: m_x(x), : m_x(x),
m_y(y), m_y(y),
m_screenX(screenX), m_screenX(screenX),
m_screenY(screenY), m_screenY(screenY),
m_button(button), m_button(button),
m_buttons(buttons), m_buttons(buttons),
m_modifiers(modifiers) m_modifiers(modifiers),
m_screen(screen)
{} {}
int x() const { return m_x; } int x() const { return m_x; }
@ -55,6 +58,7 @@ public:
int button() const { return m_button; } int button() const { return m_button; }
Qt::MouseButtons buttons() const { return m_buttons; } Qt::MouseButtons buttons() const { return m_buttons; }
Qt::KeyboardModifiers modifiers() const { return m_modifiers; } Qt::KeyboardModifiers modifiers() const { return m_modifiers; }
QScreen* screen() const { return m_screen; }
// only for internal usage // only for internal usage
void setX(int x) { m_x = x; } void setX(int x) { m_x = x; }
@ -68,6 +72,7 @@ private:
Qt::MouseButton m_button; Qt::MouseButton m_button;
Qt::MouseButtons m_buttons; Qt::MouseButtons m_buttons;
Qt::KeyboardModifiers m_modifiers; Qt::KeyboardModifiers m_modifiers;
QScreen *m_screen;
}; };
class KDeclarativeWheelEvent : public QObject class KDeclarativeWheelEvent : public QObject
@ -173,6 +178,8 @@ private Q_SLOTS:
void handlePressAndHold(); void handlePressAndHold();
private: private:
static QScreen* screenForGlobalPos(const QPoint &globalPos);
QPointF buttonDownPos(int btn) const; QPointF buttonDownPos(int btn) const;
bool m_pressed; bool m_pressed;
KDeclarativeMouseEvent* m_pressAndHoldEvent; KDeclarativeMouseEvent* m_pressAndHoldEvent;

View File

@ -178,9 +178,6 @@ void Containment::restore(KConfigGroup &group)
restoreContents(group); restoreContents(group);
setImmutability((Types::ImmutabilityType)group.readEntry("immutability", (int)Types::Mutable)); 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"); KConfigGroup cfg = KConfigGroup(corona()->config(), "ActionPlugins");
cfg = KConfigGroup(&cfg, QString::number(containmentType())); cfg = KConfigGroup(&cfg, QString::number(containmentType()));
@ -230,7 +227,7 @@ void Containment::save(KConfigGroup &g) const
// locking is saved in Applet::save // locking is saved in Applet::save
Applet::save(group); Applet::save(group);
group.writeEntry("screen", d->screen); // group.writeEntry("screen", d->screen);
group.writeEntry("lastScreen", d->lastScreen); group.writeEntry("lastScreen", d->lastScreen);
group.writeEntry("formfactor", (int)d->formFactor); group.writeEntry("formfactor", (int)d->formFactor);
group.writeEntry("location", (int)d->location); group.writeEntry("location", (int)d->location);
@ -429,14 +426,9 @@ QList<Applet *> Containment::applets() const
return d->applets; return d->applets;
} }
void Containment::setScreen(int newScreen)
{
d->setScreen(newScreen);
}
int Containment::screen() const int Containment::screen() const
{ {
return d->screen; return corona()->screenForContainment(this);
} }
int Containment::lastScreen() const int Containment::lastScreen() const
@ -546,6 +538,23 @@ QString Containment::activity() const
return d->activityId; 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 } // Plasma namespace

View File

@ -133,15 +133,6 @@ class PLASMA_EXPORT Containment : public Applet
*/ */
QList<Applet *> applets() const; 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 * @return the screen number this containment is serving as the desktop for
* or -1 if none * or -1 if none
@ -243,14 +234,12 @@ Q_SIGNALS:
void showAddWidgetsInterface(const QPointF &pos); 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. * associated (or dissociated) with a physical screen.
* *
* @param wasScreen the screen it was associated with * @param newScreen the screen it is now associated with
* @param isScreen the screen it is now associated with
* @param containment the containment switching screens
*/ */
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. * 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 setDrawWallpaper(bool drawWallpaper);
void reactToScreenChange();
protected: protected:
/** /**
* Called when the contents of the containment should be saved. By default this saves * 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; 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 QList<Containment*> Corona::containments() const
{ {
return d->containments; return d->containments;
@ -214,6 +198,12 @@ Containment *Corona::createContainment(const QString &name, const QVariantList &
return 0; return 0;
} }
int Corona::screenForContainment(const Containment* containment) const
{
return -1;
}
int Corona::numScreens() const int Corona::numScreens() const
{ {
return 1; return 1;

View File

@ -99,17 +99,6 @@ public:
*/ */
Containment *containmentForScreen(int screen) const; 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. * Returns the number of screens available to plasma.
* Subclasses should override this method as the default * Subclasses should override this method as the default
@ -168,6 +157,12 @@ public:
*/ */
void exportLayout(KConfigGroup &config, QList<Containment*> containments); 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;
public Q_SLOTS: public Q_SLOTS:
/** /**
* Load applet layout from a config file. The results will be added to the * 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); 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 ContainmentPrivate::containmentActionsConfig() const
{ {
KConfigGroup cfg = KConfigGroup(q->corona()->config(), "ActionPlugins"); KConfigGroup cfg = KConfigGroup(q->corona()->config(), "ActionPlugins");

View File

@ -49,7 +49,6 @@ public:
: q(c), : q(c),
formFactor(Types::Planar), formFactor(Types::Planar),
location(Types::Floating), location(Types::Floating),
screen(-1), // no screen
lastScreen(-1), // never had a screen lastScreen(-1), // never had a screen
type(Plasma::Types::NoContainmentType), type(Plasma::Types::NoContainmentType),
drawWallpaper(false) drawWallpaper(false)
@ -67,7 +66,6 @@ public:
void triggerShowAddWidgets(); void triggerShowAddWidgets();
void checkStatus(Plasma::Types::ItemStatus status); void checkStatus(Plasma::Types::ItemStatus status);
void setScreen(int newScreen);
/** /**
* Called when constraints have been updated on this containment to provide * Called when constraints have been updated on this containment to provide
@ -103,7 +101,6 @@ public:
QSet <Applet *> loadingApplets; QSet <Applet *> loadingApplets;
QString wallpaper; QString wallpaper;
QHash<QString, ContainmentActions*> localActionPlugins; QHash<QString, ContainmentActions*> localActionPlugins;
int screen;
int lastScreen; int lastScreen;
QString activityId; QString activityId;
Types::ContainmentType type; 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 //FIXME:we need a way to reparent to *NO* graphics item, but this makes Qt crash
oldGraphicObject->setParent(containment.data()); oldGraphicObject->setParent(containment.data());
} }
containment.data()->reactToScreenChange();
} }
containment = cont; containment = cont;
@ -88,6 +89,7 @@ void PlasmaQuickViewPrivate::setContainment(Plasma::Containment *cont)
emit q->containmentChanged(); emit q->containmentChanged();
if (cont) { if (cont) {
cont->reactToScreenChange();
QObject::connect(cont, &Plasma::Containment::locationChanged, QObject::connect(cont, &Plasma::Containment::locationChanged,
q, &PlasmaQuickView::locationChanged); q, &PlasmaQuickView::locationChanged);
QObject::connect(cont, &Plasma::Containment::formFactorChanged, QObject::connect(cont, &Plasma::Containment::formFactorChanged,
@ -168,7 +170,7 @@ PlasmaQuickView::PlasmaQuickView(Plasma::Corona *corona, QWindow *parent)
setColor(Qt::transparent); setColor(Qt::transparent);
QObject::connect(screen(), &QScreen::virtualGeometryChanged, QObject::connect(screen(), &QScreen::geometryChanged,
this, &PlasmaQuickView::screenGeometryChanged); this, &PlasmaQuickView::screenGeometryChanged);
if (!corona->package().isValid()) { if (!corona->package().isValid()) {

View File

@ -198,7 +198,8 @@ Plasma::Applet *ContainmentInterface::addApplet(const QString &plugin, const QVa
emit appletAdded(appletGraphicObject, pos.x(), pos.y()); emit appletAdded(appletGraphicObject, pos.x(), pos.y());
emit appletsChanged(); emit appletsChanged();
} } else
blockSignals(false);
return applet; return applet;
} }

View File

@ -42,34 +42,23 @@
Activity::Activity(const QString &id, Plasma::Corona *parent) Activity::Activity(const QString &id, Plasma::Corona *parent)
: QObject(parent), : QObject(parent),
m_id(id), 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_info(new KActivities::Info(id, this)),
m_activityConsumer(new KActivities::Consumer(this)), m_activityConsumer(new KActivities::Consumer(this)),
m_corona(parent),
m_current(false) m_current(false)
{ {
m_name = m_info->name(); m_name = m_info->name();
m_icon = m_info->icon(); m_icon = m_info->icon();
connect(m_info, SIGNAL(infoChanged()), this, SLOT(activityChanged())); connect(m_info, SIGNAL(infoChanged()), this, SLOT(activityChanged()));
connect(m_info, SIGNAL(stateChanged(KActivities::Info::State)), this, SLOT(activityStateChanged(KActivities::Info::State))); connect(m_info, SIGNAL(stateChanged(KActivities::Info::State)), this, SIGNAL(stateChanged()));
connect(m_info, SIGNAL(started()), this, SLOT(opened())); connect(m_info, SIGNAL(started()), this, SIGNAL(opened()));
connect(m_info, SIGNAL(stopped()), this, SLOT(closed())); connect(m_info, SIGNAL(stopped()), this, SIGNAL(closed()));
connect(m_info, SIGNAL(removed()), this, SLOT(removed())); 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())); connect(m_activityConsumer, SIGNAL(currentActivityChanged(QString)), this, SLOT(checkIfCurrent()));
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() Activity::~Activity()
@ -82,12 +71,6 @@ void Activity::activityChanged()
setIcon(m_info->icon()); setIcon(m_info->icon());
} }
void Activity::activityStateChanged(KActivities::Info::State state)
{
Q_UNUSED(state)
emit stateChanged();
}
QString Activity::id() QString Activity::id()
{ {
return m_id; return m_id;
@ -132,227 +115,39 @@ void Activity::remove()
KActivities::Controller().removeActivity(m_id); 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; const QString name = "activities/" + m_id;
QFile::remove(QStandardPaths::writableLocation(QStandardPaths::DataLocation)+QChar('/')+name); 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
foreach (Plasma::Containment *c, m_corona->containments()) {
if ((c->containmentType() == Plasma::Types::DesktopContainment ||
c->containmentType() == Plasma::Types::CustomContainment) &&
c->activity().isEmpty() &&
m_containments.key(c, -2) == -2) {
containment = c;
containment->setScreen(screen);
break;
}
}
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");
}
//we don't want to steal contaiments from other activities
if (!containment) {
// we failed to even get the default; we're screwed.
Q_ASSERT(false);
return 0;
}
if (!containment->activity().isEmpty() &&
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() void Activity::activate()
{ {
KActivities::Controller().setCurrentActivity(m_id); 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) void Activity::setName(const QString &name)
{ {
if (m_name == name) {
return;
}
m_name = name; m_name = name;
} }
void Activity::setIcon(const QString &icon) void Activity::setIcon(const QString &icon)
{ {
if (m_icon == icon) {
return;
}
m_icon = 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() void Activity::close()
{ {
KActivities::Controller().stopActivity(m_id); KActivities::Controller().stopActivity(m_id);
} }
void Activity::closed() KConfigGroup Activity::config() const
{ {
const QString name = "activities/" + m_id; const QString name = "activities/" + m_id;
KConfig external(name, KConfig::SimpleConfig, QStandardPaths::GenericDataLocation); KConfig external(name, KConfig::SimpleConfig, QStandardPaths::GenericDataLocation);
//passing an empty string for the group name turns a kconfig into a kconfiggroup //passing an empty string for the group name turns a kconfig into a kconfiggroup
KConfigGroup group = external.group(QString()); return 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::replaceContainment(Plasma::Containment* containment)
{
insertContainment(containment, true);
}
void Activity::insertContainment(Plasma::Containment* cont, bool force)
{
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 (!force && 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);
QHash<int, Plasma::Containment*>::iterator i;
for (i = m_containments.begin(); i != m_containments.end(); ++i) {
Plasma::Containment *cont = i.value();
if (cont == deletedCont) {
m_containments.remove(i.key());
break;
}
}
} }
void Activity::open() void Activity::open()
@ -360,38 +155,6 @@ void Activity::open()
KActivities::Controller().startActivity(m_id); 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) void Activity::setDefaultPlugin(const QString &plugin)
{ {
m_plugin = plugin; m_plugin = plugin;

View File

@ -24,6 +24,7 @@
#include <QHash> #include <QHash>
#include <kactivities/info.h> #include <kactivities/info.h>
#include <kconfiggroup.h>
class QSize; class QSize;
class QString; class QString;
@ -81,22 +82,6 @@ public:
*/ */
KActivities::Info::State state(); 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 * set the plugin to use when creating new containments
*/ */
@ -107,11 +92,17 @@ public:
*/ */
const KActivities::Info * info() const; const KActivities::Info * info() const;
KConfigGroup config() const;
Q_SIGNALS: Q_SIGNALS:
void infoChanged(); void infoChanged();
void stateChanged(); void stateChanged();
void currentStatusChanged(); void currentStatusChanged();
void removed();
void opened();
void closed();
public Q_SLOTS: public Q_SLOTS:
void setName(const QString &name); void setName(const QString &name);
void setIcon(const QString &icon); void setIcon(const QString &icon);
@ -136,34 +127,18 @@ public Q_SLOTS:
*/ */
void open(); void open();
/**
* forcibly insert a containment, replacing the one on its screen/desktop
*/
void replaceContainment(Plasma::Containment* containment);
private Q_SLOTS: private Q_SLOTS:
void containmentDestroyed(QObject *object);
void activityChanged(); void activityChanged();
void activityStateChanged(KActivities::Info::State);
void checkIfCurrent(); void checkIfCurrent();
void cleanupActivity();
void removed();
void opened();
void closed();
private: private:
void insertContainment(Plasma::Containment* cont, bool force=false);
void insertContainment(Plasma::Containment* containment, int screen);
void checkScreens();
QString m_id; QString m_id;
QString m_name; QString m_name;
QString m_icon; QString m_icon;
QString m_plugin; QString m_plugin;
QHash<int, Plasma::Containment*> m_containments;
KActivities::Info *m_info; KActivities::Info *m_info;
KActivities::Consumer *m_activityConsumer; KActivities::Consumer *m_activityConsumer;
Plasma::Corona *m_corona;
bool m_current; bool m_current;
}; };

View File

@ -40,6 +40,8 @@ PanelConfigView::PanelConfigView(Plasma::Containment *containment, PanelView *pa
m_containment(containment), m_containment(containment),
m_panelView(panelView) m_panelView(panelView)
{ {
setScreen(panelView->screen());
connect(panelView, &PanelView::screenChanged, [=](QScreen *screen){setScreen(screen); syncGeometry();});
setFlags(Qt::FramelessWindowHint); setFlags(Qt::FramelessWindowHint);

View File

@ -35,7 +35,7 @@ class PanelView : public PlasmaQuickView
Q_PROPERTY(int length READ length WRITE setLength NOTIFY lengthChanged) Q_PROPERTY(int length READ length WRITE setLength NOTIFY lengthChanged)
Q_PROPERTY(int maximumLength READ maximumLength WRITE setMaximumLength NOTIFY maximumLengthChanged) Q_PROPERTY(int maximumLength READ maximumLength WRITE setMaximumLength NOTIFY maximumLengthChanged)
Q_PROPERTY(int minimumLength READ minimumLength WRITE setMinimumLength NOTIFY minimumLengthChanged) Q_PROPERTY(int minimumLength READ minimumLength WRITE setMinimumLength NOTIFY minimumLengthChanged)
Q_PROPERTY(QScreen *screen READ screen NOTIFY screenChanged) Q_PROPERTY(QScreen *screen READ screen WRITE setScreen NOTIFY screenChanged)
Q_PROPERTY(VisibilityMode visibilityMode READ visibilityMode WRITE setVisibilityMode) Q_PROPERTY(VisibilityMode visibilityMode READ visibilityMode WRITE setVisibilityMode)
public: public:

View File

@ -82,13 +82,6 @@ int Containment::screen() const
return d->containment.data()->screen(); return d->containment.data()->screen();
} }
void Containment::setScreen(int screen)
{
if (d->containment) {
d->containment.data()->setScreen(screen);
}
}
QString Containment::wallpaperPlugin() const QString Containment::wallpaperPlugin() const
{ {
return d->wallpaperPlugin; return d->wallpaperPlugin;

View File

@ -37,6 +37,7 @@ namespace WorkspaceScripting
class Containment : public Applet class Containment : public Applet
{ {
Q_OBJECT Q_OBJECT
///FIXME: add NOTIFY
Q_PROPERTY(QString version READ version) Q_PROPERTY(QString version READ version)
Q_PROPERTY(QStringList configKeys READ configKeys) Q_PROPERTY(QStringList configKeys READ configKeys)
Q_PROPERTY(QStringList configGroups READ configGroups) Q_PROPERTY(QStringList configGroups READ configGroups)
@ -50,7 +51,7 @@ class Containment : public Applet
Q_PROPERTY(QString type READ type) Q_PROPERTY(QString type READ type)
Q_PROPERTY(QString formFactor READ formFactor) Q_PROPERTY(QString formFactor READ formFactor)
Q_PROPERTY(QList<int> widgetIds READ widgetIds) 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) Q_PROPERTY(int id READ id)
public: public:
@ -66,7 +67,6 @@ public:
void setName(const QString &name); void setName(const QString &name);
int screen() const; int screen() const;
void setScreen(int screen);
Plasma::Applet *applet() const; Plasma::Applet *applet() const;
Plasma::Containment *containment() const; Plasma::Containment *containment() const;

View File

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

View File

@ -140,7 +140,6 @@ QScriptValue ScriptEngine::createContainment(const QString &type, const QString
// some defaults // some defaults
c->setFormFactor(Plasma::Types::Horizontal); c->setFormFactor(Plasma::Types::Horizontal);
c->setLocation(Plasma::Types::TopEdge); c->setLocation(Plasma::Types::TopEdge);
c->setScreen(env->defaultPanelScreen());
} }
c->updateConstraints(Plasma::Types::AllConstraints | Plasma::Types::StartupCompletedConstraint); c->updateConstraints(Plasma::Types::AllConstraints | Plasma::Types::StartupCompletedConstraint);
c->flushPendingConstraintsEvents(); c->flushPendingConstraintsEvents();

View File

@ -72,12 +72,12 @@ public:
QList <DesktopView *> views; QList <DesktopView *> views;
KActivities::Controller *activityController; KActivities::Controller *activityController;
KActivities::Consumer *activityConsumer; KActivities::Consumer *activityConsumer;
QHash <Plasma::Containment *, PanelView *> panelViews; QHash <const Plasma::Containment *, PanelView *> panelViews;
KConfigGroup desktopDefaultsConfig; KConfigGroup desktopDefaultsConfig;
WorkspaceScripting::DesktopScriptEngine * scriptEngine; WorkspaceScripting::DesktopScriptEngine * scriptEngine;
QList<Plasma::Containment *> waitingPanels; QList<Plasma::Containment *> waitingPanels;
QSet<Plasma::Containment *> loadingDesktops;
QHash<QString, Activity*> activities; QHash<QString, Activity*> activities;
QHash<QString, QHash<int, Plasma::Containment*> > desktopContainments;
QTimer *waitingPanelsTimer; QTimer *waitingPanelsTimer;
QAction *addPanelAction; QAction *addPanelAction;
QMenu *addPanelsMenu; QMenu *addPanelsMenu;
@ -103,15 +103,8 @@ ShellCorona::ShellCorona(QObject *parent)
connect(&d->appConfigSyncTimer, &QTimer::timeout, connect(&d->appConfigSyncTimer, &QTimer::timeout,
this, &ShellCorona::syncAppConfig); this, &ShellCorona::syncAppConfig);
connect(d->desktopWidget, &QDesktopWidget::resized,
this, &ShellCorona::screenResized );
connect(d->desktopWidget, &QDesktopWidget::workAreaResized,
this, &ShellCorona::workAreaResized);
connect(this, &ShellCorona::containmentAdded, connect(this, &ShellCorona::containmentAdded,
this, &ShellCorona::handleContainmentAdded); this, &ShellCorona::handleContainmentAdded);
connect(this, &ShellCorona::screenOwnerChanged,
this, &ShellCorona::updateScreenOwner);
d->scriptEngine = new WorkspaceScripting::DesktopScriptEngine(this, true); d->scriptEngine = new WorkspaceScripting::DesktopScriptEngine(this, true);
@ -166,13 +159,15 @@ void ShellCorona::setShell(const QString &shell)
unload(); unload();
d->shell = shell; d->shell = shell;
KConfigGroup config(KSharedConfig::openConfig(), "General");
Plasma::Package package = Plasma::PluginLoader::self()->loadPackage("Plasma/Shell"); Plasma::Package package = Plasma::PluginLoader::self()->loadPackage("Plasma/Shell");
package.setPath(shell); package.setPath(shell);
setPackage(package); setPackage(package);
load(); if (d->activityConsumer->serviceStatus() == KActivities::Consumer::Unknown) {
//TODO: panel views should be synced here: either creating views for panels without, or deleting views for panels that don't have one anymore connect(d->activityConsumer, SIGNAL(serviceStatusChanged(Consumer::ServiceStatus)), SLOT(load()), Qt::UniqueConnection);
} else {
load();
}
} }
QString ShellCorona::shell() const QString ShellCorona::shell() const
@ -182,16 +177,36 @@ QString ShellCorona::shell() const
void ShellCorona::load() 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"); loadLayout("plasma-" + d->shell + "-appletsrc");
checkActivities();
if (containments().isEmpty()) { if (containments().isEmpty()) {
loadDefaultLayout(); loadDefaultLayout();
foreach(Plasma::Containment* containment, containments()) {
containment->setActivity(d->activityConsumer->currentActivity());
}
} }
processUpdateScripts(); 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();
}
insertContainment(containment->activity(), screen, containment);
}
}
for (QScreen *screen : QGuiApplication::screens()) { for (QScreen *screen : QGuiApplication::screens()) {
screenAdded(screen); screenAdded(screen);
@ -199,13 +214,14 @@ void ShellCorona::load()
connect(qApp, &QGuiApplication::screenAdded, connect(qApp, &QGuiApplication::screenAdded,
this, &ShellCorona::screenAdded); this, &ShellCorona::screenAdded);
checkScreens(); if (!d->waitingPanels.isEmpty()) {
d->waitingPanelsTimer->start();
}
} }
void ShellCorona::unload() void ShellCorona::unload()
{ {
if (d->shell.isEmpty()) return; if (d->shell.isEmpty()) return;
qDeleteAll(containments()); qDeleteAll(containments());
} }
@ -239,92 +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() KActivities::Controller *ShellCorona::activityController()
{ {
return d->activityController; return d->activityController;
} }
void ShellCorona::checkScreens(bool signalWhenExists)
{
// quick sanity check to ensure we have containments for each screen
int num = numScreens();
for (int i = 0; i < num; ++i) {
checkScreen(i, signalWhenExists);
}
}
void ShellCorona::checkScreen(int screen, bool signalWhenExists)
{
// signalWhenExists is there to allow PlasmaApp to know when to create views
// it does this only on containment addition, but in the case of a screen being
// added and the containment already existing for that screen, no signal is emitted
// and so PlasmaApp does not know that it needs to create a view for it. to avoid
// taking care of that case in PlasmaApp (which would duplicate some of the code below,
// ShellCorona will, when signalWhenExists is true, emit a containmentAdded signal
// even if the containment actually existed prior to this method being called.
//
//note: the signal actually triggers view creation only for panels, atm.
//desktop views are created in response to containment's screenChanged signal instead, which is
//buggy (sometimes the containment thinks it's already on the screen, so no view is created)
//TODO: restore activities
Activity *currentActivity = activity(d->activityController->currentActivity());
//ensure the desktop(s) have a containment and view
checkDesktop(currentActivity, signalWhenExists, screen);
//ensure the panels get views too
if (signalWhenExists) {
foreach (Plasma::Containment * c, containments()) {
if (c->screen() != screen) {
continue;
}
Plasma::Types::ContainmentType t = c->containmentType();
if (t == Plasma::Types::PanelContainment ||
t == Plasma::Types::CustomPanelContainment) {
emit containmentAdded(c);
}
}
}
}
void ShellCorona::checkDesktop(Activity *activity, bool signalWhenExists, int screen)
{
Plasma::Containment *c = activity->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();
if (signalWhenExists) {
emit containmentAdded(c);
}
}
int ShellCorona::numScreens() const int ShellCorona::numScreens() const
{ {
return d->desktopWidget->screenCount(); return d->desktopWidget->screenCount();
@ -353,54 +288,68 @@ PanelView *ShellCorona::panelView(Plasma::Containment *containment) const
///// SLOTS ///// 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) void ShellCorona::screenAdded(QScreen *screen)
{ {
DesktopView *view = new DesktopView(this, screen); DesktopView *view = new DesktopView(this, screen);
d->views << view; const QString currentActivity = d->activityController->currentActivity();
view->show();
if (!d->views.isEmpty() && screen == QGuiApplication::primaryScreen()) {
DesktopView* oldPrimaryView = d->views.first();
QScreen* oldPrimaryScreen = oldPrimaryView->screen();
//move any panels that were preivously on the old primary screen to the new primary screen
foreach (PanelView *panelView, d->panelViews) {
if (oldPrimaryScreen==panelView->screen())
panelView->setScreen(screen);
}
Plasma::Containment* primaryContainment = oldPrimaryView->containment();
oldPrimaryView->setContainment(0);
view->setContainment(primaryContainment);
d->views.prepend(view);
view = oldPrimaryView;
} else {
d->views.append(view);
}
int screenNum = d->views.count()-1;
Plasma::Containment *containment = d->desktopContainments[currentActivity][screenNum];
if(!containment) {
containment = createContainmentForActivity(currentActivity, screenNum);
}
view->setContainment(containment);
connect(screen, SIGNAL(destroyed(QObject*)), SLOT(screenRemoved(QObject*))); connect(screen, SIGNAL(destroyed(QObject*)), SLOT(screenRemoved(QObject*)));
view->show();
}
Plasma::Containment* ShellCorona::createContainmentForActivity(const QString& activity, int screenNum)
{
Plasma::Containment* containment = createContainment(d->desktopDefaultsConfig.readEntry("Containment", "org.kde.desktopcontainment"));
containment->setActivity(activity);
insertContainment(activity, screenNum, containment);
return containment;
} }
void ShellCorona::screenRemoved(QObject *screen) void ShellCorona::screenRemoved(QObject *screen)
{ {
qDebug() << "screen removed " << qobject_cast<QScreen*>(screen)->name();
//desktop containments
for (auto i = d->views.begin(); i != d->views.end() ; i++) { for (auto i = d->views.begin(); i != d->views.end() ; i++) {
if ((*i)->screen() == screen) { if ((*i)->screen() == screen) {
(*i)->deleteLater(); (*i)->deleteLater();
d->views.erase(i); d->views.erase(i);
(*i)->containment()->reactToScreenChange();
break; break;
} }
} }
}
void ShellCorona::checkLoadingDesktopsComplete() //move all panels on a deleted screen to the primary screen
{ foreach (PanelView *view, d->panelViews) {
Plasma::Containment *c = qobject_cast<Plasma::Containment *>(sender()); view->setScreen(QGuiApplication::primaryScreen());
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();
} }
} }
@ -408,60 +357,20 @@ void ShellCorona::createWaitingPanels()
{ {
foreach (Plasma::Containment *cont, d->waitingPanels) { foreach (Plasma::Containment *cont, d->waitingPanels) {
d->panelViews[cont] = new PanelView(this); d->panelViews[cont] = new PanelView(this);
//keep screen suggestions within bounds of screens we actually have
int screen = qBound(0, cont->lastScreen(), QGuiApplication::screens().size() -1);
d->panelViews[cont]->setScreen(QGuiApplication::screens()[screen]);
d->panelViews[cont]->setContainment(cont); d->panelViews[cont]->setContainment(cont);
} }
d->waitingPanels.clear(); 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) void ShellCorona::handleContainmentAdded(Plasma::Containment* c)
{ {
connect(c, &Plasma::Containment::showAddWidgetsInterface, connect(c, &Plasma::Containment::showAddWidgetsInterface,
this, &ShellCorona::toggleWidgetExplorer); this, &ShellCorona::toggleWidgetExplorer);
connect(c, &QObject::destroyed, [=] (QObject *o) {
d->loadingDesktops.remove(static_cast<Plasma::Containment *>(o));
});
} }
void ShellCorona::toggleWidgetExplorer() void ShellCorona::toggleWidgetExplorer()
@ -510,13 +419,11 @@ void ShellCorona::setDashboardShown(bool show)
void ShellCorona::checkActivities() void ShellCorona::checkActivities()
{ {
qDebug() << "containments to start with" << containments().count();
KActivities::Consumer::ServiceStatus status = d->activityController->serviceStatus(); KActivities::Consumer::ServiceStatus status = d->activityController->serviceStatus();
//qDebug() << "$%$%$#%$%$%Status:" << status; //qDebug() << "$%$%$#%$%$%Status:" << status;
if (status != KActivities::Consumer::Running) { if (status != KActivities::Consumer::Running) {
//panic and give up - better than causing a mess //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; return;
} }
@ -542,11 +449,14 @@ void ShellCorona::checkActivities()
void ShellCorona::currentActivityChanged(const QString &newActivity) void ShellCorona::currentActivityChanged(const QString &newActivity)
{ {
Activity *act = activity(newActivity); qDebug() << "Activity changed:" << newActivity;
qDebug() << "Activity changed:" << newActivity << act;
if (act) { for(int i = 0; i<d->views.count(); ++i) {
act->ensureActive(); Plasma::Containment* c = d->desktopContainments[newActivity][i];
if(!c) {
c = createContainmentForActivity(newActivity, i);
}
d->views[i]->setContainment(c);
} }
} }
@ -559,9 +469,6 @@ void ShellCorona::activityAdded(const QString &id)
} }
Activity *a = new Activity(id, this); Activity *a = new Activity(id, this);
if (a->isCurrent()) {
a->ensureActive();
}
d->activities.insert(id, a); d->activities.insert(id, a);
} }
@ -637,7 +544,7 @@ void ShellCorona::addPanel(const QString &plugin)
QList<Plasma::Types::Location> availableLocations; QList<Plasma::Types::Location> availableLocations;
availableLocations << Plasma::Types::LeftEdge << Plasma::Types::TopEdge << Plasma::Types::RightEdge << Plasma::Types::BottomEdge; availableLocations << Plasma::Types::LeftEdge << Plasma::Types::TopEdge << Plasma::Types::RightEdge << Plasma::Types::BottomEdge;
foreach (Plasma::Containment *cont, d->panelViews.keys()) { foreach (const Plasma::Containment *cont, d->panelViews.keys()) {
availableLocations.removeAll(cont->location()); availableLocations.removeAll(cont->location());
} }
Plasma::Types::Location loc; Plasma::Types::Location loc;
@ -656,8 +563,6 @@ void ShellCorona::addPanel(const QString &plugin)
panel->setFormFactor(Plasma::Types::Horizontal); panel->setFormFactor(Plasma::Types::Horizontal);
break; break;
} }
panel->setScreen(0);
d->waitingPanels << panel; d->waitingPanels << panel;
d->waitingPanelsTimer->start(); d->waitingPanelsTimer->start();
@ -673,6 +578,63 @@ void ShellCorona::printScriptMessage(const QString &message)
qDebug() << message; qDebug() << message;
} }
int ShellCorona::screenForContainment(const Plasma::Containment *containment) const
{
QScreen* s = nullptr;
for (int i=0; i<d->views.size(); i++) {
if (d->views[i]->containment() == containment) {
s = d->views[i]->screen();
}
}
if(!s) {
PanelView *view = d->panelViews[containment];
if (view) {
s = view->screen();
}
}
return s? qApp->screens().indexOf(s) : -1;
}
void ShellCorona::activityOpened()
{
Activity* activity = qobject_cast<Activity*>(sender());
QList<Plasma::Containment*> cs = importLayout(activity->config());
for(Plasma::Containment *containment : cs) {
insertContainment(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;
//when a containment gets deleted update our map of containments
connect(containment, &QObject::destroyed, [=](QObject *obj) {
auto containment = qobject_cast<Plasma::Containment*>(obj);
d->desktopContainments[containment->activity()].remove(containment->lastScreen());
});
}
// Desktop corona handler // Desktop corona handler

View File

@ -54,17 +54,6 @@ public:
KSharedConfig::Ptr applicationConfig(); KSharedConfig::Ptr applicationConfig();
WorkspaceScripting::DesktopScriptEngine * scriptEngine() const; WorkspaceScripting::DesktopScriptEngine * scriptEngine() const;
/**
* Ensures we have the necessary containments for every screen
*/
void checkScreens(bool signalWhenExists = false);
/**
* Ensures we have the necessary containments for the given screen
*/
void checkScreen(int screen, bool signalWhenExists = false);
void checkDesktop(Activity *activity, bool signalWhenExists, int screen);
int numScreens() const; int numScreens() const;
QRect screenGeometry(int id) const; QRect screenGeometry(int id) const;
@ -73,8 +62,6 @@ public:
PanelView *panelView(Plasma::Containment *containment) const; PanelView *panelView(Plasma::Containment *containment) const;
Activity* activity(const QString &id);
KActivities::Controller *activityController(); KActivities::Controller *activityController();
public Q_SLOTS: public Q_SLOTS:
@ -94,13 +81,8 @@ public Q_SLOTS:
QString shell() const; QString shell() const;
protected Q_SLOTS: protected Q_SLOTS:
void screenCountChanged(int newCount);
void screenResized(int screen);
void workAreaResized(int screen);
void screenAdded(QScreen *screen); void screenAdded(QScreen *screen);
void screenRemoved(QObject *screen); void screenRemoved(QObject *screen);
void updateScreenOwner(int wasScreen, int isScreen, Plasma::Containment *containment);
void printScriptError(const QString &error); void printScriptError(const QString &error);
void printScriptMessage(const QString &message); void printScriptMessage(const QString &message);
@ -125,8 +107,9 @@ protected Q_SLOTS:
*/ */
void processUpdateScripts(); void processUpdateScripts();
int screenForContainment(const Plasma::Containment *containment) const;
private Q_SLOTS: private Q_SLOTS:
void checkLoadingDesktopsComplete();
void createWaitingPanels(); void createWaitingPanels();
void handleContainmentAdded(Plasma::Containment *c); void handleContainmentAdded(Plasma::Containment *c);
void toggleWidgetExplorer(); void toggleWidgetExplorer();
@ -142,7 +125,17 @@ private Q_SLOTS:
void addPanel(QAction *action); void addPanel(QAction *action);
void addPanel(const QString &plugin); void addPanel(const QString &plugin);
void activityOpened();
void activityClosed();
void activityRemoved();
private: private:
/**
* @returns a new containment associated with the specified @p activity and @p screen.
*/
Plasma::Containment* createContainmentForActivity(const QString& activity, int screenNum);
void insertContainment(const QString &activity, int screenNum, Plasma::Containment *containment);
class Private; class Private;
const QScopedPointer<Private> d; const QScopedPointer<Private> d;
}; };

View File

@ -148,8 +148,10 @@ void ShellManager::deregisterHandler(QObject * handler)
handler->disconnect(this); handler->disconnect(this);
} }
if (d->currentHandler == handler) if (d->currentHandler == handler) {
d->currentHandler = nullptr; d->currentHandler = nullptr;
updateShell();
}
} }
void ShellManager::requestShellUpdate() void ShellManager::requestShellUpdate()
@ -202,7 +204,6 @@ void ShellManager::updateShell()
d->currentHandler = handler; d->currentHandler = handler;
d->currentHandler->setProperty("loaded", true); d->currentHandler->setProperty("loaded", true);
// d->corona->setShell(d->currentHandler->property("shell").toString());
emit shellChanged(d->currentHandler->property("shell").toString()); emit shellChanged(d->currentHandler->property("shell").toString());
} }

View File

@ -22,7 +22,15 @@
#include <QObject> #include <QObject>
/**
* ShellManager creates a ShellCorona instance and manages it.
*
* Shell manager loads "handlers" from QML files which suggests which shell
* corona should currently be active.
* For example switching between tablet and desktop shells on hardware changes.
*
* This class also provides crash handling.
*/
class ShellManager: public QObject { class ShellManager: public QObject {
Q_OBJECT Q_OBJECT