[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">&lt;<a href="mailto:aleixpol@kde.org" \
target="_blank">aleixpol@kde.org</a>&gt;</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 &#39;plasmashell+libkscreen&#39;.<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&#39;m not merging to master yet as I&#39;m experiencing some issues but \
it&#39;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 &lt;KAuthorized&gt;<br>
  #include &lt;KWindowSystem&gt;<br>
<br>
+#include &lt;KScreen/Config&gt;<br>
+#include &lt;kscreen/configmonitor.h&gt;<br>
+<br>
  #include &quot;config-ktexteditor.h&quot; // HAVE_KTEXTEDITOR<br>
<br>
<br>
@@ -59,8 +62,6 @@<br>
<br>
  #include &quot;plasmashelladaptor.h&quot;<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&lt;InteractiveConsole&gt; 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-&gt;name() == output-&gt;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-&gt;shell;<br>
  }<br>
<br>
+static QList&lt;KScreen::Output*&gt; sortOutputs(const QHash&lt;int, \
KScreen::Output*&gt; &amp;outputs)<br> +{<br>
+      QList&lt;KScreen::Output*&gt; ret;<br>
+      foreach(KScreen::Output* output, outputs) {<br>
+            if(!output-&gt;isEnabled())<br>
+                  ;<br>
+            else if(output-&gt;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-&gt;shell.isEmpty() ||<br>
@@ -269,17 +295,73 @@ void ShellCorona::load()<br>
              }<br>
        }<br>
<br>
-      for (QScreen *screen : QGuiApplication::screens()) {<br>
-            screenAdded(screen);<br>
+      d-&gt;screenConfiguration = KScreen::Config::current();<br>
+      KScreen::ConfigMonitor::instance()-&gt;addConfig(d-&gt;screenConfiguration);<br>
 +      for (KScreen::Output *output : \
sortOutputs(d-&gt;screenConfiguration-&gt;connectedOutputs())) {<br> +            \
outputAdded(output);<br>  }<br>
-      connect(qApp, &amp;QGuiApplication::screenAdded,<br>
-                  this, &amp;ShellCorona::screenAdded);<br>
+      connect(d-&gt;screenConfiguration, &amp;KScreen::Config::outputAdded,<br>
+                  this, &amp;ShellCorona::outputAdded);<br>
+      connect(d-&gt;screenConfiguration, \
&amp;KScreen::Config::primaryOutputChanged,<br> +                  this, \
&amp;ShellCorona::primaryOutputChanged);<br> <br>
        if (!d-&gt;waitingPanels.isEmpty()) {<br>
              d-&gt;waitingPanelsTimer.start();<br>
        }<br>
  }<br>
<br>
+void ShellCorona::primaryOutputChanged()<br>
+{<br>
+      KScreen::Config* current = d-&gt;screenConfiguration;<br>
+      QScreen* newPrimary = outputToScreen(current-&gt;primaryOutput());<br>
+      int i=0;<br>
+      foreach(DesktopView* view, d-&gt;views) {<br>
+            if(view-&gt;screen() == newPrimary)<br>
+                  break;<br>
+            i++;<br>
+      }<br>
+      QScreen* oldPrimary = d-&gt;views.first()-&gt;screen();<br>
+      qDebug() &lt;&lt; &quot;primary changed!&quot; &lt;&lt; oldPrimary-&gt;name() \
&lt;&lt; newPrimary-&gt;name() &lt;&lt; i;<br> +//<br>
+//       //if it was not found, it means that outputAdded hasn&#39;t been called \
yet<br> +      if (i&gt;=d-&gt;views.count() || i==0)<br>
+            return;<br>
+//<br>
+      Q_ASSERT(oldPrimary != newPrimary);<br>
+      Q_ASSERT(d-&gt;views[0]-&gt;screen() != d-&gt;views[i]-&gt;screen());<br>
+      Q_ASSERT(d-&gt;views[0]-&gt;screen() == oldPrimary);<br>
+      Q_ASSERT(d-&gt;views[0]-&gt;screen() != newPrimary);<br>
+      Q_ASSERT(d-&gt;views[0]-&gt;geometry() == oldPrimary-&gt;geometry());<br>
+      qDebug() &lt;&lt; &quot;adapting&quot; &lt;&lt; newPrimary-&gt;geometry() \
&lt;&lt; d-&gt;views[0]-&gt;containment()-&gt;wallpaper()<br> +                       \
&lt;&lt; oldPrimary-&gt;geometry() &lt;&lt; \
d-&gt;views[i]-&gt;containment()-&gt;wallpaper() &lt;&lt; i;<br> +<br>
+      d-&gt;views[0]-&gt;setScreen(newPrimary);<br>
+      d-&gt;views[i]-&gt;setScreen(oldPrimary);<br>
+      screenInvariants();<br>
+<br>
+      QList&lt;Plasma::Containment*&gt; panels;<br>
+      foreach(PanelView* panel, d-&gt;panelViews) {<br>
+            if(panel-&gt;screen() == oldPrimary)<br>
+                  panel-&gt;setScreen(newPrimary);<br>
+            else if(panel-&gt;screen() == newPrimary)<br>
+                  panel-&gt;setScreen(oldPrimary);<br>
+      }<br>
+}<br>
+<br>
+void ShellCorona::screenInvariants()<br>
+{<br>
+      QScreen* s = outputToScreen(d-&gt;screenConfiguration-&gt;primaryOutput());<br>
 +      Q_ASSERT(d-&gt;views[0]-&gt;screen()-&gt;name() == s-&gt;name());<br>
+      Q_ASSERT(d-&gt;views[0]-&gt;geometry() == s-&gt;geometry());<br>
+<br>
+      QSet&lt;QScreen*&gt; screens;<br>
+      foreach(DesktopView* view, d-&gt;views) {<br>
+            Q_ASSERT(!screens.contains(view-&gt;screen()));<br>
+            screens.insert(view-&gt;screen());<br>
+      }<br>
+}<br>
+<br>
+<br>
  void ShellCorona::unload()<br>
  {<br>
        if (d-&gt;shell.isEmpty()) {<br>
@@ -356,7 +438,7 @@ QRegion ShellCorona::availableScreenRegion(int id) const<br>
<br>
        if (view) {<br>
              QRegion r = view-&gt;geometry();<br>
-            foreach (PanelView *v, d-&gt;panelViews.values()) {<br>
+            foreach (PanelView *v, d-&gt;panelViews) {<br>
                    if (v-&gt;containment()-&gt;screen() == id &amp;&amp; \
v-&gt;visibilityMode() != PanelView::AutoHide) {<br>  r -= v-&gt;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-&gt;panelViews.values()) {<br>
+      foreach (PanelView *view, d-&gt;panelViews) {<br>
              if (view-&gt;containment()-&gt;screen() == id &amp;&amp; \
view-&gt;visibilityMode() != PanelView::AutoHide) {<br>  QRect v = \
view-&gt;geometry();<br>  switch (view-&gt;location()) {<br>
@@ -417,11 +499,13 @@ PanelView *ShellCorona::panelView(Plasma::Containment \
*containment) const<br>  return d-&gt;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&#39;t have any idea of &quot;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, &amp;QObject::destroyed, [=](){<br>
-            d-&gt;views.removeAll(view);<br>
-            view-&gt;containment()-&gt;reactToScreenChange();<br>
-            view-&gt;deleteLater();<br>
-      });<br>
<br>
+      //We have to do it in a lambda,<br>
+      connect(screen, &amp;QObject::destroyed, this, [=]() { removeDesktop(view); \
});<br> <br>
        const QString currentActivity = \
d-&gt;activityController-&gt;currentActivity();<br> <br>
-      if (!d-&gt;views.isEmpty() &amp;&amp; screen == \
QGuiApplication::primaryScreen()) {<br> +      qDebug() &lt;&lt; &quot;adding \
screen&quot; &lt;&lt; output-&gt;name() &lt;&lt; output-&gt;isPrimary();<br> +      \
if (!d-&gt;views.isEmpty() &amp;&amp; output-&gt;isPrimary()) {<br>  DesktopView* \
oldPrimaryView = d-&gt;views.first();<br>  QScreen* oldPrimaryScreen = \
oldPrimaryView-&gt;screen();<br> <br>
@@ -462,6 +544,7 @@ void ShellCorona::screenAdded(QScreen *screen)<br>
              d-&gt;views.prepend(view);<br>
              view = oldPrimaryView;<br>
        } else {<br>
+            Q_ASSERT(d-&gt;views.isEmpty() || !output-&gt;isPrimary());<br>
              d-&gt;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-&gt;views.indexOf(view);<br>
+      DesktopView* lastView = d-&gt;views.takeAt(d-&gt;views.count()-1);<br>
+      lastView-&gt;containment()-&gt;reactToScreenChange();<br>
+      lastView-&gt;deleteLater();<br>
+<br>
+      for(int i = idx; i&lt;d-&gt;views.count()-1; ++i) {<br>
+            d-&gt;views[i]-&gt;setScreen(d-&gt;views[i+1]-&gt;screen());<br>
+      }<br>
+<br>
+      screenInvariants();<br>
  }<br>
<br>
+void ShellCorona::removePanel(Plasma::Containment* cont)<br>
+{<br>
+      d-&gt;panelViews[cont]-&gt;deleteLater();<br>
+      d-&gt;waitingPanels &lt;&lt; cont;<br>
+      d-&gt;panelViews.remove(cont);<br>
+}<br>
<br>
  Plasma::Containment* ShellCorona::createContainmentForActivity(const QString&amp; \
activity, int screenNum)<br>  {<br>
@@ -517,30 +622,32 @@ void ShellCorona::createWaitingPanels()<br>
<br>
        foreach (Plasma::Containment *cont, d-&gt;waitingPanels) {<br>
              //ignore non existing (yet?) screens<br>
-            if (cont-&gt;lastScreen() &gt; (QGuiApplication::screens().size() - 1)) \
{<br> +            int requestedScreen = cont-&gt;lastScreen();<br>
+            if (requestedScreen &lt; 0)<br>
+                  ++requestedScreen;<br>
+<br>
+            if (requestedScreen &gt; (d-&gt;views.size() - 1)) {<br>
                    stillWaitingPanels &lt;&lt; cont;<br>
                    continue;<br>
              }<br>
<br>
              d-&gt;panelViews[cont] = new PanelView(cont);<br>
<br>
-            //keep screen suggestions within bounds of screens we actually have<br>
-            int screen = qBound(0, cont-&gt;lastScreen(), \
QGuiApplication::screens().size() -1);<br> +            Q_ASSERT(qBound(0, \
requestedScreen, d-&gt;views.size() -1) == requestedScreen);<br> +            \
QScreen* screen = d-&gt;views[requestedScreen]-&gt;screen();<br> <br>
-            d-&gt;panelViews[cont]-&gt;setScreen(QGuiApplication::screens()[screen]);<br>
 +            d-&gt;panelViews[cont]-&gt;setScreen(screen);<br>
              cont-&gt;reactToScreenChange();<br>
              connect(cont, &amp;QObject::destroyed,<br>
-                        [=](QObject *obj) {<br>
+                        [=](QObject* ) {<br>
                                d-&gt;panelViews.remove(cont);<br>
                                emit availableScreenRectChanged();<br>
                                emit availableScreenRegionChanged();<br>
                          });<br>
<br>
-            connect(QGuiApplication::screens()[screen], &amp;QObject::destroyed,<br>
-                        [=](QObject *obj) {<br>
-                              d-&gt;panelViews[cont]-&gt;deleteLater();<br>
-                              d-&gt;waitingPanels &lt;&lt; cont;<br>
-                              d-&gt;panelViews.remove(cont);<br>
+            connect(screen, &amp;QObject::destroyed,<br>
+                        [=](QObject*) {<br>
+                              removePanel(cont);<br>
                          });<br>
        }<br>
        d-&gt;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, &amp;Plasma::Containment::showAddWidgetsInterface,<br>
@@ -883,34 +992,34 @@ void ShellCorona::addPanel(const QString &amp;plugin)<br>
<br>
        d-&gt;waitingPanels &lt;&lt; panel;<br>
        createWaitingPanels();<br>
-      if (d-&gt;panelViews.contains(panel)) {<br>
-            const QPoint cursorPos(QCursor::pos());<br>
-            foreach (QScreen *screen, QGuiApplication::screens()) {<br>
-                  if (screen-&gt;geometry().contains(cursorPos)) {<br>
-                        d-&gt;panelViews[panel]-&gt;setScreen(screen);<br>
-                        break;<br>
-                  }<br>
+      Q_ASSERT(d-&gt;panelViews.contains(panel));<br>
+      const QPoint cursorPos(QCursor::pos());<br>
+      foreach (QScreen *screen, QGuiApplication::screens()) {<br>
+            if (screen-&gt;geometry().contains(cursorPos)) {<br>
+                  d-&gt;panelViews[panel]-&gt;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 &lt; d-&gt;views.size(); i++) {<br>
              if (d-&gt;views[i]-&gt;containment() == containment) {<br>
-                  screen = d-&gt;views[i]-&gt;screen();<br>
+                  return i;<br>
              }<br>
        }<br>
<br>
-      if (!screen) {<br>
-            PanelView *view = d-&gt;panelViews.value(containment);<br>
-            if (view) {<br>
-                  screen = view-&gt;screen();<br>
+      PanelView *view = d-&gt;panelViews.value(containment);<br>
+      if (view) {<br>
+            QScreen *screen = view-&gt;screen();<br>
+            for (int i = 0; i &lt; d-&gt;views.size(); i++) {<br>
+                  if (d-&gt;views[i]-&gt;screen() == screen) {<br>
+                        return i;<br>
+                  }<br>
              }<br>
        }<br>
-<br>
-      return screen ? qApp-&gt;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 &lt;Plasma/Package&gt;<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 &amp;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 &amp;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