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