Note that the coding style is quite off and it messes up the existing style in all those files; can you please run astyle on it before merging so it can all be the same?
Cheers -- Martin Klapetek | KDE Developer On Thu, May 1, 2014 at 3:42 AM, Aleix Pol <aleix...@kde.org> wrote: > Git commit 168c15a463746cf9039f2f9e188b1827ed809f97 by Aleix Pol. > Committed on 01/05/2014 at 01:41. > Pushed by apol into branch 'plasmashell+libkscreen'. > > Adopt libkscreen to get information of the screens > > Qt subsystem has deficiencies on their approximation to multiple > screens. [1] > This patch adopts libkscreen to figure out screen additions and primary > modifications. > I'm not merging to master yet as I'm experiencing some issues but it's > already far more comfortable to work with than QGuiApplication::screens(). > > [1] https://bugreports.qt-project.org/browse/QTBUG-38404 > > CCMAIL: plasma-devel@kde.org > > M +1 -0 CMakeLists.txt > M +1 -0 shell/CMakeLists.txt > M +151 -42 shell/shellcorona.cpp > M +11 -2 shell/shellcorona.h > > > http://commits.kde.org/plasma-workspace/168c15a463746cf9039f2f9e188b1827ed809f97 > > diff --git a/CMakeLists.txt b/CMakeLists.txt > index 31e29b2..8078b0b 100644 > --- a/CMakeLists.txt > +++ b/CMakeLists.txt > @@ -13,6 +13,7 @@ find_package(KF5 REQUIRED COMPONENTS > IdleTime ThreadWeaver Declarative PlasmaQuick WebKit > KDELibs4Support) > > find_package(KF5 REQUIRED COMPONENTS SysGuard) > +find_package(KF5 REQUIRED COMPONENTS Screen) > find_package(KWinDBusInterface CONFIG REQUIRED) > > include(KDEInstallDirs) > diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt > index 5f58d8c..5b2a290 100644 > --- a/shell/CMakeLists.txt > +++ b/shell/CMakeLists.txt > @@ -87,6 +87,7 @@ target_link_libraries(plasma-shell > KF5::Activities > KF5::GlobalAccel > KF5::DBusAddons > + KF5::Screen > ) > if (TARGET KF5::TextEditor) > target_link_libraries(plasma-shell KF5::TextEditor) > diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp > index 2f82132..0670b43 100644 > --- a/shell/shellcorona.cpp > +++ b/shell/shellcorona.cpp > @@ -42,6 +42,9 @@ > #include <KAuthorized> > #include <KWindowSystem> > > +#include <KScreen/Config> > +#include <kscreen/configmonitor.h> > + > #include "config-ktexteditor.h" // HAVE_KTEXTEDITOR > > > @@ -59,8 +62,6 @@ > > #include "plasmashelladaptor.h" > > - > - > static const int s_configSyncDelay = 10000; // 10 seconds > > class ShellCorona::Private { > @@ -70,7 +71,8 @@ public: > activityController(new KActivities::Controller(q)), > activityConsumer(new KActivities::Consumer(q)), > addPanelAction(nullptr), > - addPanelsMenu(nullptr) > + addPanelsMenu(nullptr), > + screenConfiguration(nullptr) > { > appConfigSyncTimer.setSingleShot(true); > appConfigSyncTimer.setInterval(s_configSyncDelay); > @@ -99,10 +101,20 @@ public: > QWeakPointer<InteractiveConsole> console; > #endif > > + KScreen::Config* screenConfiguration; > QTimer waitingPanelsTimer; > QTimer appConfigSyncTimer; > }; > > +static QScreen* outputToScreen(KScreen::Output* output) > +{ > + foreach(QScreen* screen, QGuiApplication::screens()) { > + if(screen->name() == output->name()) { > + return screen; > + } > + } > + return 0; > +} > > WorkspaceScripting::DesktopScriptEngine * ShellCorona::scriptEngine() > const > { > @@ -233,6 +245,20 @@ QString ShellCorona::shell() const > return d->shell; > } > > +static QList<KScreen::Output*> sortOutputs(const QHash<int, > KScreen::Output*> &outputs) > +{ > + QList<KScreen::Output*> ret; > + foreach(KScreen::Output* output, outputs) { > + if(!output->isEnabled()) > + ; > + else if(output->isPrimary()) > + ret.prepend(output); > + else > + ret.append(output); > + } > + return ret; > +} > + > void ShellCorona::load() > { > if (d->shell.isEmpty() || > @@ -269,17 +295,73 @@ void ShellCorona::load() > } > } > > - for (QScreen *screen : QGuiApplication::screens()) { > - screenAdded(screen); > + d->screenConfiguration = KScreen::Config::current(); > + KScreen::ConfigMonitor::instance()->addConfig(d->screenConfiguration); > + for (KScreen::Output *output : > sortOutputs(d->screenConfiguration->connectedOutputs())) { > + outputAdded(output); > } > - connect(qApp, &QGuiApplication::screenAdded, > - this, &ShellCorona::screenAdded); > + connect(d->screenConfiguration, &KScreen::Config::outputAdded, > + this, &ShellCorona::outputAdded); > + connect(d->screenConfiguration, > &KScreen::Config::primaryOutputChanged, > + this, &ShellCorona::primaryOutputChanged); > > if (!d->waitingPanels.isEmpty()) { > d->waitingPanelsTimer.start(); > } > } > > +void ShellCorona::primaryOutputChanged() > +{ > + KScreen::Config* current = d->screenConfiguration; > + QScreen* newPrimary = outputToScreen(current->primaryOutput()); > + int i=0; > + foreach(DesktopView* view, d->views) { > + if(view->screen() == newPrimary) > + break; > + i++; > + } > + QScreen* oldPrimary = d->views.first()->screen(); > + qDebug() << "primary changed!" << oldPrimary->name() << > newPrimary->name() << i; > +// > +// //if it was not found, it means that outputAdded hasn't been > called yet > + if (i>=d->views.count() || i==0) > + return; > +// > + Q_ASSERT(oldPrimary != newPrimary); > + Q_ASSERT(d->views[0]->screen() != d->views[i]->screen()); > + Q_ASSERT(d->views[0]->screen() == oldPrimary); > + Q_ASSERT(d->views[0]->screen() != newPrimary); > + Q_ASSERT(d->views[0]->geometry() == oldPrimary->geometry()); > + qDebug() << "adapting" << newPrimary->geometry() << > d->views[0]->containment()->wallpaper() > + << oldPrimary->geometry() << > d->views[i]->containment()->wallpaper() << i; > + > + d->views[0]->setScreen(newPrimary); > + d->views[i]->setScreen(oldPrimary); > + screenInvariants(); > + > + QList<Plasma::Containment*> panels; > + foreach(PanelView* panel, d->panelViews) { > + if(panel->screen() == oldPrimary) > + panel->setScreen(newPrimary); > + else if(panel->screen() == newPrimary) > + panel->setScreen(oldPrimary); > + } > +} > + > +void ShellCorona::screenInvariants() > +{ > + QScreen* s = outputToScreen(d->screenConfiguration->primaryOutput()); > + Q_ASSERT(d->views[0]->screen()->name() == s->name()); > + Q_ASSERT(d->views[0]->geometry() == s->geometry()); > + > + QSet<QScreen*> screens; > + foreach(DesktopView* view, d->views) { > + Q_ASSERT(!screens.contains(view->screen())); > + screens.insert(view->screen()); > + } > +} > + > + > void ShellCorona::unload() > { > if (d->shell.isEmpty()) { > @@ -356,7 +438,7 @@ QRegion ShellCorona::availableScreenRegion(int id) > const > > if (view) { > QRegion r = view->geometry(); > - foreach (PanelView *v, d->panelViews.values()) { > + foreach (PanelView *v, d->panelViews) { > if (v->containment()->screen() == id && v->visibilityMode() > != PanelView::AutoHide) { > r -= v->geometry(); > } > @@ -375,7 +457,7 @@ QRect ShellCorona::availableScreenRect(int id) const > > QRect r(screenGeometry(id)); > > - foreach (PanelView *view, d->panelViews.values()) { > + foreach (PanelView *view, d->panelViews) { > if (view->containment()->screen() == id && view->visibilityMode() > != PanelView::AutoHide) { > QRect v = view->geometry(); > switch (view->location()) { > @@ -417,11 +499,13 @@ PanelView > *ShellCorona::panelView(Plasma::Containment *containment) const > return d->panelViews.value(containment); > } > > - > ///// SLOTS > > -void ShellCorona::screenAdded(QScreen *screen) > +void ShellCorona::outputAdded(KScreen::Output* output) > { > + QScreen* screen = outputToScreen(output); > + Q_ASSERT(screen); > + > //FIXME: QScreen doesn't have any idea of "this qscreen is clone of > this other one > //so this ultra inefficient heuristic has to stay until we have a > slightly better api > foreach (QScreen *s, QGuiApplication::screens()) { > @@ -433,16 +517,14 @@ void ShellCorona::screenAdded(QScreen *screen) > } > > DesktopView *view = new DesktopView(this, screen); > - connect(screen, &QObject::destroyed, [=](){ > - d->views.removeAll(view); > - view->containment()->reactToScreenChange(); > - view->deleteLater(); > - }); > > + //We have to do it in a lambda, > + connect(screen, &QObject::destroyed, this, [=]() { > removeDesktop(view); }); > > const QString currentActivity = > d->activityController->currentActivity(); > > - if (!d->views.isEmpty() && screen == > QGuiApplication::primaryScreen()) { > + qDebug() << "adding screen" << output->name() << output->isPrimary(); > + if (!d->views.isEmpty() && output->isPrimary()) { > DesktopView* oldPrimaryView = d->views.first(); > QScreen* oldPrimaryScreen = oldPrimaryView->screen(); > > @@ -462,6 +544,7 @@ void ShellCorona::screenAdded(QScreen *screen) > d->views.prepend(view); > view = oldPrimaryView; > } else { > + Q_ASSERT(d->views.isEmpty() || !output->isPrimary()); > d->views.append(view); > } > > @@ -488,8 +571,30 @@ void ShellCorona::screenAdded(QScreen *screen) > > emit availableScreenRectChanged(); > emit availableScreenRegionChanged(); > + > + screenInvariants(); > +} > + > +void ShellCorona::removeDesktop(DesktopView* view) > +{ > + int idx = d->views.indexOf(view); > + DesktopView* lastView = d->views.takeAt(d->views.count()-1); > + lastView->containment()->reactToScreenChange(); > + lastView->deleteLater(); > + > + for(int i = idx; i<d->views.count()-1; ++i) { > + d->views[i]->setScreen(d->views[i+1]->screen()); > + } > + > + screenInvariants(); > } > > +void ShellCorona::removePanel(Plasma::Containment* cont) > +{ > + d->panelViews[cont]->deleteLater(); > + d->waitingPanels << cont; > + d->panelViews.remove(cont); > +} > > Plasma::Containment* ShellCorona::createContainmentForActivity(const > QString& activity, int screenNum) > { > @@ -517,30 +622,32 @@ void ShellCorona::createWaitingPanels() > > foreach (Plasma::Containment *cont, d->waitingPanels) { > //ignore non existing (yet?) screens > - if (cont->lastScreen() > (QGuiApplication::screens().size() - 1)) > { > + int requestedScreen = cont->lastScreen(); > + if (requestedScreen < 0) > + ++requestedScreen; > + > + if (requestedScreen > (d->views.size() - 1)) { > stillWaitingPanels << cont; > continue; > } > > d->panelViews[cont] = new PanelView(cont); > > - //keep screen suggestions within bounds of screens we actually > have > - int screen = qBound(0, cont->lastScreen(), > QGuiApplication::screens().size() -1); > + Q_ASSERT(qBound(0, requestedScreen, d->views.size() -1) == > requestedScreen); > + QScreen* screen = d->views[requestedScreen]->screen(); > > - > d->panelViews[cont]->setScreen(QGuiApplication::screens()[screen]); > + d->panelViews[cont]->setScreen(screen); > cont->reactToScreenChange(); > connect(cont, &QObject::destroyed, > - [=](QObject *obj) { > + [=](QObject* ) { > d->panelViews.remove(cont); > emit availableScreenRectChanged(); > emit availableScreenRegionChanged(); > }); > > - connect(QGuiApplication::screens()[screen], &QObject::destroyed, > - [=](QObject *obj) { > - d->panelViews[cont]->deleteLater(); > - d->waitingPanels << cont; > - d->panelViews.remove(cont); > + connect(screen, &QObject::destroyed, > + [=](QObject*) { > + removePanel(cont); > }); > } > d->waitingPanels.clear(); > @@ -549,6 +656,8 @@ void ShellCorona::createWaitingPanels() > emit availableScreenRegionChanged(); > } > > + > + > void ShellCorona::handleContainmentAdded(Plasma::Containment* c) > { > connect(c, &Plasma::Containment::showAddWidgetsInterface, > @@ -883,34 +992,34 @@ void ShellCorona::addPanel(const QString &plugin) > > d->waitingPanels << panel; > createWaitingPanels(); > - if (d->panelViews.contains(panel)) { > - const QPoint cursorPos(QCursor::pos()); > - foreach (QScreen *screen, QGuiApplication::screens()) { > - if (screen->geometry().contains(cursorPos)) { > - d->panelViews[panel]->setScreen(screen); > - break; > - } > + Q_ASSERT(d->panelViews.contains(panel)); > + const QPoint cursorPos(QCursor::pos()); > + foreach (QScreen *screen, QGuiApplication::screens()) { > + if (screen->geometry().contains(cursorPos)) { > + d->panelViews[panel]->setScreen(screen); > + break; > } > } > } > > int ShellCorona::screenForContainment(const Plasma::Containment > *containment) const > { > - QScreen *screen = nullptr; > for (int i = 0; i < d->views.size(); i++) { > if (d->views[i]->containment() == containment) { > - screen = d->views[i]->screen(); > + return i; > } > } > > - if (!screen) { > - PanelView *view = d->panelViews.value(containment); > - if (view) { > - screen = view->screen(); > + PanelView *view = d->panelViews.value(containment); > + if (view) { > + QScreen *screen = view->screen(); > + for (int i = 0; i < d->views.size(); i++) { > + if (d->views[i]->screen() == screen) { > + return i; > + } > } > } > - > - return screen ? qApp->screens().indexOf(screen) : -1; > + return -1; > } > > void ShellCorona::activityOpened() > diff --git a/shell/shellcorona.h b/shell/shellcorona.h > index d71f648..dc74500 100644 > --- a/shell/shellcorona.h > +++ b/shell/shellcorona.h > @@ -27,6 +27,9 @@ > > #include <Plasma/Package> > > +namespace KScreen { > +class Output; > +} > > namespace Plasma > { > @@ -34,6 +37,7 @@ namespace Plasma > } // namespace Plasma > > class Activity; > +class DesktopView; > class PanelView; > class QScreen; > namespace WorkspaceScripting { > @@ -102,8 +106,6 @@ public Q_SLOTS: > void loadScriptInInteractiveConsole(const QString &script); > > protected Q_SLOTS: > - void screenAdded(QScreen *screen); > - > /** > * Loads the layout and performs the needed checks > */ > @@ -141,11 +143,18 @@ private Q_SLOTS: > void addPanel(QAction *action); > void addPanel(const QString &plugin); > > + void removePanel(Plasma::Containment* cont); > + void removeDesktop(DesktopView* screen); > + void outputAdded(KScreen::Output* output); > + void primaryOutputChanged(); > + > void activityOpened(); > void activityClosed(); > void activityRemoved(); > > private: > + void screenInvariants(); > + > /** > * @returns a new containment associated with the specified @p > activity and @p screen. > */ > > _______________________________________________ > Plasma-devel mailing list > Plasma-devel@kde.org > https://mail.kde.org/mailman/listinfo/plasma-devel >
_______________________________________________ Plasma-devel mailing list Plasma-devel@kde.org https://mail.kde.org/mailman/listinfo/plasma-devel