Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libkscreen2 for openSUSE:Factory checked in at 2022-02-07 23:37:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libkscreen2 (Old) and /work/SRC/openSUSE:Factory/.libkscreen2.new.1898 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libkscreen2" Mon Feb 7 23:37:04 2022 rev:133 rq:951886 version:5.24.0 Changes: -------- --- /work/SRC/openSUSE:Factory/libkscreen2/libkscreen2.changes 2022-01-11 21:14:25.788754576 +0100 +++ /work/SRC/openSUSE:Factory/.libkscreen2.new.1898/libkscreen2.changes 2022-02-07 23:37:21.762739534 +0100 @@ -1,0 +2,37 @@ +Sat Feb 5 19:50:59 UTC 2022 - Fabian Vogt <fab...@ritter-vogt.de> + +- Update to 5.24.0 + * New bugfix release + * For more details please see: + * https://kde.org/announcements/plasma/5/5.24.0 +- Changes since 5.23.90: + * backends/kwayland: Use output name to guess output type + * Update required PlasmaWaylandProtocols version + +------------------------------------------------------------------- +Thu Jan 13 20:30:22 UTC 2022 - Fabian Vogt <fab...@ritter-vogt.de> + +- Update to 5.23.90 + * New feature release + * For more details please see: + * https://kde.org/announcements/plasma/5/5.23.90 +- Changes since 5.23.5: + * GetConfiguration: ensure to set explicitLogicalSize for returned outputs + * Add KScreen::Config::Feature::SynchronousOutputChanges + * Wayland: Wait for KWin reply before returning from setConfig + * Fix some clazy warnings + * Under X11 ignore per-screen scale to compute logicalSize + * Enable GitLab CI + * Add KScreen::Output::typeName + * wayland: Issue a configChanged when the primary changes + * Do not issue SetConfigOperations with bogus primary states + * Fix using correct log level by using systemd unit (kde#444084) + * wayland: Properly choose interface versions + * Implement Primary Displays on the wayland session + * Add support to primary into the kscreen-doctor tool + * XrandR: Fix impossibilty to change resolution in VirtualBox (kde#407058) + * Fix autorotate when "only in tablet mode" is selected (kde#428626) + * Add .kde-ci.yml + * fix all the new settings (kde#442520) + +------------------------------------------------------------------- Old: ---- libkscreen-5.23.5.tar.xz libkscreen-5.23.5.tar.xz.sig New: ---- libkscreen-5.24.0.tar.xz libkscreen-5.24.0.tar.xz.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libkscreen2.spec ++++++ --- /var/tmp/diff_new_pack.PLoYtj/_old 2022-02-07 23:37:22.386735334 +0100 +++ /var/tmp/diff_new_pack.PLoYtj/_new 2022-02-07 23:37:22.390735306 +0100 @@ -16,10 +16,10 @@ # -%bcond_without lang +%bcond_without released %define lname libKF5Screen7 Name: libkscreen2 -Version: 5.23.5 +Version: 5.24.0 Release: 0 # Full Plasma 5 version (e.g. 5.8.95) %{!?_plasma5_bugfix: %define _plasma5_bugfix %{version}} @@ -29,9 +29,9 @@ License: GPL-2.0-or-later Group: System/GUI/KDE URL: http://www.kde.org -Source: https://download.kde.org/stable/plasma/%{version}/libkscreen-%{version}.tar.xz -%if %{with lang} -Source1: https://download.kde.org/stable/plasma/%{version}/libkscreen-%{version}.tar.xz.sig +Source: libkscreen-%{version}.tar.xz +%if %{with released} +Source1: libkscreen-%{version}.tar.xz.sig Source2: plasma.keyring %endif BuildRequires: cmake >= 3.16 @@ -92,6 +92,15 @@ %postun -n %{lname} -p /sbin/ldconfig +%post plugin +%{systemd_user_post plasma-kscreen.service} + +%preun plugin +%{systemd_user_preun plasma-kscreen.service} + +%postun plugin +%{systemd_user_postun plasma-kscreen.service} + %files plugin %license LICENSES/* %{_kf5_bindir}/kscreen-doctor @@ -99,6 +108,7 @@ %{_kf5_libexecdir}/ %{_kf5_sharedir}/dbus-1/services/org.kde.kscreen.service %{_kf5_debugdir}/libkscreen.categories +%{_userunitdir}/plasma-kscreen.service %files -n %{lname} %license LICENSES/* ++++++ libkscreen-5.23.5.tar.xz -> libkscreen-5.24.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/.arcconfig new/libkscreen-5.24.0/.arcconfig --- old/libkscreen-5.23.5/.arcconfig 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/.arcconfig 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +0,0 @@ -{ - "phabricator.uri" : "https://phabricator.kde.org/" -} - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/.gitlab-ci.yml new/libkscreen-5.24.0/.gitlab-ci.yml --- old/libkscreen-5.23.5/.gitlab-ci.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/libkscreen-5.24.0/.gitlab-ci.yml 2022-02-03 15:36:03.000000000 +0100 @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: None +# SPDX-License-Identifier: CC0-1.0 + +include: + - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml + - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/.kde-ci.yml new/libkscreen-5.24.0/.kde-ci.yml --- old/libkscreen-5.23.5/.kde-ci.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/libkscreen-5.24.0/.kde-ci.yml 2022-02-03 15:36:03.000000000 +0100 @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: None +# SPDX-License-Identifier: CC0-1.0 + +Dependencies: +- 'on': ['@all'] + 'require': + 'frameworks/extra-cmake-modules': '@latest' + 'frameworks/kwayland': '@latest' + 'plasma/kwayland-server': '@same' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/CMakeLists.txt new/libkscreen-5.24.0/CMakeLists.txt --- old/libkscreen-5.23.5/CMakeLists.txt 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/CMakeLists.txt 2022-02-03 15:36:03.000000000 +0100 @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) project(libkscreen) -set(PROJECT_VERSION "5.23.5") +set(PROJECT_VERSION "5.24.0") set(QT_MIN_VERSION "5.15.0") set(KF5_MIN_VERSION "5.86") @@ -34,7 +34,7 @@ find_package(KF5Wayland ${KF5_MIN_VERSION} CONFIG REQUIRED) add_feature_info("KF5Wayland" KF5Wayland_FOUND "Required for building libkscreen's KWayland backend") -find_package(PlasmaWaylandProtocols 1.4.0 CONFIG) +find_package(PlasmaWaylandProtocols 1.6.0 CONFIG) set_package_properties(PlasmaWaylandProtocols PROPERTIES TYPE REQUIRED) # Wayland backend diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/CMakePresets.json new/libkscreen-5.24.0/CMakePresets.json --- old/libkscreen-5.23.5/CMakePresets.json 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/CMakePresets.json 2022-02-03 15:36:03.000000000 +0100 @@ -12,6 +12,17 @@ } }, { + "name": "dev-disable-deprecated", + "displayName": "Build as without deprecated methods", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build-disable-deprecated", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_CXX_FLAGS_INIT": "-DQT_DISABLE_DEPRECATED_BEFORE=0x060000 -DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x060000" + } + }, + { "name": "asan", "displayName": "Build with Asan support.", "generator": "Ninja", @@ -29,7 +40,7 @@ "binaryDir": "${sourceDir}/build-unity", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", - "USE_UNITY_CMAKE_SUPPORT": "ON", + "CMAKE_UNITY_BUILD": "ON", "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" } }, @@ -72,6 +83,18 @@ "configurePreset": "dev" }, { + "name": "asan", + "configurePreset": "asan" + }, + { + "name": "dev-disable-deprecated", + "configurePreset": "dev-disable-deprecated" + }, + { + "name": "unity", + "configurePreset": "unity" + }, + { "name": "clazy", "configurePreset": "clazy", "environment": { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/fake/CMakeLists.txt new/libkscreen-5.24.0/backends/fake/CMakeLists.txt --- old/libkscreen-5.23.5/backends/fake/CMakeLists.txt 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/fake/CMakeLists.txt 2022-02-03 15:36:03.000000000 +0100 @@ -6,6 +6,8 @@ set(fake_SRCS fake.cpp parser.cpp + fake.h + parser.h ) qt_add_dbus_adaptor(fake_SRCS ${CMAKE_SOURCE_DIR}/interfaces/org.kde.KScreen.FakeBackend.xml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/kwayland/CMakeLists.txt new/libkscreen-5.24.0/backends/kwayland/CMakeLists.txt --- old/libkscreen-5.23.5/backends/kwayland/CMakeLists.txt 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/kwayland/CMakeLists.txt 2022-02-03 15:36:03.000000000 +0100 @@ -26,6 +26,10 @@ BASENAME kde-output-management-v2 ) +ecm_add_qtwayland_client_protocol(wayland_SRCS + PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/kde-primary-output-v1.xml + BASENAME kde-primary-output-v1 +) add_library(KSC_KWayland MODULE ${wayland_SRCS}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/kwayland/waylandbackend.cpp new/libkscreen-5.24.0/backends/kwayland/waylandbackend.cpp --- old/libkscreen-5.23.5/backends/kwayland/waylandbackend.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/kwayland/waylandbackend.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -53,7 +53,13 @@ if (!newconfig) { return; } + // wait for KWin reply + QEventLoop loop; + + connect(m_internalConfig, &WaylandConfig::configChanged, &loop, &QEventLoop::quit); m_internalConfig->applyConfig(newconfig); + + loop.exec(); } QByteArray WaylandBackend::edid(int outputId) const diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/kwayland/waylandconfig.cpp new/libkscreen-5.24.0/backends/kwayland/waylandconfig.cpp --- old/libkscreen-5.23.5/backends/kwayland/waylandconfig.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/kwayland/waylandconfig.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -121,10 +121,26 @@ connect(m_registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this](const QByteArray &interface, quint32 name, quint32 version) { if (interface == WaylandOutputDevice::interface()->name) { - addOutput(name, version); + addOutput(name, std::min(2u, version)); } if (interface == WaylandOutputManagement::interface()->name) { - m_outputManagement = new WaylandOutputManagement(m_registry->registry(), name, version); + m_outputManagement = new WaylandOutputManagement(m_registry->registry(), name, std::min(2u, version)); + } + if (interface == WaylandPrimaryOutput::interface()->name) { + m_primaryOutput.reset(new WaylandPrimaryOutput(m_registry->registry(), name, std::min(1u, version))); + connect(m_primaryOutput.data(), &WaylandPrimaryOutput::primaryOutputChanged, this, [this](const QString &name) { + if (m_primaryOutputName == name) { + return; + } + + m_primaryOutputName = name; + for (auto output : qAsConst(m_outputMap)) { + output->setPrimary(output->outputName() == name); + } + if (!m_blockSignals) { + Q_EMIT configChanged(); + } + }); } }); @@ -158,6 +174,7 @@ QObject::disconnect(*connection); delete connection; + device->setPrimary(m_primaryOutputName == device->outputName()); m_initializingOutputs.removeOne(device); m_outputMap.insert(device->id(), device); checkInitialized(); @@ -224,7 +241,8 @@ { m_kscreenConfig->setScreen(m_screen->toKScreenScreen(m_kscreenConfig)); - const auto features = Config::Feature::Writable | Config::Feature::PerOutputScaling | Config::Feature::AutoRotation | Config::Feature::TabletMode; + const auto features = Config::Feature::Writable | Config::Feature::PerOutputScaling | Config::Feature::AutoRotation | Config::Feature::TabletMode + | Config::Feature::PrimaryDisplay | Config::Feature::SynchronousOutputChanges; m_kscreenConfig->setSupportedFeatures(features); m_kscreenConfig->setValid(m_connection->display()); @@ -239,20 +257,15 @@ } } - // Add KScreen::Outputs that aren't in the list yet, handle primaryOutput + // Add KScreen::Outputs that aren't in the list yet KScreen::OutputList kscreenOutputs = m_kscreenConfig->outputs(); for (const auto &output : m_outputMap) { - KScreen::OutputPtr kscreenOutput = kscreenOutputs[output->id()]; + KScreen::OutputPtr &kscreenOutput = kscreenOutputs[output->id()]; if (!kscreenOutput) { kscreenOutput = output->toKScreenOutput(); - kscreenOutputs.insert(kscreenOutput->id(), kscreenOutput); - } - if (kscreenOutput && m_outputMap.count() == 1) { - kscreenOutput->setPrimary(true); - } else if (m_outputMap.count() > 1) { - // primaryScreen concept doesn't exist in kwayland, so we don't set one + } else { + output->updateKScreenOutput(kscreenOutput); } - output->updateKScreenOutput(kscreenOutput); } m_kscreenConfig->setOutputs(kscreenOutputs); @@ -276,6 +289,16 @@ m_kscreenPendingConfig = nullptr; } +WaylandOutputDevice *WaylandConfig::findOutputDevice(struct ::kde_output_device_v2 *outputdevice) const +{ + for (WaylandOutputDevice *device : m_outputMap) { + if (device->object() == outputdevice) { + return device; + } + } + return nullptr; +} + void WaylandConfig::applyConfig(const KScreen::ConfigPtr &newConfig) { using namespace KWayland::Client; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/kwayland/waylandconfig.h new/libkscreen-5.24.0/backends/kwayland/waylandconfig.h --- old/libkscreen-5.23.5/backends/kwayland/waylandconfig.h 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/kwayland/waylandconfig.h 2022-02-03 15:36:03.000000000 +0100 @@ -15,6 +15,8 @@ #include <QSize> #include <QSocketNotifier> +struct kde_output_device_v2; + namespace KWayland { namespace Client @@ -29,6 +31,7 @@ namespace KScreen { class Output; +class WaylandPrimaryOutput; class WaylandOutputDevice; class WaylandScreen; class WaylandOutputManagement; @@ -58,6 +61,7 @@ QMap<int, WaylandOutputDevice *> outputMap() const; void applyConfig(const KScreen::ConfigPtr &newConfig); + WaylandOutputDevice *findOutputDevice(struct ::kde_output_device_v2 *outputdevice) const; bool isReady() const; @@ -84,9 +88,11 @@ KWayland::Client::Registry *m_registry; WaylandOutputManagement *m_outputManagement = nullptr; + QScopedPointer<WaylandPrimaryOutput> m_primaryOutput; // KWayland names as keys QMap<int, WaylandOutputDevice *> m_outputMap; + QString m_primaryOutputName; // KWayland names QList<WaylandOutputDevice *> m_initializingOutputs; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/kwayland/waylandoutputdevice.cpp new/libkscreen-5.24.0/backends/kwayland/waylandoutputdevice.cpp --- old/libkscreen-5.23.5/backends/kwayland/waylandoutputdevice.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/kwayland/waylandoutputdevice.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -170,7 +170,7 @@ output->setId(m_id); output->setEnabled(enabled()); output->setConnected(true); - output->setPrimary(true); // FIXME: wayland doesn't have the concept of a primary display + output->setPrimary(m_isPrimary); output->setName(name()); output->setSizeMm(m_physicalSize); output->setPos(m_pos); @@ -182,7 +182,7 @@ QSize currentSize = m_mode->size(); output->setSize(output->isHorizontal() ? currentSize : currentSize.transposed()); output->setScale(m_factor); - output->setType(Utils::guessOutputType(m_model, m_model)); + output->setType(Utils::guessOutputType(m_outputName, m_outputName)); output->setCapabilities(static_cast<Output::Capabilities>(static_cast<uint32_t>(m_flags))); output->setOverscan(m_overscan); output->setVrrPolicy(static_cast<Output::VrrPolicy>(m_vrr_policy)); @@ -257,6 +257,11 @@ changed = true; } + if (output->isPrimary()) { + wlConfig->set_primary_output(object()); + changed = true; + } + return changed; } @@ -271,12 +276,27 @@ return QStringLiteral("%1 %2").arg(m_manufacturer, m_model); } +QString WaylandOutputDevice::outputName() const +{ + return m_outputName; +} + QDebug operator<<(QDebug dbg, const WaylandOutputDevice *output) { dbg << "WaylandOutput(Id:" << output->id() << ", Name:" << QString(output->manufacturer() + QLatin1Char(' ') + output->model()) << ")"; return dbg; } +bool WaylandOutputDevice::isPrimary() const +{ + return m_isPrimary; +} + +void WaylandOutputDevice::setPrimary(bool primary) +{ + m_isPrimary = primary; +} + void WaylandOutputDevice::kde_output_device_v2_done() { Q_EMIT done(); @@ -332,6 +352,11 @@ m_rgbRange = rgb_range; } +void WaylandOutputDevice::kde_output_device_v2_name(const QString &outputName) +{ + m_outputName = outputName; +} + QByteArray WaylandOutputDevice::edid() const { return m_edid; @@ -396,5 +421,3 @@ { return m_rgbRange; } - -#include "waylandoutputdevice.moc" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/kwayland/waylandoutputdevice.h new/libkscreen-5.24.0/backends/kwayland/waylandoutputdevice.h --- old/libkscreen-5.23.5/backends/kwayland/waylandoutputdevice.h 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/kwayland/waylandoutputdevice.h 2022-02-03 15:36:03.000000000 +0100 @@ -32,6 +32,7 @@ bool enabled() const; int id() const; QString name() const; + QString outputName() const; QString model() const; QString manufacturer() const; qreal scale() const; @@ -47,9 +48,15 @@ void updateKScreenOutput(OutputPtr &output); void updateKScreenModes(OutputPtr &output); + bool isPrimary() const; + void setPrimary(bool primary); bool setWlConfig(WaylandOutputConfiguration *wlConfig, const KScreen::OutputPtr &output); QString modeId() const; + QString uuid() const + { + return m_uuid; + } Q_SIGNALS: void done(); @@ -76,6 +83,7 @@ void kde_output_device_v2_overscan(uint32_t overscan) override; void kde_output_device_v2_vrr_policy(uint32_t vrr_policy) override; void kde_output_device_v2_rgb_range(uint32_t rgb_range) override; + void kde_output_device_v2_name(const QString &name) override; private: QString modeName(const WaylandOutputDeviceMode *m) const; @@ -96,11 +104,13 @@ int32_t m_enabled; QString m_uuid; QString m_serialNumber; + QString m_outputName; QString m_eisaId; uint32_t m_flags; uint32_t m_overscan; uint32_t m_vrr_policy; uint32_t m_rgbRange; + bool m_isPrimary = false; }; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/kwayland/waylandoutputmanagement.cpp new/libkscreen-5.24.0/backends/kwayland/waylandoutputmanagement.cpp --- old/libkscreen-5.23.5/backends/kwayland/waylandoutputmanagement.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/kwayland/waylandoutputmanagement.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -5,15 +5,15 @@ * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "waylandoutputmanagement.h" +#include "waylandconfig.h" #include <QDebug> namespace KScreen { WaylandOutputManagement::WaylandOutputManagement(struct ::wl_registry *registry, int id, int version) : QObject() - , QtWayland::kde_output_management_v2() + , QtWayland::kde_output_management_v2(registry, id, version) { - init(registry, id, version); } WaylandOutputConfiguration *WaylandOutputManagement::createConfiguration() @@ -37,4 +37,14 @@ Q_EMIT failed(); } +WaylandPrimaryOutput::WaylandPrimaryOutput(struct ::wl_registry *registry, int id, int version) + : QObject() + , QtWayland::kde_primary_output_v1(registry, id, version) +{ +} + +void WaylandPrimaryOutput::kde_primary_output_v1_primary_output(const QString &outputName) +{ + Q_EMIT primaryOutputChanged(outputName); +} } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/kwayland/waylandoutputmanagement.h new/libkscreen-5.24.0/backends/kwayland/waylandoutputmanagement.h --- old/libkscreen-5.23.5/backends/kwayland/waylandoutputmanagement.h 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/kwayland/waylandoutputmanagement.h 2022-02-03 15:36:03.000000000 +0100 @@ -8,12 +8,16 @@ #define WAYLANDOUTPUTMANAGEMENT_H #include "qwayland-kde-output-management-v2.h" +#include "qwayland-kde-primary-output-v1.h" #include <QObject> #include <QSize> namespace KScreen { +class WaylandConfig; +class WaylandOutputDevice; + class WaylandOutputConfiguration : public QObject, public QtWayland::kde_output_configuration_v2 { Q_OBJECT @@ -38,6 +42,18 @@ WaylandOutputConfiguration *createConfiguration(); }; +class WaylandPrimaryOutput : public QObject, public QtWayland::kde_primary_output_v1 +{ + Q_OBJECT +public: + WaylandPrimaryOutput(struct ::wl_registry *registry, int id, int version); + +Q_SIGNALS: + void primaryOutputChanged(const QString &outputName); + +protected: + void kde_primary_output_v1_primary_output(const QString &outputName) override; +}; } #endif // WAYLANDOUTPUTMANAGEMENT_H diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/qscreen/CMakeLists.txt new/libkscreen-5.24.0/backends/qscreen/CMakeLists.txt --- old/libkscreen-5.23.5/backends/qscreen/CMakeLists.txt 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/qscreen/CMakeLists.txt 2022-02-03 15:36:03.000000000 +0100 @@ -2,15 +2,19 @@ ${CMAKE_BUILD_DIR} ) -set(qscreen_SRCS + +add_library(KSC_QScreen MODULE) +target_sources(KSC_QScreen PRIVATE qscreenbackend.cpp qscreenconfig.cpp qscreenscreen.cpp qscreenoutput.cpp + qscreenbackend.h + qscreenconfig.h + qscreenscreen.h + qscreenoutput.h ) -add_library(KSC_QScreen MODULE ${qscreen_SRCS}) - set_target_properties(KSC_QScreen PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/kf5/kscreen") set_target_properties(KSC_QScreen PROPERTIES PREFIX "") target_link_libraries(KSC_QScreen Qt::Core diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xcbeventlistener.cpp new/libkscreen-5.24.0/backends/xcbeventlistener.cpp --- old/libkscreen-5.23.5/backends/xcbeventlistener.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xcbeventlistener.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -139,6 +139,8 @@ } qCDebug(KSCREEN_XCB_HELPER) << "RRScreenChangeNotify"; + qCDebug(KSCREEN_XCB_HELPER) << "\tTimestamp: " << e2->timestamp; + qCDebug(KSCREEN_XCB_HELPER) << "\tConfig_timestamp: " << e2->config_timestamp; qCDebug(KSCREEN_XCB_HELPER) << "\tWindow:" << e2->request_window; qCDebug(KSCREEN_XCB_HELPER) << "\tRoot:" << e2->root; qCDebug(KSCREEN_XCB_HELPER) << "\tRotation: " << rotationToString((xcb_randr_rotation_t)e2->rotation); @@ -157,15 +159,17 @@ if (randrEvent->subCode == XCB_RANDR_NOTIFY_CRTC_CHANGE) { xcb_randr_crtc_change_t crtc = randrEvent->u.cc; qCDebug(KSCREEN_XCB_HELPER) << "RRNotify_CrtcChange"; + qCDebug(KSCREEN_XCB_HELPER) << "\tTimestamp: " << crtc.timestamp; qCDebug(KSCREEN_XCB_HELPER) << "\tCRTC: " << crtc.crtc; qCDebug(KSCREEN_XCB_HELPER) << "\tMode: " << crtc.mode; qCDebug(KSCREEN_XCB_HELPER) << "\tRotation: " << rotationToString((xcb_randr_rotation_t)crtc.rotation); qCDebug(KSCREEN_XCB_HELPER) << "\tGeometry: " << crtc.x << crtc.y << crtc.width << crtc.height; - Q_EMIT crtcChanged(crtc.crtc, crtc.mode, (xcb_randr_rotation_t)crtc.rotation, QRect(crtc.x, crtc.y, crtc.width, crtc.height)); + Q_EMIT crtcChanged(crtc.crtc, crtc.mode, (xcb_randr_rotation_t)crtc.rotation, QRect(crtc.x, crtc.y, crtc.width, crtc.height), crtc.timestamp); } else if (randrEvent->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) { xcb_randr_output_change_t output = randrEvent->u.oc; qCDebug(KSCREEN_XCB_HELPER) << "RRNotify_OutputChange"; + qCDebug(KSCREEN_XCB_HELPER) << "\tTimestamp: " << output.timestamp; qCDebug(KSCREEN_XCB_HELPER) << "\tOutput: " << output.output; qCDebug(KSCREEN_XCB_HELPER) << "\tCRTC: " << output.crtc; qCDebug(KSCREEN_XCB_HELPER) << "\tMode: " << output.mode; @@ -181,6 +185,7 @@ xcb_get_atom_name_reply(QX11Info::connection(), xcb_get_atom_name(QX11Info::connection(), property.atom), nullptr)); qCDebug(KSCREEN_XCB_HELPER) << "RRNotify_OutputProperty (ignored)"; + qCDebug(KSCREEN_XCB_HELPER) << "\tTimestamp: " << property.timestamp; qCDebug(KSCREEN_XCB_HELPER) << "\tOutput: " << property.output; qCDebug(KSCREEN_XCB_HELPER) << "\tProperty: " << xcb_get_atom_name_name(reply.data()); qCDebug(KSCREEN_XCB_HELPER) << "\tState (newValue, Deleted): " << property.status; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xcbeventlistener.h new/libkscreen-5.24.0/backends/xcbeventlistener.h --- old/libkscreen-5.23.5/backends/xcbeventlistener.h 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xcbeventlistener.h 2022-02-03 15:36:03.000000000 +0100 @@ -30,7 +30,7 @@ void outputsChanged(); /* Emitted only when XRandR 1.2 or newer is available */ - void crtcChanged(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_rotation_t rotation, const QRect &geom); + void crtcChanged(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_rotation_t rotation, const QRect &geom, xcb_timestamp_t timestamp); void outputChanged(xcb_randr_output_t output, xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t connection); void outputPropertyChanged(xcb_randr_output_t output); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xrandr/CMakeLists.txt new/libkscreen-5.24.0/backends/xrandr/CMakeLists.txt --- old/libkscreen-5.23.5/backends/xrandr/CMakeLists.txt 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xrandr/CMakeLists.txt 2022-02-03 15:36:03.000000000 +0100 @@ -2,7 +2,9 @@ ${CMAKE_BUILD_DIR} ) -set(xrandr_SRCS + +add_library(KSC_XRandR MODULE) +target_sources(KSC_XRandR PRIVATE xrandr.cpp xrandrconfig.cpp xrandrcrtc.cpp @@ -14,8 +16,6 @@ ../utils.cpp ) -add_library(KSC_XRandR MODULE ${xrandr_SRCS}) - set_target_properties(KSC_XRandR PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/kf5/kscreen") set_target_properties(KSC_XRandR PROPERTIES PREFIX "") target_link_libraries(KSC_XRandR Qt::Core diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xrandr/xrandr.cpp new/libkscreen-5.24.0/backends/xrandr/xrandr.cpp --- old/libkscreen-5.23.5/backends/xrandr/xrandr.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xrandr/xrandr.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -45,6 +45,7 @@ qRegisterMetaType<xcb_randr_mode_t>("xcb_randr_mode_t"); qRegisterMetaType<xcb_randr_connection_t>("xcb_randr_connection_t"); qRegisterMetaType<xcb_randr_rotation_t>("xcb_randr_rotation_t"); + qRegisterMetaType<xcb_timestamp_t>("xcb_timestamp_t"); // Use our own connection to make sure that we won't mess up Qt's connection // if something goes wrong on our side. @@ -143,7 +144,7 @@ qCDebug(KSCREEN_XRANDR) << "Output" << xOutput->id() << ": connected =" << xOutput->isConnected() << ", enabled =" << xOutput->isEnabled(); } -void XRandR::crtcChanged(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_rotation_t rotation, const QRect &geom) +void XRandR::crtcChanged(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_rotation_t rotation, const QRect &geom, xcb_timestamp_t timestamp) { XRandRCrtc *xCrtc = s_internalConfig->crtc(crtc); if (!xCrtc) { @@ -152,6 +153,7 @@ xCrtc->update(mode, rotation, geom); } + xCrtc->updateConfigTimestamp(timestamp); m_configChangeCompressor->start(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xrandr/xrandr.h new/libkscreen-5.24.0/backends/xrandr/xrandr.h --- old/libkscreen-5.23.5/backends/xrandr/xrandr.h 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xrandr/xrandr.h 2022-02-03 15:36:03.000000000 +0100 @@ -44,7 +44,7 @@ private: void outputChanged(xcb_randr_output_t output, xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_connection_t connection); - void crtcChanged(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_rotation_t rotation, const QRect &geom); + void crtcChanged(xcb_randr_crtc_t crtc, xcb_randr_mode_t mode, xcb_randr_rotation_t rotation, const QRect &geom, xcb_timestamp_t timestamp); void screenChanged(xcb_randr_rotation_t rotation, const QSize &sizePx, const QSize &sizeMm); static quint8 *getXProperty(xcb_randr_output_t output, xcb_atom_t atom, size_t &len); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xrandr/xrandrconfig.cpp new/libkscreen-5.24.0/backends/xrandr/xrandrconfig.cpp --- old/libkscreen-5.23.5/backends/xrandr/xrandrconfig.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xrandr/xrandrconfig.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -504,6 +504,8 @@ XCB_NONE, xOutput->isConnected() ? XCB_RANDR_CONNECTION_CONNECTED : XCB_RANDR_CONNECTION_DISCONNECTED, kscreenOutput->isPrimary()); + if (xOutput->crtc()) + xOutput->crtc()->updateTimestamp(reply->timestamp); } return (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS); } @@ -573,7 +575,7 @@ << "\n" << "\tCRTC:" << xOutput->crtc()->crtc() << "\n" << "\tPos:" << kscreenOutput->pos() << "\n" - << "\tMode:" << modeId << kscreenOutput->currentMode() << "\n" + << "\tMode:" << kscreenOutput->currentMode() << "Preferred:" << kscreenOutput->preferredModeId() << "\n" << "\tRotation:" << kscreenOutput->rotation(); if (!sendConfig(kscreenOutput, xOutput->crtc())) { @@ -605,6 +607,9 @@ qCDebug(KSCREEN_XRANDR) << "\tResult: unknown (error)"; return false; } - qCDebug(KSCREEN_XRANDR) << "\tResult: " << reply->status; + + crtc->updateTimestamp(reply->timestamp); + + qCDebug(KSCREEN_XRANDR) << "\tResult: " << reply->status << " timestamp: " << reply->timestamp; return (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xrandr/xrandrcrtc.cpp new/libkscreen-5.24.0/backends/xrandr/xrandrcrtc.cpp --- old/libkscreen-5.23.5/backends/xrandr/xrandrcrtc.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xrandr/xrandrcrtc.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -16,6 +16,8 @@ , m_crtc(crtc) , m_mode(0) , m_rotation(XCB_RANDR_ROTATION_ROTATE_0) + , m_timestamp(XCB_CURRENT_TIME) + , m_configTimestamp(XCB_CURRENT_TIME) { update(); } @@ -111,3 +113,24 @@ m_geometry = geom; m_rotation = rotation; } + +void XRandRCrtc::updateTimestamp(const xcb_timestamp_t tmstamp) +{ + if (tmstamp > m_timestamp) { + qCDebug(KSCREEN_XRANDR) << "XRandRCrtc " << m_crtc << " m_timestamp update " << m_timestamp << " => " << tmstamp; + m_timestamp = tmstamp; + } +} + +void XRandRCrtc::updateConfigTimestamp(const xcb_timestamp_t tmstamp) +{ + if (tmstamp > m_configTimestamp) { + qCDebug(KSCREEN_XRANDR) << "XRandRCrtc " << m_crtc << " m_configTimestamp update" << m_configTimestamp << " => " << tmstamp; + m_configTimestamp = tmstamp; + } +} + +bool XRandRCrtc::isChangedFromOutside() const +{ + return m_configTimestamp > m_timestamp; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xrandr/xrandrcrtc.h new/libkscreen-5.24.0/backends/xrandr/xrandrcrtc.h --- old/libkscreen-5.23.5/backends/xrandr/xrandrcrtc.h 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xrandr/xrandrcrtc.h 2022-02-03 15:36:03.000000000 +0100 @@ -41,6 +41,10 @@ void update(); void update(xcb_randr_crtc_t mode, xcb_randr_rotation_t rotation, const QRect &geom); + void updateTimestamp(const xcb_timestamp_t tmstamp); + void updateConfigTimestamp(const xcb_timestamp_t tmstamp); + bool isChangedFromOutside() const; + private: xcb_randr_crtc_t m_crtc; xcb_randr_mode_t m_mode; @@ -50,4 +54,7 @@ QVector<xcb_randr_output_t> m_possibleOutputs; QVector<xcb_randr_output_t> m_outputs; + + xcb_timestamp_t m_timestamp; + xcb_timestamp_t m_configTimestamp; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xrandr/xrandroutput.cpp new/libkscreen-5.24.0/backends/xrandr/xrandroutput.cpp --- old/libkscreen-5.23.5/backends/xrandr/xrandroutput.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xrandr/xrandroutput.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -403,7 +403,7 @@ // See https://bugzilla.redhat.com/show_bug.cgi?id=1290586 // QXL will be creating a new mode we need to jump to every time the display is resized - kscreenOutput->setFollowPreferredMode(m_hotplugModeUpdate); + kscreenOutput->setFollowPreferredMode(m_hotplugModeUpdate && m_crtc && m_crtc->isChangedFromOutside()); kscreenOutput->setConnected(isConnected()); if (isConnected()) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/backends/xrandr1.1/CMakeLists.txt new/libkscreen-5.24.0/backends/xrandr1.1/CMakeLists.txt --- old/libkscreen-5.23.5/backends/xrandr1.1/CMakeLists.txt 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/backends/xrandr1.1/CMakeLists.txt 2022-02-03 15:36:03.000000000 +0100 @@ -1,19 +1,18 @@ find_package(XCB REQUIRED COMPONENTS XCB RANDR) include_directories(${CMAKE_SOURCE_DIR}/src - ${KDE4_INCLUDES} ${CMAKE_BUILD_DIR} ${QT_INCLUDES} ) -set(xrandr11_SRCS + +add_library(KSC_XRandR11 MODULE) +target_sources(KSC_XRandR11 PRIVATE xrandr11.cpp ../xcbeventlistener.cpp ../xcbwrapper.cpp ) -add_library(KSC_XRandR11 MODULE ${xrandr11_SRCS}) - set_target_properties(KSC_XRandR11 PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/kf5/kscreen") set_target_properties(KSC_XRandR11 PROPERTIES PREFIX "") target_link_libraries(KSC_XRandR11 Qt::Core diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/backendlauncher/CMakeLists.txt new/libkscreen-5.24.0/src/backendlauncher/CMakeLists.txt --- old/libkscreen-5.23.5/src/backendlauncher/CMakeLists.txt 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/backendlauncher/CMakeLists.txt 2022-02-03 15:36:03.000000000 +0100 @@ -35,3 +35,10 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kscreen.service DESTINATION ${KDE_INSTALL_DBUSSERVICEDIR} ) + +configure_file(plasma-kscreen.service.cmake + ${CMAKE_CURRENT_BINARY_DIR}/plasma-kscreen.service @ONLY +) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/plasma-kscreen.service + DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR} +) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/backendlauncher/org.kde.kscreen.service.cmake new/libkscreen-5.24.0/src/backendlauncher/org.kde.kscreen.service.cmake --- old/libkscreen-5.23.5/src/backendlauncher/org.kde.kscreen.service.cmake 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/backendlauncher/org.kde.kscreen.service.cmake 2022-02-03 15:36:03.000000000 +0100 @@ -1,3 +1,4 @@ [D-BUS Service] Name=org.kde.KScreen Exec=@CMAKE_INSTALL_FULL_LIBEXECDIR_KF5@/kscreen_backend_launcher +SystemdService=plasma-kscreen.service diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/backendlauncher/plasma-kscreen.service.cmake new/libkscreen-5.24.0/src/backendlauncher/plasma-kscreen.service.cmake --- old/libkscreen-5.23.5/src/backendlauncher/plasma-kscreen.service.cmake 1970-01-01 01:00:00.000000000 +0100 +++ new/libkscreen-5.24.0/src/backendlauncher/plasma-kscreen.service.cmake 2022-02-03 15:36:03.000000000 +0100 @@ -0,0 +1,12 @@ +[Unit] +Description=KScreen +PartOf=graphical-session.target + +[Service] +ExecStart=@CMAKE_INSTALL_FULL_LIBEXECDIR_KF5@/kscreen_backend_launcher +Type=dbus +BusName=org.kde.KScreen +TimeoutSec=5sec +Slice=background.slice +# Disable restart as we're dbus activated anyway +Restart=no diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/config.cpp new/libkscreen-5.24.0/src/config.cpp --- old/libkscreen-5.23.5/src/config.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/config.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -203,13 +203,13 @@ { ConfigPtr newConfig(new Config()); newConfig->d->screen = d->screen->clone(); - for (const OutputPtr &ourOutput : d->outputs) { - newConfig->addOutput(ourOutput->clone()); - } - newConfig->d->primaryOutput = newConfig->d->findPrimaryOutput(); newConfig->setSupportedFeatures(supportedFeatures()); newConfig->setTabletModeAvailable(tabletModeAvailable()); newConfig->setTabletModeEngaged(tabletModeEngaged()); + for (const OutputPtr &ourOutput : qAsConst(d->outputs)) { + newConfig->addOutput(ourOutput->clone()); + } + newConfig->d->primaryOutput = newConfig->d->findPrimaryOutput(); return newConfig; } @@ -325,6 +325,7 @@ void Config::addOutput(const OutputPtr &output) { d->outputs.insert(output->id(), output); + output->setExplicitLogicalSize(logicalSizeForOutput(*output)); connect(output.data(), &KScreen::Output::isPrimaryChanged, d, &KScreen::Config::Private::onPrimaryOutputChanged); Q_EMIT outputAdded(output); @@ -384,6 +385,7 @@ } else { // Update existing outputs d->outputs[otherOutput->id()]->apply(otherOutput); + d->outputs[otherOutput->id()]->setExplicitLogicalSize(logicalSizeForOutput(*d->outputs[otherOutput->id()])); } } @@ -391,6 +393,37 @@ setValid(other->isValid()); } +QRect Config::outputGeometryForOutput(const KScreen::Output &output) const +{ + QSize size = logicalSizeForOutput(output).toSize(); + if (!size.isValid()) { + return QRect(); + } + + return QRect(output.pos(), size); +} + +QSizeF Config::logicalSizeForOutput(const KScreen::Output &output) const +{ + QSizeF size = output.enforcedModeSize(); + if (!size.isValid()) { + return QSizeF(); + } + // ignore scale where scaling is not per-output + if (supportedFeatures().testFlag(Feature::PerOutputScaling)) { + size = size / output.scale(); + } + + // We can't use output.size(), because it does not reflect the actual rotation() set by caller. + // It is only updated when we get update from KScreen, but not when user changes mode or + // rotation manually. + + if (!output.isHorizontal()) { + size = size.transposed(); + } + return size; +} + QDebug operator<<(QDebug dbg, const KScreen::ConfigPtr &config) { if (config) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/config.h new/libkscreen-5.24.0/src/config.h --- old/libkscreen-5.23.5/src/config.h 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/config.h 2022-02-03 15:36:03.000000000 +0100 @@ -50,12 +50,13 @@ */ enum class Feature { None = 0, ///< None of the mentioned features are supported. - PrimaryDisplay = 1, ///< The backend knows about the concept of a primary display, this is mostly limited to X11. + PrimaryDisplay = 1, ///< The backend knows about the concept of a primary display Writable = 1 << 1, ///< The backend supports setting the config, it's not read-only. PerOutputScaling = 1 << 2, ///< The backend supports scaling each output individually. OutputReplication = 1 << 3, ///< The backend supports replication of outputs. AutoRotation = 1 << 4, ///< The backend supports automatic rotation of outputs. TabletMode = 1 << 5, ///< The backend supports querying if a device is in tablet mode. + SynchronousOutputChanges = 1 << 6, ///< The backend supports blocking until the output setting changes are applied }; Q_DECLARE_FLAGS(Features, Feature) @@ -190,6 +191,10 @@ */ void setTabletModeEngaged(bool engaged); + QRect outputGeometryForOutput(const KScreen::Output &output) const; + + QSizeF logicalSizeForOutput(const KScreen::Output &output) const; + Q_SIGNALS: void outputAdded(const KScreen::OutputPtr &output); void outputRemoved(int outputId); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/doctor/CMakeLists.txt new/libkscreen-5.24.0/src/doctor/CMakeLists.txt --- old/libkscreen-5.23.5/src/doctor/CMakeLists.txt 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/doctor/CMakeLists.txt 2022-02-03 15:36:03.000000000 +0100 @@ -1,4 +1,4 @@ -add_executable(kscreen-doctor main.cpp doctor.cpp dpmsclient.cpp) +add_executable(kscreen-doctor main.cpp doctor.cpp dpmsclient.cpp doctor.h dpmsclient.h) target_link_libraries(kscreen-doctor Qt::DBus KF5::Screen KF5::WaylandClient) install(TARGETS kscreen-doctor ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/doctor/doctor.cpp new/libkscreen-5.24.0/src/doctor/doctor.cpp --- old/libkscreen-5.23.5/src/doctor/doctor.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/doctor/doctor.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -194,7 +194,12 @@ return; } } - if (ops.count() == 3 && ops[2] == QLatin1String("enable")) { + if (ops.count() == 3 && ops[2] == QLatin1String("primary")) { + if (!setPrimary(output_id)) { + qApp->exit(1); + return; + }; + } else if (ops.count() == 3 && ops[2] == QLatin1String("enable")) { if (!setEnabled(output_id, true)) { qApp->exit(1); return; @@ -238,7 +243,7 @@ // be lenient about . vs. comma as separator qreal scale = ops[3].replace(QLatin1Char(','), QLatin1Char('.')).toDouble(&ok); if (ops.count() == 5) { - const QString dbl = ops[3] + QLatin1String(".") + ops[4]; + const QString dbl = ops[3] + QStringLiteral(".") + ops[4]; scale = dbl.toDouble(&ok); }; // set scale @@ -385,9 +390,9 @@ for (const auto &output : m_config->outputs()) { cout << green << "Output: " << cr << output->id() << " " << output->name(); - cout << " " << (output->isEnabled() ? green + QLatin1String("enabled") : red + QLatin1String("disabled")); - cout << " " << (output->isConnected() ? green + QLatin1String("connected") : red + QLatin1String("disconnected")); - cout << " " << (output->isPrimary() ? green + QLatin1String("primary") : QString()); + cout << " " << (output->isEnabled() ? green + QStringLiteral("enabled") : red + QStringLiteral("disabled")); + cout << " " << (output->isConnected() ? green + QStringLiteral("connected") : red + QStringLiteral("disconnected")); + cout << " " << (output->isPrimary() ? green + QStringLiteral("primary") : QString()); auto _type = typeString[output->type()]; cout << " " << yellow << (_type.isEmpty() ? QStringLiteral("UnmappedOutputType") : _type); cout << blue << " Modes: " << cr; @@ -506,7 +511,7 @@ for (const auto &output : m_config->outputs()) { if (output->id() == id) { // find mode - for (const KScreen::ModePtr mode : output->modes()) { + for (const KScreen::ModePtr &mode : output->modes()) { auto name = QStringLiteral("%1x%2@%3") .arg(QString::number(mode->size().width()), QString::number(mode->size().height()), QString::number(qRound(mode->refreshRate()))); @@ -613,6 +618,32 @@ return false; } +bool KScreen::Doctor::setPrimary(int id) +{ + if (!m_config) { + qCWarning(KSCREEN_DOCTOR) << "Invalid config."; + return false; + } + + bool found = false; + for (const auto &output : m_config->outputs()) { + if (output->id() == id) { + output->setPrimary(true); + m_changed = true; + found = true; + } + } + if (found) { + for (const auto &output : m_config->outputs()) { + if (output->id() != id) { + output->setPrimary(false); + m_changed = true; + } + } + } + return found; +} + void Doctor::applyConfig() { if (!m_changed) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/doctor/doctor.h new/libkscreen-5.24.0/src/doctor/doctor.h --- old/libkscreen-5.23.5/src/doctor/doctor.h 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/doctor/doctor.h 2022-02-03 15:36:03.000000000 +0100 @@ -46,6 +46,7 @@ bool setOverscan(int id, uint32_t overscan); bool setVrrPolicy(int id, KScreen::Output::VrrPolicy policy); bool setRgbRange(int id, KScreen::Output::RgbRange rgbRange); + bool setPrimary(int id); Q_SIGNALS: void outputsChanged(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/output.cpp new/libkscreen-5.24.0/src/output.cpp --- old/libkscreen-5.23.5/src/output.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/output.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -13,6 +13,7 @@ #include "mode.h" #include <QCryptographicHash> +#include <QGuiApplication> #include <QRect> #include <QScopedPointer> #include <QStringList> @@ -28,7 +29,7 @@ , replicationSource(0) , rotation(None) , scale(1.0) - , logicalSize(QSizeF()) + , explicitLogicalSize(QSizeF()) , connected(false) , enabled(false) , primary(false) @@ -51,6 +52,7 @@ , size(other.size) , rotation(other.rotation) , scale(other.scale) + , explicitLogicalSize(other.explicitLogicalSize) , connected(other.connected) , enabled(other.enabled) , primary(other.primary) @@ -87,7 +89,7 @@ QSize size; Rotation rotation; qreal scale; - QSizeF logicalSize; + QSizeF explicitLogicalSize; bool connected; bool enabled; bool primary; @@ -246,6 +248,43 @@ Q_EMIT outputChanged(); } +QString Output::typeName() const +{ + switch (d->type) { + case Output::Unknown: + return QStringLiteral("Unknown"); + case Output::Panel: + return QStringLiteral("Panel (Laptop)"); + case Output::VGA: + return QStringLiteral("VGA"); + case Output::DVI: + return QStringLiteral("DVI"); + case Output::DVII: + return QStringLiteral("DVI-I"); + case Output::DVIA: + return QStringLiteral("DVI-A"); + case Output::DVID: + return QStringLiteral("DVI-D"); + case Output::HDMI: + return QStringLiteral("HDMI"); + case Output::TV: + return QStringLiteral("TV"); + case Output::TVComposite: + return QStringLiteral("TV-Composite"); + case Output::TVSVideo: + return QStringLiteral("TV-SVideo"); + case Output::TVComponent: + return QStringLiteral("TV-Component"); + case Output::TVSCART: + return QStringLiteral("TV-SCART"); + case Output::TVC4: + return QStringLiteral("TV-C4"); + case Output::DisplayPort: + return QStringLiteral("DisplayPort"); + }; + return QStringLiteral("Invalid Type") + QString::number(d->type); +} + QString Output::icon() const { return d->icon; @@ -422,40 +461,18 @@ Q_EMIT scaleChanged(); } -QSizeF Output::logicalSize() const -{ - if (d->logicalSize.isValid()) { - return d->logicalSize; - } - - QSizeF size = enforcedModeSize(); - if (!size.isValid()) { - return QSizeF(); - } - size = size / d->scale; - - // We can't use d->size, because d->size does not reflect the actual rotation() set by caller. - // It is only updated when we get update from KScreen, but not when user changes mode or - // rotation manually. - - if (!isHorizontal()) { - size = size.transposed(); - } - return size; -} - QSizeF Output::explicitLogicalSize() const { - return d->logicalSize; + return d->explicitLogicalSize; } -void Output::setLogicalSize(const QSizeF &size) +void Output::setExplicitLogicalSize(const QSizeF &size) { - if (qFuzzyCompare(d->logicalSize.width(), size.width()) && qFuzzyCompare(d->logicalSize.height(), size.height())) { + if (qFuzzyCompare(d->explicitLogicalSize.width(), size.width()) && qFuzzyCompare(d->explicitLogicalSize.height(), size.height())) { return; } - d->logicalSize = size; - Q_EMIT logicalSizeChanged(); + d->explicitLogicalSize = size; + Q_EMIT explicitLogicalSizeChanged(); } bool Output::isConnected() const @@ -591,7 +608,7 @@ QRect Output::geometry() const { - QSize size = logicalSize().toSize(); + QSize size = explicitLogicalSize().toSize(); if (!size.isValid()) { return QRect(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/output.h new/libkscreen-5.24.0/src/output.h --- old/libkscreen-5.23.5/src/output.h 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/output.h 2022-02-03 15:36:03.000000000 +0100 @@ -47,7 +47,7 @@ Q_PROPERTY(QSize sizeMm READ sizeMm CONSTANT) Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged) Q_PROPERTY(bool followPreferredMode READ followPreferredMode WRITE setFollowPreferredMode NOTIFY followPreferredModeChanged) - Q_PROPERTY(QSizeF logicalSize READ logicalSize WRITE setLogicalSize NOTIFY logicalSizeChanged) + Q_PROPERTY(QSizeF explicitLogicalSize READ explicitLogicalSize WRITE setExplicitLogicalSize NOTIFY explicitLogicalSizeChanged) Q_PROPERTY(Capabilities capabilities READ capabilities NOTIFY capabilitiesChanged) Q_PROPERTY(uint32_t overscan READ overscan WRITE setOverscan NOTIFY overscanChanged) Q_PROPERTY(VrrPolicy vrrPolicy READ vrrPolicy WRITE setVrrPolicy NOTIFY vrrPolicyChanged) @@ -139,6 +139,7 @@ QString hashMd5() const; Type type() const; + QString typeName() const; void setType(Type type); QString icon() const; @@ -314,16 +315,6 @@ * The logical size is the output's representation internal to the display server and its * overall screen geometry. * - * returns the logical size of this output - * - * @since 5.18 - */ - QSizeF logicalSize() const; - - /** - * The logical size is the output's representation internal to the display server and its - * overall screen geometry. - * * returns the explicitly set logical size of this output, is an invalid size if not set * * @since 5.18 @@ -337,9 +328,9 @@ * * @param size of this output in logical space * - * @since 5.18 + * @since 5.24 */ - void setLogicalSize(const QSizeF &size); + void setExplicitLogicalSize(const QSizeF &size); /** * @returns whether the mode should be changed to the new preferred mode @@ -420,7 +411,7 @@ void clonesChanged(); void replicationSourceChanged(); void scaleChanged(); - void logicalSizeChanged(); + void explicitLogicalSizeChanged(); void followPreferredModeChanged(bool followPreferredMode); void capabilitiesChanged(); void overscanChanged(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkscreen-5.23.5/src/setconfigoperation.cpp new/libkscreen-5.24.0/src/setconfigoperation.cpp --- old/libkscreen-5.23.5/src/setconfigoperation.cpp 2022-01-04 10:00:26.000000000 +0100 +++ new/libkscreen-5.24.0/src/setconfigoperation.cpp 2022-02-03 15:36:03.000000000 +0100 @@ -32,6 +32,7 @@ void backendReady(org::kde::kscreen::Backend *backend) override; void onConfigSet(QDBusPendingCallWatcher *watcher); void normalizeOutputPositions(); + void fixPrimaryOutput(); KScreen::ConfigPtr config; @@ -110,6 +111,7 @@ { Q_D(SetConfigOperation); d->normalizeOutputPositions(); + d->fixPrimaryOutput(); if (BackendManager::instance()->method() == BackendManager::InProcess) { auto backend = d->loadBackend(); backend->setConfig(d->config); @@ -149,4 +151,41 @@ } } +void SetConfigOperationPrivate::fixPrimaryOutput() +{ + if (!config || !(config->supportedFeatures() & Config::Feature::PrimaryDisplay)) { + return; + } + const auto outputs = config->outputs(); + if (outputs.isEmpty()) { + return; + } + + // Here we make sure that: + // - that our primary is enabled + // - we have at least a primary + // - we have exactly 1 primary + // - we have a primary at all + bool found = false; + KScreen::OutputPtr candidate; + for (const KScreen::OutputPtr &output : outputs) { + if (!output->isEnabled() && output->isPrimary()) { + qCDebug(KSCREEN) << "can't be primary if disabled!!" << output; + output->setPrimary(false); + } else if (output->isPrimary() && !found) { + found = true; + } else if (output->isPrimary() && found) { + qCDebug(KSCREEN) << "can only have 1 primary" << output; + output->setPrimary(false); + } else if (output->isEnabled()) { + candidate = output; + } + } + + if (!found && candidate) { + qCDebug(KSCREEN) << "setting primary instead" << candidate; + candidate->setPrimary(true); + } +} + #include "setconfigoperation.moc"