[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#857762: unblock: libkscreen/4:5.8.6-2



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Dear release team,

KDE Plasma 5.8 is an LTS release that I consider fit to be updated in stretch. 
This particular request is for libkscreen 5.8.6.

Compared to the 5.8.4 version currently in stretch the 5.8.6 release fixes 
are:
 + Allow changing an output's modelist at runtime (7367e55) [1]
 + Disable low level logging (04a6483) [2] (Closes: #846940)
 + Improve laptop panel detection (57cd4d1)

On the Debian side, the symbols file adds the new symbols related to 7367e55, 
and notes the mentioned closes.

I'm attaching the full debdiff and the upstream gitlog.

The 4:5.8.6-1 version is currently in experimental, and I would like to upload 
the 4:5.8.6-2 version to unstable if this gets approved.

Please unblock package libkscreen

Happy hacking,

[1]: https://bugs.kde.org/show_bug.cgi?id=356864
[2]: https://bugs.kde.org/show_bug.cgi?id=361688

unblock libkscreen/4:5.8.6-2

-- System Information:
Debian Release: 9.0
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'testing-debug'), (500, 'testing'), (500, 'stable'), (50, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386, armhf

Kernel: Linux 4.9.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Init: systemd (via /run/systemd/system)
commit 652f0452059e41e529a8f6a7275b6e364ed6928b
Author: Jonathan Riddell <jr@jriddell.org>
Date:   Tue Feb 21 11:44:09 2017 +0000

    Update version number for 5.8.6
    GIT_SILENT

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6fbf0a..b1a3bdb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 2.8.12)
 
 project(libkscreen)
-set(PROJECT_VERSION "5.8.5")
+set(PROJECT_VERSION "5.8.6")
 
 find_package(ECM 5.14.0 REQUIRED NO_MODULE)
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})

commit 57cd4d12b3c70495935675cb7df6532b98695fb1
Author: Sebastian Kügler <sebas@kde.org>
Date:   Tue Jan 24 16:15:26 2017 +0100

    Fix type argument for get property call
    
    We were passing the wrong argument in there, it has to be the atom's
    type, not the atom property itself.
    
    This fixes detection of the laptop panel in some cases, where we can't
    fix it with our fallback mechanism.
    
    Patch-by: Gabriel Souza Franco <gabrielfrancosouza@gmail.com>
    Signed-off-by: Sebastian Kügler <sebas@kde.org>

diff --git a/backends/xrandr/xrandroutput.cpp b/backends/xrandr/xrandroutput.cpp
index 94a0b65..cc49823 100644
--- a/backends/xrandr/xrandroutput.cpp
+++ b/backends/xrandr/xrandroutput.cpp
@@ -318,7 +318,7 @@ QByteArray XRandROutput::typeFromProperty(xcb_randr_output_t outputId)
 
     char *connectorType;
 
-    auto cookie = xcb_randr_get_output_property(XCB::connection(), outputId, atomType,
+    auto cookie = xcb_randr_get_output_property(XCB::connection(), outputId, atomType->atom,
                                                 XCB_ATOM_ANY, 0, 100, false, false);
     XCB::ScopedPointer<xcb_randr_get_output_property_reply_t> reply(xcb_randr_get_output_property_reply(XCB::connection(), cookie, NULL));
     if (!reply) {

commit 04a6483a01caaa17e476ac9e4a47725f0e1ca06f
Author: Sebastian Kügler <sebas@kde.org>
Date:   Fri Jan 6 17:46:13 2017 +0100

    disable logging to kscreen.log by default
    
    Summary:
    Most of the issues that this feature should uncover have been uncovered,
    it makes sense to disable the logging (and futzing around with
    QCategorizedLogging) by default, and only use it to debug specific
    setups.
    
    Test Plan: Adjusted autotests accordingly.
    
    Reviewers: #plasma, mart
    
    Reviewed By: mart
    
    Subscribers: graesslin, plasma-devel
    
    Tags: #plasma
    
    Differential Revision: https://phabricator.kde.org/D3993
    
    BUG:361688
    CHANGELOG:Disable logging to kscreen.log by default, re-enable with export KSCREEN_LOGGING=1
    
    cherry-picked from cea4c63f84650efa4

diff --git a/autotests/testlog.cpp b/autotests/testlog.cpp
index 47cd1df..76654d6 100644
--- a/autotests/testlog.cpp
+++ b/autotests/testlog.cpp
@@ -55,6 +55,7 @@ void TestLog::init()
 void TestLog::initTestCase()
 {
 
+    qputenv(KSCREEN_LOGGING, QByteArray("true"));
 }
 
 void TestLog::cleanupTestCase()
@@ -85,6 +86,13 @@ void TestLog::testEnabled()
     qunsetenv(KSCREEN_LOGGING);
 
     log = Log::instance();
+    QCOMPARE(log->enabled(), false);
+    QCOMPARE(log->logFile(), QString());
+
+    delete log;
+    qputenv(KSCREEN_LOGGING, QByteArray("truE"));
+
+    log = Log::instance();
     QCOMPARE(log->enabled(), true);
     QCOMPARE(log->logFile(), m_defaultLogFile);
 
diff --git a/src/log.cpp b/src/log.cpp
index dbb48a3..51b385e 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -57,7 +57,7 @@ class Log::Private
 {
   public:
       QString context;
-      bool enabled = true;
+      bool enabled = false;
       QString logFile;
 };
 
@@ -68,11 +68,13 @@ Log::Log() :
 
     if (qEnvironmentVariableIsSet(logging_env)) {
         const QString logging_env_value = qgetenv(logging_env).constData();
-        if (logging_env_value == QStringLiteral("0") || logging_env_value.toLower() == QStringLiteral("false")) {
-            d->enabled = false;
-            return;
+        if (logging_env_value != QStringLiteral("0") && logging_env_value.toLower() != QStringLiteral("false")) {
+            d->enabled = true;
         }
     }
+    if (!d->enabled) {
+         return;
+    }
     d->logFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kscreen/kscreen.log";
 
     QLoggingCategory::setFilterRules("kscreen.*=true");

commit 7f364342238af7b667ef64f4f63eb3077655b024
Author: Jonathan Riddell <jr@jriddell.org>
Date:   Tue Dec 27 09:27:30 2016 +0000

    Update version number for 5.8.5
    GIT_SILENT

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8515e95..a6fbf0a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 2.8.12)
 
 project(libkscreen)
-set(PROJECT_VERSION "5.8.4")
+set(PROJECT_VERSION "5.8.5")
 
 find_package(ECM 5.14.0 REQUIRED NO_MODULE)
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})

commit 7367e55b7c172d54d068eb09f308e92368c294e9
Author: Sebastian Kügler <sebas@kde.org>
Date:   Wed Oct 19 23:36:43 2016 +0200

    allow changing an output's modelist at runtime
    
    This should fix running Plasma in a windowed virtual machine, when the window is
    resized, the mode list changes, and libksreen can't currently handle that.
    
    Summary:
    * make Output::modes() non CONSTANT, add modesChanged() signal
    * compare the mode lists and set the new one
    * queue an outputChanged signal when applied
    * autotest for modelist changes
    * update the mode list on RRNotify events
    
    BUG:356864
    
    Test Plan:
    * for library part, autotests are added
    * for xrandr backends, we can't sensibly autotest this :(
    
    Reviewers: #plasma, mart
    
    Reviewed By: mart
    
    Subscribers: graesslin, plasma-devel
    
    Tags: #plasma
    
    Differential Revision: https://phabricator.kde.org/D3117

diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index 9f8cea7..774685c 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -22,6 +22,7 @@ kscreen_add_test(testconfigmonitor)
 kscreen_add_test(testinprocess)
 kscreen_add_test(testbackendloader)
 kscreen_add_test(testlog)
+kscreen_add_test(testmodelistchange)
 
 set(KSCREEN_WAYLAND_LIBS
     KF5::WaylandServer KF5::WaylandClient
diff --git a/autotests/testmodelistchange.cpp b/autotests/testmodelistchange.cpp
new file mode 100644
index 0000000..58080f8
--- /dev/null
+++ b/autotests/testmodelistchange.cpp
@@ -0,0 +1,179 @@
+/*************************************************************************************
+ *  Copyright 2016 by Sebastian Kügler <sebas@kde.org>                               *
+ *                                                                                   *
+ *  This library is free software; you can redistribute it and/or                    *
+ *  modify it under the terms of the GNU Lesser General Public                       *
+ *  License as published by the Free Software Foundation; either                     *
+ *  version 2.1 of the License, or (at your option) any later version.               *
+ *                                                                                   *
+ *  This library is distributed in the hope that it will be useful,                  *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                *
+ *  Lesser General Public License for more details.                                  *
+ *                                                                                   *
+ *  You should have received a copy of the GNU Lesser General Public                 *
+ *  License along with this library; if not, write to the Free Software              *
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA       *
+ *************************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/QObject>
+
+#include "../src/config.h"
+#include "../src/configmonitor.h"
+#include "../src/output.h"
+#include "../src/mode.h"
+#include "../src/getconfigoperation.h"
+#include "../src/setconfigoperation.h"
+#include "../src/backendmanager_p.h"
+
+using namespace KScreen;
+
+
+class TestModeListChange : public QObject
+{
+    Q_OBJECT
+
+private:
+    KScreen::ConfigPtr getConfig();
+    KScreen::ModeList createModeList();
+    bool compareModeList(KScreen::ModeList before, KScreen::ModeList &after);
+
+    QSize s0 = QSize(1920, 1080);
+    QSize s1 = QSize(1600, 1200);
+    QSize s2 = QSize(1280, 1024);
+    QSize s3 = QSize(800, 600);
+    QSize snew = QSize(777, 888);
+    QString idnew = QStringLiteral("666");
+
+private Q_SLOTS:
+    void initTestCase();
+    void cleanupTestCase();
+
+    void modeListChange();
+};
+
+ConfigPtr TestModeListChange::getConfig()
+{
+    qputenv("KSCREEN_BACKEND_INPROCESS", "1");
+    auto *op = new GetConfigOperation();
+    if (!op->exec()) {
+        qWarning("ConfigOperation error: %s", qPrintable(op->errorString()));
+        BackendManager::instance()->shutdownBackend();
+        return ConfigPtr();
+    }
+
+    BackendManager::instance()->shutdownBackend();
+
+    return op->config();
+}
+
+KScreen::ModeList TestModeListChange::createModeList()
+{
+
+    KScreen::ModeList newmodes;
+    {
+        QString _id = QString::number(11);
+        KScreen::ModePtr kscreenMode(new KScreen::Mode);
+        kscreenMode->setId(_id);
+        kscreenMode->setName(_id);
+        kscreenMode->setSize(s0);
+        kscreenMode->setRefreshRate(60);
+        newmodes.insert(_id, kscreenMode);
+    }
+    {
+        QString _id = QString::number(22);
+        KScreen::ModePtr kscreenMode(new KScreen::Mode);
+        kscreenMode->setId(_id);
+        kscreenMode->setName(_id);
+        kscreenMode->setSize(s1);
+        kscreenMode->setRefreshRate(60);
+        newmodes.insert(_id, kscreenMode);
+    }
+    {
+        QString _id = QString::number(33);
+        KScreen::ModePtr kscreenMode(new KScreen::Mode);
+        kscreenMode->setId(_id);
+        kscreenMode->setName(_id);
+        kscreenMode->setSize(s2);
+        kscreenMode->setRefreshRate(60);
+        newmodes.insert(_id, kscreenMode);
+    }
+    return newmodes;
+}
+
+
+void TestModeListChange::initTestCase()
+{
+    qputenv("KSCREEN_LOGGING", "false");
+    qputenv("KSCREEN_BACKEND", "Fake");
+}
+
+void TestModeListChange::cleanupTestCase()
+{
+    BackendManager::instance()->shutdownBackend();
+}
+
+void TestModeListChange::modeListChange()
+{
+    //json file for the fake backend
+    qputenv("KSCREEN_BACKEND_ARGS", "TEST_DATA=" TEST_DATA "singleoutput.json");
+
+    const ConfigPtr config = getConfig();
+    QVERIFY(!config.isNull());
+
+    auto output = config->outputs().first();
+    QVERIFY(!output.isNull());
+    auto modelist = output->modes();
+
+    auto mode = modelist.first();
+    mode->setId(QStringLiteral("44"));
+    mode->setSize(QSize(880, 440));
+    output->setModes(modelist);
+
+    QCOMPARE(output->modes().first()->id(), QStringLiteral("44"));
+    QCOMPARE(output->modes().first()->size(), QSize(880, 440));
+    QVERIFY(!modelist.isEmpty());
+
+    ConfigMonitor::instance()->addConfig(config);
+    QSignalSpy outputChangedSpy(output.data(), &Output::outputChanged);
+    QVERIFY(outputChangedSpy.isValid());
+    QSignalSpy modesChangedSpy(output.data(), &Output::modesChanged);
+    QVERIFY(modesChangedSpy.isValid());
+
+    auto before = createModeList();
+    output->setModes(before);
+    QCOMPARE(modesChangedSpy.count(), 1);
+    output->setModes(before);
+    QCOMPARE(modesChangedSpy.count(), 1);
+    output->setModes(before);
+    QCOMPARE(modesChangedSpy.count(), 1);
+    QCOMPARE(output->modes().first()->size(), s0);
+    QCOMPARE(output->modes().first()->id(), QStringLiteral("11"));
+
+    auto after = createModeList();
+    auto firstmode = after.first();
+    QVERIFY(!firstmode.isNull());
+    QCOMPARE(firstmode->size(), s0);
+    QCOMPARE(firstmode->id(), QStringLiteral("11"));
+    firstmode->setSize(snew);
+    firstmode->setId(idnew);
+    output->setModes(after);
+    QCOMPARE(modesChangedSpy.count(), 2);
+
+    QString _id = QString::number(11);
+    KScreen::ModePtr kscreenMode(new KScreen::Mode);
+    kscreenMode->setId(_id);
+    kscreenMode->setName(_id);
+    kscreenMode->setSize(s0);
+    kscreenMode->setRefreshRate(60);
+    before.insert(_id, kscreenMode);
+    output->setModes(before);
+    QCOMPARE(modesChangedSpy.count(), 3);
+    QCOMPARE(outputChangedSpy.count(), modesChangedSpy.count());
+}
+
+
+QTEST_MAIN(TestModeListChange)
+
+#include "testmodelistchange.moc"
diff --git a/backends/xrandr/xrandroutput.cpp b/backends/xrandr/xrandroutput.cpp
index 9a5cabc..94a0b65 100644
--- a/backends/xrandr/xrandroutput.cpp
+++ b/backends/xrandr/xrandroutput.cpp
@@ -141,7 +141,7 @@ void XRandROutput::update(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_rand
     if (isConnected() != (conn == XCB_RANDR_CONNECTION_CONNECTED)) {
         if (conn == XCB_RANDR_CONNECTION_CONNECTED) {
             // New monitor has been connected, refresh everything
-          init();
+            init();
         } else {
             // Disconnected
             m_connected = conn;
@@ -153,6 +153,14 @@ void XRandROutput::update(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_rand
             m_modes.clear();
             m_preferredModes.clear();
         }
+    } else if (conn == XCB_RANDR_CONNECTION_CONNECTED) {
+        // the output changed in some way, let's update the internal
+        // list of modes, as it may have changed
+        XCB::OutputInfo outputInfo(m_id, XCB_TIME_CURRENT_TIME);
+        if (outputInfo) {
+            updateModes(outputInfo);
+        }
+
     }
 
     // A monitor has been enabled or disabled
diff --git a/src/output.cpp b/src/output.cpp
index a45150e..1fcf30b 100644
--- a/src/output.cpp
+++ b/src/output.cpp
@@ -69,6 +69,7 @@ class Output::Private
     }
 
     QString biggestMode(const ModeList& modes) const;
+    bool compareModeList(const ModeList& before, const ModeList& after);
 
     int id;
     QString name;
@@ -90,6 +91,32 @@ class Output::Private
     mutable QPointer<Edid> edid;
 };
 
+bool Output::Private::compareModeList(const ModeList& before, const ModeList &after)
+{
+    if (before.keys() != after.keys()) {
+        return false;
+    }
+    for (const QString &key : before.keys()) {
+        const auto mb = before.value(key);
+        const auto ma = after.value(key);
+        if (mb->id() != ma->id()) {
+            return false;
+        }
+        if (mb->size() != ma->size()) {
+            return false;
+        }
+        if (mb->refreshRate() != ma->refreshRate()) {
+            return false;
+        }
+        if (mb->name() != ma->name()) {
+            return false;
+        }
+    }
+    // They're the same
+    return true;
+}
+
+
 QString Output::Private::biggestMode(const ModeList& modes) const
 {
     int area, total = 0;
@@ -221,7 +248,12 @@ ModeList Output::modes() const
 
 void Output::setModes(const ModeList &modes)
 {
+    bool changed = !d->compareModeList(d->modeList, modes);
     d->modeList = modes;
+    if (changed) {
+        emit modesChanged();
+        emit outputChanged();
+    }
 }
 
 QString Output::currentModeId() const
@@ -494,8 +526,10 @@ void Output::apply(const OutputPtr& other)
         changes << &Output::clonesChanged;
         setClones(other->d->clones);;
     }
+    if (!d->compareModeList(d->modeList, other->d->modeList)) {
+        changes << &Output::outputChanged;
+    }
 
-    // Non-notifyable changes
     setPreferredModes(other->d->preferredModes);
     ModeList modes;
     Q_FOREACH (const ModePtr &otherMode, other->modes()) {
@@ -503,6 +537,7 @@ void Output::apply(const OutputPtr& other)
     }
     setModes(modes);
 
+    // Non-notifyable changes
     if (other->d->edid) {
         delete d->edid;
         d->edid = other->d->edid->clone();
diff --git a/src/output.h b/src/output.h
index bb109e2..13b4a72 100644
--- a/src/output.h
+++ b/src/output.h
@@ -46,7 +46,7 @@ class KSCREEN_EXPORT Output : public QObject
         Q_PROPERTY(QString name READ name WRITE setName NOTIFY outputChanged)
         Q_PROPERTY(Type type READ type WRITE setType NOTIFY outputChanged)
         Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY outputChanged)
-        Q_PROPERTY(ModeList modes READ modes CONSTANT)
+        Q_PROPERTY(ModeList modes READ modes NOTIFY modesChanged)
         Q_PROPERTY(QPoint pos READ pos WRITE setPos NOTIFY posChanged)
         Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY sizeChanged)
         Q_PROPERTY(Rotation rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
@@ -204,6 +204,14 @@ class KSCREEN_EXPORT Output : public QObject
         void isPrimaryChanged();
         void clonesChanged();
 
+        /** The mode list changed.
+         *
+         * This may happen when a mode is added or changed.
+         *
+         * @since 5.8.3
+         */
+        void modesChanged();
+
     private:
         Q_DISABLE_COPY(Output)
 
diff -Nru libkscreen-5.8.4/autotests/CMakeLists.txt libkscreen-5.8.6/autotests/CMakeLists.txt
--- libkscreen-5.8.4/autotests/CMakeLists.txt	2016-11-22 11:18:06.000000000 +0100
+++ libkscreen-5.8.6/autotests/CMakeLists.txt	2017-02-21 13:06:30.000000000 +0100
@@ -22,6 +22,7 @@
 kscreen_add_test(testinprocess)
 kscreen_add_test(testbackendloader)
 kscreen_add_test(testlog)
+kscreen_add_test(testmodelistchange)
 
 set(KSCREEN_WAYLAND_LIBS
     KF5::WaylandServer KF5::WaylandClient
diff -Nru libkscreen-5.8.4/autotests/testlog.cpp libkscreen-5.8.6/autotests/testlog.cpp
--- libkscreen-5.8.4/autotests/testlog.cpp	2016-11-22 11:18:06.000000000 +0100
+++ libkscreen-5.8.6/autotests/testlog.cpp	2017-02-21 13:06:30.000000000 +0100
@@ -55,6 +55,7 @@
 void TestLog::initTestCase()
 {
 
+    qputenv(KSCREEN_LOGGING, QByteArray("true"));
 }
 
 void TestLog::cleanupTestCase()
@@ -85,6 +86,13 @@
     qunsetenv(KSCREEN_LOGGING);
 
     log = Log::instance();
+    QCOMPARE(log->enabled(), false);
+    QCOMPARE(log->logFile(), QString());
+
+    delete log;
+    qputenv(KSCREEN_LOGGING, QByteArray("truE"));
+
+    log = Log::instance();
     QCOMPARE(log->enabled(), true);
     QCOMPARE(log->logFile(), m_defaultLogFile);
 
diff -Nru libkscreen-5.8.4/autotests/testmodelistchange.cpp libkscreen-5.8.6/autotests/testmodelistchange.cpp
--- libkscreen-5.8.4/autotests/testmodelistchange.cpp	1970-01-01 01:00:00.000000000 +0100
+++ libkscreen-5.8.6/autotests/testmodelistchange.cpp	2017-02-21 13:06:30.000000000 +0100
@@ -0,0 +1,179 @@
+/*************************************************************************************
+ *  Copyright 2016 by Sebastian Kügler <sebas@kde.org>                               *
+ *                                                                                   *
+ *  This library is free software; you can redistribute it and/or                    *
+ *  modify it under the terms of the GNU Lesser General Public                       *
+ *  License as published by the Free Software Foundation; either                     *
+ *  version 2.1 of the License, or (at your option) any later version.               *
+ *                                                                                   *
+ *  This library is distributed in the hope that it will be useful,                  *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                *
+ *  Lesser General Public License for more details.                                  *
+ *                                                                                   *
+ *  You should have received a copy of the GNU Lesser General Public                 *
+ *  License along with this library; if not, write to the Free Software              *
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA       *
+ *************************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/QObject>
+
+#include "../src/config.h"
+#include "../src/configmonitor.h"
+#include "../src/output.h"
+#include "../src/mode.h"
+#include "../src/getconfigoperation.h"
+#include "../src/setconfigoperation.h"
+#include "../src/backendmanager_p.h"
+
+using namespace KScreen;
+
+
+class TestModeListChange : public QObject
+{
+    Q_OBJECT
+
+private:
+    KScreen::ConfigPtr getConfig();
+    KScreen::ModeList createModeList();
+    bool compareModeList(KScreen::ModeList before, KScreen::ModeList &after);
+
+    QSize s0 = QSize(1920, 1080);
+    QSize s1 = QSize(1600, 1200);
+    QSize s2 = QSize(1280, 1024);
+    QSize s3 = QSize(800, 600);
+    QSize snew = QSize(777, 888);
+    QString idnew = QStringLiteral("666");
+
+private Q_SLOTS:
+    void initTestCase();
+    void cleanupTestCase();
+
+    void modeListChange();
+};
+
+ConfigPtr TestModeListChange::getConfig()
+{
+    qputenv("KSCREEN_BACKEND_INPROCESS", "1");
+    auto *op = new GetConfigOperation();
+    if (!op->exec()) {
+        qWarning("ConfigOperation error: %s", qPrintable(op->errorString()));
+        BackendManager::instance()->shutdownBackend();
+        return ConfigPtr();
+    }
+
+    BackendManager::instance()->shutdownBackend();
+
+    return op->config();
+}
+
+KScreen::ModeList TestModeListChange::createModeList()
+{
+
+    KScreen::ModeList newmodes;
+    {
+        QString _id = QString::number(11);
+        KScreen::ModePtr kscreenMode(new KScreen::Mode);
+        kscreenMode->setId(_id);
+        kscreenMode->setName(_id);
+        kscreenMode->setSize(s0);
+        kscreenMode->setRefreshRate(60);
+        newmodes.insert(_id, kscreenMode);
+    }
+    {
+        QString _id = QString::number(22);
+        KScreen::ModePtr kscreenMode(new KScreen::Mode);
+        kscreenMode->setId(_id);
+        kscreenMode->setName(_id);
+        kscreenMode->setSize(s1);
+        kscreenMode->setRefreshRate(60);
+        newmodes.insert(_id, kscreenMode);
+    }
+    {
+        QString _id = QString::number(33);
+        KScreen::ModePtr kscreenMode(new KScreen::Mode);
+        kscreenMode->setId(_id);
+        kscreenMode->setName(_id);
+        kscreenMode->setSize(s2);
+        kscreenMode->setRefreshRate(60);
+        newmodes.insert(_id, kscreenMode);
+    }
+    return newmodes;
+}
+
+
+void TestModeListChange::initTestCase()
+{
+    qputenv("KSCREEN_LOGGING", "false");
+    qputenv("KSCREEN_BACKEND", "Fake");
+}
+
+void TestModeListChange::cleanupTestCase()
+{
+    BackendManager::instance()->shutdownBackend();
+}
+
+void TestModeListChange::modeListChange()
+{
+    //json file for the fake backend
+    qputenv("KSCREEN_BACKEND_ARGS", "TEST_DATA=" TEST_DATA "singleoutput.json");
+
+    const ConfigPtr config = getConfig();
+    QVERIFY(!config.isNull());
+
+    auto output = config->outputs().first();
+    QVERIFY(!output.isNull());
+    auto modelist = output->modes();
+
+    auto mode = modelist.first();
+    mode->setId(QStringLiteral("44"));
+    mode->setSize(QSize(880, 440));
+    output->setModes(modelist);
+
+    QCOMPARE(output->modes().first()->id(), QStringLiteral("44"));
+    QCOMPARE(output->modes().first()->size(), QSize(880, 440));
+    QVERIFY(!modelist.isEmpty());
+
+    ConfigMonitor::instance()->addConfig(config);
+    QSignalSpy outputChangedSpy(output.data(), &Output::outputChanged);
+    QVERIFY(outputChangedSpy.isValid());
+    QSignalSpy modesChangedSpy(output.data(), &Output::modesChanged);
+    QVERIFY(modesChangedSpy.isValid());
+
+    auto before = createModeList();
+    output->setModes(before);
+    QCOMPARE(modesChangedSpy.count(), 1);
+    output->setModes(before);
+    QCOMPARE(modesChangedSpy.count(), 1);
+    output->setModes(before);
+    QCOMPARE(modesChangedSpy.count(), 1);
+    QCOMPARE(output->modes().first()->size(), s0);
+    QCOMPARE(output->modes().first()->id(), QStringLiteral("11"));
+
+    auto after = createModeList();
+    auto firstmode = after.first();
+    QVERIFY(!firstmode.isNull());
+    QCOMPARE(firstmode->size(), s0);
+    QCOMPARE(firstmode->id(), QStringLiteral("11"));
+    firstmode->setSize(snew);
+    firstmode->setId(idnew);
+    output->setModes(after);
+    QCOMPARE(modesChangedSpy.count(), 2);
+
+    QString _id = QString::number(11);
+    KScreen::ModePtr kscreenMode(new KScreen::Mode);
+    kscreenMode->setId(_id);
+    kscreenMode->setName(_id);
+    kscreenMode->setSize(s0);
+    kscreenMode->setRefreshRate(60);
+    before.insert(_id, kscreenMode);
+    output->setModes(before);
+    QCOMPARE(modesChangedSpy.count(), 3);
+    QCOMPARE(outputChangedSpy.count(), modesChangedSpy.count());
+}
+
+
+QTEST_MAIN(TestModeListChange)
+
+#include "testmodelistchange.moc"
diff -Nru libkscreen-5.8.4/backends/xrandr/xrandroutput.cpp libkscreen-5.8.6/backends/xrandr/xrandroutput.cpp
--- libkscreen-5.8.4/backends/xrandr/xrandroutput.cpp	2016-11-22 11:18:06.000000000 +0100
+++ libkscreen-5.8.6/backends/xrandr/xrandroutput.cpp	2017-02-21 13:06:30.000000000 +0100
@@ -141,7 +141,7 @@
     if (isConnected() != (conn == XCB_RANDR_CONNECTION_CONNECTED)) {
         if (conn == XCB_RANDR_CONNECTION_CONNECTED) {
             // New monitor has been connected, refresh everything
-          init();
+            init();
         } else {
             // Disconnected
             m_connected = conn;
@@ -153,6 +153,14 @@
             m_modes.clear();
             m_preferredModes.clear();
         }
+    } else if (conn == XCB_RANDR_CONNECTION_CONNECTED) {
+        // the output changed in some way, let's update the internal
+        // list of modes, as it may have changed
+        XCB::OutputInfo outputInfo(m_id, XCB_TIME_CURRENT_TIME);
+        if (outputInfo) {
+            updateModes(outputInfo);
+        }
+
     }
 
     // A monitor has been enabled or disabled
@@ -310,7 +318,7 @@
 
     char *connectorType;
 
-    auto cookie = xcb_randr_get_output_property(XCB::connection(), outputId, atomType,
+    auto cookie = xcb_randr_get_output_property(XCB::connection(), outputId, atomType->atom,
                                                 XCB_ATOM_ANY, 0, 100, false, false);
     XCB::ScopedPointer<xcb_randr_get_output_property_reply_t> reply(xcb_randr_get_output_property_reply(XCB::connection(), cookie, NULL));
     if (!reply) {
diff -Nru libkscreen-5.8.4/CMakeLists.txt libkscreen-5.8.6/CMakeLists.txt
--- libkscreen-5.8.4/CMakeLists.txt	2016-11-22 11:18:06.000000000 +0100
+++ libkscreen-5.8.6/CMakeLists.txt	2017-02-21 13:06:30.000000000 +0100
@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 2.8.12)
 
 project(libkscreen)
-set(PROJECT_VERSION "5.8.4")
+set(PROJECT_VERSION "5.8.6")
 
 find_package(ECM 5.14.0 REQUIRED NO_MODULE)
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
diff -Nru libkscreen-5.8.4/debian/changelog libkscreen-5.8.6/debian/changelog
--- libkscreen-5.8.4/debian/changelog	2016-11-23 18:37:14.000000000 +0100
+++ libkscreen-5.8.6/debian/changelog	2017-03-13 11:33:19.000000000 +0100
@@ -1,3 +1,17 @@
+libkscreen (4:5.8.6-1) experimental; urgency=medium
+
+  * New upstream release (5.8.6)
+    + Disable kscreen.log logging by default (Closes: 846940)
+
+ -- Maximiliano Curia <maxy@debian.org>  Mon, 13 Mar 2017 11:33:19 +0100
+
+libkscreen (4:5.8.5-1) experimental; urgency=medium
+
+  * New upstream release (5.8.5).
+  * Update symbols files.
+
+ -- Maximiliano Curia <maxy@debian.org>  Fri, 30 Dec 2016 18:46:19 +0100
+
 libkscreen (4:5.8.4-1) unstable; urgency=medium
 
   [ Automatic packaging ]
diff -Nru libkscreen-5.8.4/debian/libkf5screen7.symbols libkscreen-5.8.6/debian/libkf5screen7.symbols
--- libkscreen-5.8.4/debian/libkf5screen7.symbols	2016-11-23 18:37:14.000000000 +0100
+++ libkscreen-5.8.6/debian/libkf5screen7.symbols	2017-03-13 11:33:19.000000000 +0100
@@ -1,4 +1,4 @@
-# SymbolsHelper-Confirmed: 4:5.8.0 amd64 armhf i386
+# SymbolsHelper-Confirmed: 4:5.8.5 amd64
 libKF5Screen.so.7 libkf5screen7 #MINVER#, libkf5screen-bin (>= 4:5.6.2~)
  _ZN7KScreen13ConfigMonitor11qt_metacallEN11QMetaObject4CallEiPPv@Base 5.1.1
  _ZN7KScreen13ConfigMonitor11qt_metacastEPKc@Base 5.1.1
@@ -171,6 +171,7 @@
  _ZN7KScreen6Output11qt_metacastEPKc@Base 5.1.1
  _ZN7KScreen6Output11setRotationENS0_8RotationE@Base 5.1.1
  _ZN7KScreen6Output11sizeChangedEv@Base 4:5.4.0
+ _ZN7KScreen6Output12modesChangedEv@Base 4:5.8.5
  _ZN7KScreen6Output12setConnectedEb@Base 5.1.1
  _ZN7KScreen6Output13clonesChangedEv@Base 5.1.1
  _ZN7KScreen6Output13outputChangedEv@Base 5.1.1
@@ -185,6 +186,7 @@
  _ZN7KScreen6Output5applyERK14QSharedPointerIS0_E@Base 5.1.1
  _ZN7KScreen6Output5setIdEi@Base 5.1.1
  _ZN7KScreen6Output6setPosERK6QPoint@Base 5.1.1
+ _ZN7KScreen6Output7Private15compareModeListERK4QMapI7QString14QSharedPointerINS_4ModeEEES9_@Base 4:5.8.5
  _ZN7KScreen6Output7setEdidERK10QByteArray@Base 5.1.1
  _ZN7KScreen6Output7setIconERK7QString@Base 5.1.1
  _ZN7KScreen6Output7setNameERK7QString@Base 5.1.1
diff -Nru libkscreen-5.8.4/debian/patches/make_kwayland_optional.diff libkscreen-5.8.6/debian/patches/make_kwayland_optional.diff
--- libkscreen-5.8.4/debian/patches/make_kwayland_optional.diff	2016-11-23 18:37:14.000000000 +0100
+++ libkscreen-5.8.6/debian/patches/make_kwayland_optional.diff	2017-03-13 11:33:19.000000000 +0100
@@ -9,11 +9,9 @@
  tests/CMakeLists.txt     |  4 +++-
  4 files changed, 27 insertions(+), 19 deletions(-)
 
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 8515e95..a66cf5b 100644
 --- a/CMakeLists.txt
 +++ b/CMakeLists.txt
-@@ -20,7 +20,7 @@ set(REQUIRED_QT_VERSION 5.4.0)
+@@ -20,7 +20,7 @@
  find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Core DBus Gui Test X11Extras)
  
  # Wayland backend
@@ -22,8 +20,6 @@
  add_feature_info("KF5Wayland" KF5Wayland_FOUND "Required for building libkscreen's KWayland backend")
  
  # xrandr backend
-diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
-index 9f8cea7..3a3bc20 100644
 --- a/autotests/CMakeLists.txt
 +++ b/autotests/CMakeLists.txt
 @@ -1,6 +1,9 @@
@@ -37,9 +33,9 @@
  
  macro(KSCREEN_ADD_TEST)
      foreach(_testname ${ARGN})
-@@ -23,24 +26,25 @@ kscreen_add_test(testinprocess)
- kscreen_add_test(testbackendloader)
+@@ -24,24 +27,25 @@
  kscreen_add_test(testlog)
+ kscreen_add_test(testmodelistchange)
  
 -set(KSCREEN_WAYLAND_LIBS
 -    KF5::WaylandServer KF5::WaylandClient
@@ -51,35 +47,36 @@
 -    ${CMAKE_SOURCE_DIR}/tests/kwayland/waylandtestserver.cpp
 -)
 -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../backends/kwayland)
+-
+-kscreen_add_test(testkwaylandbackend)
+-kscreen_add_test(testkwaylandconfig)
+-kscreen_add_test(testkwaylanddpms)
+-
+-set(KSCREEN_WAYLAND_LIBS "")
+-set(KSCREEN_WAYLAND_SRCS "")
+-
 +if(${KF5Wayland_FOUND})
 +    set(KSCREEN_WAYLAND_LIBS
 +        KF5::WaylandServer KF5::WaylandClient
 +    )
- 
--kscreen_add_test(testkwaylandbackend)
--kscreen_add_test(testkwaylandconfig)
--kscreen_add_test(testkwaylanddpms)
++
 +    # For WaylandConfigReader and TestServer
 +    set(KSCREEN_WAYLAND_SRCS
 +        ${CMAKE_SOURCE_DIR}/tests/kwayland/waylandconfigreader.cpp
 +        ${CMAKE_SOURCE_DIR}/tests/kwayland/waylandtestserver.cpp
 +    )
 +    include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../backends/kwayland)
- 
--set(KSCREEN_WAYLAND_LIBS "")
--set(KSCREEN_WAYLAND_SRCS "")
++
 +    kscreen_add_test(testkwaylandbackend)
 +    kscreen_add_test(testkwaylandconfig)
 +    kscreen_add_test(testkwaylanddpms)
- 
++
 +    set(KSCREEN_WAYLAND_LIBS "")
 +    set(KSCREEN_WAYLAND_SRCS "")
 +endif()
  
  if (ENABLE_XRANDR_TESTS)
      kscreen_add_test(textxrandr)
-diff --git a/backends/CMakeLists.txt b/backends/CMakeLists.txt
-index 3563e13..5f44182 100644
 --- a/backends/CMakeLists.txt
 +++ b/backends/CMakeLists.txt
 @@ -1,6 +1,8 @@
@@ -92,8 +89,6 @@
  
  if(${XCB_RANDR_FOUND})
      message(STATUS "Will build xrandr backend.")
-diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
-index 1489d21..e82f7f7 100644
 --- a/tests/CMakeLists.txt
 +++ b/tests/CMakeLists.txt
 @@ -1,4 +1,6 @@
diff -Nru libkscreen-5.8.4/src/log.cpp libkscreen-5.8.6/src/log.cpp
--- libkscreen-5.8.4/src/log.cpp	2016-11-22 11:18:06.000000000 +0100
+++ libkscreen-5.8.6/src/log.cpp	2017-02-21 13:06:30.000000000 +0100
@@ -57,7 +57,7 @@
 {
   public:
       QString context;
-      bool enabled = true;
+      bool enabled = false;
       QString logFile;
 };
 
@@ -68,11 +68,13 @@
 
     if (qEnvironmentVariableIsSet(logging_env)) {
         const QString logging_env_value = qgetenv(logging_env).constData();
-        if (logging_env_value == QStringLiteral("0") || logging_env_value.toLower() == QStringLiteral("false")) {
-            d->enabled = false;
-            return;
+        if (logging_env_value != QStringLiteral("0") && logging_env_value.toLower() != QStringLiteral("false")) {
+            d->enabled = true;
         }
     }
+    if (!d->enabled) {
+         return;
+    }
     d->logFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kscreen/kscreen.log";
 
     QLoggingCategory::setFilterRules("kscreen.*=true");
diff -Nru libkscreen-5.8.4/src/output.cpp libkscreen-5.8.6/src/output.cpp
--- libkscreen-5.8.4/src/output.cpp	2016-11-22 11:18:06.000000000 +0100
+++ libkscreen-5.8.6/src/output.cpp	2017-02-21 13:06:30.000000000 +0100
@@ -69,6 +69,7 @@
     }
 
     QString biggestMode(const ModeList& modes) const;
+    bool compareModeList(const ModeList& before, const ModeList& after);
 
     int id;
     QString name;
@@ -90,6 +91,32 @@
     mutable QPointer<Edid> edid;
 };
 
+bool Output::Private::compareModeList(const ModeList& before, const ModeList &after)
+{
+    if (before.keys() != after.keys()) {
+        return false;
+    }
+    for (const QString &key : before.keys()) {
+        const auto mb = before.value(key);
+        const auto ma = after.value(key);
+        if (mb->id() != ma->id()) {
+            return false;
+        }
+        if (mb->size() != ma->size()) {
+            return false;
+        }
+        if (mb->refreshRate() != ma->refreshRate()) {
+            return false;
+        }
+        if (mb->name() != ma->name()) {
+            return false;
+        }
+    }
+    // They're the same
+    return true;
+}
+
+
 QString Output::Private::biggestMode(const ModeList& modes) const
 {
     int area, total = 0;
@@ -221,7 +248,12 @@
 
 void Output::setModes(const ModeList &modes)
 {
+    bool changed = !d->compareModeList(d->modeList, modes);
     d->modeList = modes;
+    if (changed) {
+        emit modesChanged();
+        emit outputChanged();
+    }
 }
 
 QString Output::currentModeId() const
@@ -494,8 +526,10 @@
         changes << &Output::clonesChanged;
         setClones(other->d->clones);;
     }
+    if (!d->compareModeList(d->modeList, other->d->modeList)) {
+        changes << &Output::outputChanged;
+    }
 
-    // Non-notifyable changes
     setPreferredModes(other->d->preferredModes);
     ModeList modes;
     Q_FOREACH (const ModePtr &otherMode, other->modes()) {
@@ -503,6 +537,7 @@
     }
     setModes(modes);
 
+    // Non-notifyable changes
     if (other->d->edid) {
         delete d->edid;
         d->edid = other->d->edid->clone();
diff -Nru libkscreen-5.8.4/src/output.h libkscreen-5.8.6/src/output.h
--- libkscreen-5.8.4/src/output.h	2016-11-22 11:18:06.000000000 +0100
+++ libkscreen-5.8.6/src/output.h	2017-02-21 13:06:30.000000000 +0100
@@ -46,7 +46,7 @@
         Q_PROPERTY(QString name READ name WRITE setName NOTIFY outputChanged)
         Q_PROPERTY(Type type READ type WRITE setType NOTIFY outputChanged)
         Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY outputChanged)
-        Q_PROPERTY(ModeList modes READ modes CONSTANT)
+        Q_PROPERTY(ModeList modes READ modes NOTIFY modesChanged)
         Q_PROPERTY(QPoint pos READ pos WRITE setPos NOTIFY posChanged)
         Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY sizeChanged)
         Q_PROPERTY(Rotation rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
@@ -204,6 +204,14 @@
         void isPrimaryChanged();
         void clonesChanged();
 
+        /** The mode list changed.
+         *
+         * This may happen when a mode is added or changed.
+         *
+         * @since 5.8.3
+         */
+        void modesChanged();
+
     private:
         Q_DISABLE_COPY(Output)
 

Reply to: