commit: 45346dc6570f2d6a5032046424fa4abedad040e5
Author: Sam James <sam <AT> gentoo <DOT> org>
AuthorDate: Tue Feb 25 22:49:35 2025 +0000
Commit: Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Tue Feb 25 22:49:35 2025 +0000
URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=45346dc6
kde-plasma/kwin: fix hang on startup
Thanks to FireBurn and josef64 for reporting & testing.
Signed-off-by: Sam James <sam <AT> gentoo.org>
.../kwin/files/kwin-6.3.2-revert-fix-hang.patch | 307 +++++++++++++++++++++
.../{kwin-6.3.2.ebuild => kwin-6.3.2-r1.ebuild} | 4 +
2 files changed, 311 insertions(+)
diff --git a/kde-plasma/kwin/files/kwin-6.3.2-revert-fix-hang.patch
b/kde-plasma/kwin/files/kwin-6.3.2-revert-fix-hang.patch
new file mode 100644
index 000000000000..9b68efb94bec
--- /dev/null
+++ b/kde-plasma/kwin/files/kwin-6.3.2-revert-fix-hang.patch
@@ -0,0 +1,307 @@
+https://invent.kde.org/plasma/kwin/-/commit/544f3d1ae355d72cab0f28df5533b67085f85e88
+
+From 544f3d1ae355d72cab0f28df5533b67085f85e88 Mon Sep 17 00:00:00 2001
+From: Xaver Hugl <[email protected]>
+Date: Tue, 25 Feb 2025 22:49:06 +0100
+Subject: [PATCH] Revert "workspace: better deal with having more outputs than
+ the GPU can drive"
+
+This reverts commit a23949582f05c1db7c9bb3bf7fd0292b7120045d. For some systems
it caused
+an infinite loop on startup
+--- a/src/backends/drm/drm_backend.cpp
++++ b/src/backends/drm/drm_backend.cpp
+@@ -367,7 +367,7 @@ size_t DrmBackend::gpuCount() const
+ return m_gpus.size();
+ }
+
+-OutputConfigurationError DrmBackend::applyOutputChanges(const
OutputConfiguration &config)
++bool DrmBackend::applyOutputChanges(const OutputConfiguration &config)
+ {
+ QList<DrmOutput *> toBeEnabled;
+ QList<DrmOutput *> toBeDisabled;
+@@ -386,20 +386,14 @@ OutputConfigurationError
DrmBackend::applyOutputChanges(const OutputConfiguratio
+ }
+ }
+ }
+- const auto error = gpu->testPendingConfiguration();
+- if (error != DrmPipeline::Error::None) {
++ if (gpu->testPendingConfiguration() != DrmPipeline::Error::None) {
+ for (const auto &output : std::as_const(toBeEnabled)) {
+ output->revertQueuedChanges();
+ }
+ for (const auto &output : std::as_const(toBeDisabled)) {
+ output->revertQueuedChanges();
+ }
+- if (error == DrmPipeline::Error::NotEnoughCrtcs) {
+- // TODO make this more specific, this is per GPU!
+- return OutputConfigurationError::TooManyEnabledOutputs;
+- } else {
+- return OutputConfigurationError::Unknown;
+- }
++ return false;
+ }
+ }
+ // first, apply changes to drm outputs.
+@@ -418,7 +412,7 @@ OutputConfigurationError
DrmBackend::applyOutputChanges(const OutputConfiguratio
+ for (const auto &output : std::as_const(m_virtualOutputs)) {
+ output->applyChanges(config);
+ }
+- return OutputConfigurationError::None;
++ return true;
+ }
+
+ void DrmBackend::setRenderBackend(DrmRenderBackend *backend)
+--- a/src/backends/drm/drm_backend.h
++++ b/src/backends/drm/drm_backend.h
+@@ -73,7 +73,7 @@ Q_SIGNALS:
+ void gpuRemoved(DrmGpu *gpu);
+
+ protected:
+- OutputConfigurationError applyOutputChanges(const OutputConfiguration
&config) override;
++ bool applyOutputChanges(const OutputConfiguration &config) override;
+
+ private:
+ friend class DrmGpu;
+--- a/src/backends/drm/drm_gpu.cpp
++++ b/src/backends/drm/drm_gpu.cpp
+@@ -352,7 +352,7 @@ DrmPipeline::Error
DrmGpu::checkCrtcAssignment(QList<DrmConnector *> connectors,
+ }
+ if (!connectors.empty()) {
+ // we have no crtcs left to drive the remaining connectors
+- return DrmPipeline::Error::NotEnoughCrtcs;
++ return DrmPipeline::Error::InvalidArguments;
+ }
+ return testPipelines();
+ }
+@@ -442,10 +442,6 @@ DrmPipeline::Error DrmGpu::testPendingConfiguration()
+ output->cursorLayer()->setEnabled(false);
+ }
+ }
+- if (connectors.size() > crtcs.size()) {
+- // this can't work, we can return early
+- return DrmPipeline::Error::NotEnoughCrtcs;
+- }
+ return checkCrtcAssignment(connectors, crtcs);
+ }
+
+--- a/src/backends/drm/drm_pipeline.h
++++ b/src/backends/drm/drm_pipeline.h
+@@ -48,7 +48,6 @@ public:
+ NoPermission,
+ FramePending,
+ TestBufferFailed,
+- NotEnoughCrtcs,
+ Unknown,
+ };
+ Q_ENUM(Error)
+--- a/src/core/outputbackend.cpp
++++ b/src/core/outputbackend.cpp
+@@ -43,7 +43,7 @@ std::unique_ptr<QPainterBackend>
OutputBackend::createQPainterBackend()
+ return nullptr;
+ }
+
+-OutputConfigurationError OutputBackend::applyOutputChanges(const
OutputConfiguration &config)
++bool OutputBackend::applyOutputChanges(const OutputConfiguration &config)
+ {
+ const auto availableOutputs = outputs();
+ QList<Output *> toBeEnabledOutputs;
+@@ -63,7 +63,7 @@ OutputConfigurationError
OutputBackend::applyOutputChanges(const OutputConfigura
+ for (const auto &output : toBeDisabledOutputs) {
+ output->applyChanges(config);
+ }
+- return OutputConfigurationError::None;
++ return true;
+ }
+
+ Output *OutputBackend::findOutput(const QString &name) const
+--- a/src/core/outputbackend.h
++++ b/src/core/outputbackend.h
+@@ -92,7 +92,7 @@ public:
+ /**
+ * Applies the output changes. Default implementation only sets values
common between platforms
+ */
+- virtual OutputConfigurationError applyOutputChanges(const
OutputConfiguration &config);
++ virtual bool applyOutputChanges(const OutputConfiguration &config);
+
+ virtual Session *session() const;
+
+--- a/src/effect/globals.h
++++ b/src/effect/globals.h
+@@ -451,12 +451,6 @@ enum WindowTypeMask {
+ };
+ Q_DECLARE_FLAGS(WindowTypes, WindowTypeMask)
+
+-enum class OutputConfigurationError {
+- None,
+- Unknown,
+- TooManyEnabledOutputs,
+-};
+-
+ } // namespace
+
+ Q_DECLARE_METATYPE(std::chrono::nanoseconds)
+--- a/src/wayland/outputmanagement_v2.cpp
++++ b/src/wayland/outputmanagement_v2.cpp
+@@ -487,15 +487,11 @@ void
OutputConfigurationV2Interface::kde_output_configuration_v2_apply(Resource
+ return pair.second->handle();
+ });
+ }
+- switch (workspace()->applyOutputConfiguration(config, sortedOrder)) {
+- case OutputConfigurationError::None:
++ if (workspace()->applyOutputConfiguration(config, sortedOrder)) {
+ send_applied();
+- break;
+- case OutputConfigurationError::Unknown:
+- case OutputConfigurationError::TooManyEnabledOutputs:
++ } else {
+ // TODO provide a more accurate error reason once the driver actually
gives us anything
+ sendFailure(resource, i18n("The driver rejected the output
configuration"));
+- break;
+ }
+ }
+
+--- a/src/workspace.cpp
++++ b/src/workspace.cpp
+@@ -496,11 +496,10 @@ Workspace::~Workspace()
+ _self = nullptr;
+ }
+
+-OutputConfigurationError Workspace::applyOutputConfiguration(const
OutputConfiguration &config, const std::optional<QList<Output *>> &outputOrder)
++bool Workspace::applyOutputConfiguration(const OutputConfiguration &config,
const std::optional<QList<Output *>> &outputOrder)
+ {
+- auto error = kwinApp()->outputBackend()->applyOutputChanges(config);
+- if (error != OutputConfigurationError::None) {
+- return error;
++ if (!kwinApp()->outputBackend()->applyOutputChanges(config)) {
++ return false;
+ }
+ updateOutputs(outputOrder);
+ m_outputConfigStore->storeConfig(kwinApp()->outputBackend()->outputs(),
m_lidSwitchTracker->isLidClosed(), config, m_outputOrder);
+@@ -523,7 +522,7 @@ OutputConfigurationError
Workspace::applyOutputConfiguration(const OutputConfigu
+ output->renderLoop()->scheduleRepaint();
+ }
+
+- return OutputConfigurationError::None;
++ return true;
+ }
+
+ void Workspace::updateOutputConfiguration()
+@@ -540,12 +539,6 @@ void Workspace::updateOutputConfiguration()
+ return;
+ }
+
+- assignBrightnessDevices();
+-
+- const bool alreadyHaveEnabledOutputs = std::ranges::any_of(outputs,
[](Output *o) {
+- return o->isEnabled();
+- });
+-
+ // Update the output order to a fallback list, to avoid dangling pointers
+ const auto setFallbackOutputOrder = [this, &outputs]() {
+ auto newOrder = outputs;
+@@ -559,62 +552,40 @@ void Workspace::updateOutputConfiguration()
+ setOutputOrder(newOrder);
+ };
+
+- QList<Output *> toEnable = outputs;
+- OutputConfigurationError error = OutputConfigurationError::None;
+- do {
+- auto opt = m_outputConfigStore->queryConfig(toEnable,
m_lidSwitchTracker->isLidClosed(), m_orientationSensor->reading(),
kwinApp()->tabletModeManager()->effectiveTabletMode());
+- if (!opt) {
+- return;
+- }
+- auto &[cfg, order, type] = *opt;
++ auto opt = m_outputConfigStore->queryConfig(outputs,
m_lidSwitchTracker->isLidClosed(), m_orientationSensor->reading(),
kwinApp()->tabletModeManager()->effectiveTabletMode());
++ if (!opt) {
++ return;
++ }
++ auto &[cfg, order, type] = *opt;
+
+- for (const auto &output : outputs) {
+- if (!toEnable.contains(output)) {
+- cfg.changeSet(output)->enabled = false;
+- }
+- }
+- for (Output *output : std::as_const(toEnable)) {
+- const auto changeset = cfg.changeSet(output);
+- if (output->brightnessDevice() &&
changeset->allowSdrSoftwareBrightness.value_or(true)) {
+- changeset->allowSdrSoftwareBrightness = false;
+- changeset->brightness =
output->brightnessDevice()->observedBrightness();
+- }
++ assignBrightnessDevices();
++ for (Output *output : outputs) {
++ const auto changeset = cfg.changeSet(output);
++ if (output->brightnessDevice() &&
changeset->allowSdrSoftwareBrightness.value_or(true)) {
++ changeset->allowSdrSoftwareBrightness = false;
++ changeset->brightness =
output->brightnessDevice()->observedBrightness();
+ }
++ }
+
+- error = applyOutputConfiguration(cfg, order);
+- switch (error) {
+- case OutputConfigurationError::None:
+- setOutputOrder(order);
+- if (type == OutputConfigurationStore::ConfigType::Generated) {
+- const bool hasInternal = std::any_of(outputs.begin(),
outputs.end(), [](Output *o) {
+- return o->isInternal();
+- });
+- if (hasInternal && outputs.size() == 2) {
+- // show the OSD with output configuration presets
+- QDBusMessage message =
QDBusMessage::createMethodCall(QStringLiteral("org.kde.kscreen.osdService"),
+-
QStringLiteral("/org/kde/kscreen/osdService"),
+-
QStringLiteral("org.kde.kscreen.osdService"),
+-
QStringLiteral("showActionSelector"));
+- QDBusConnection::sessionBus().asyncCall(message);
+- }
+- }
+- return;
+- case OutputConfigurationError::Unknown:
+- qCWarning(KWIN_CORE) << "Applying output config failed!";
+- setFallbackOutputOrder();
+- return;
+- case OutputConfigurationError::TooManyEnabledOutputs:
+- if (alreadyHaveEnabledOutputs) {
+- // just keeping the old output configuration is preferable
+- break;
+- }
+- toEnable.removeLast();
+- break;
++ if (!applyOutputConfiguration(cfg, order)) {
++ qCWarning(KWIN_CORE) << "Applying output config failed!";
++ setFallbackOutputOrder();
++ return;
++ }
++ setOutputOrder(order);
++ if (type == OutputConfigurationStore::ConfigType::Generated) {
++ const bool hasInternal = std::any_of(outputs.begin(), outputs.end(),
[](Output *o) {
++ return o->isInternal();
++ });
++ if (hasInternal && outputs.size() == 2) {
++ // show the OSD with output configuration presets
++ QDBusMessage message =
QDBusMessage::createMethodCall(QStringLiteral("org.kde.kscreen.osdService"),
++
QStringLiteral("/org/kde/kscreen/osdService"),
++
QStringLiteral("org.kde.kscreen.osdService"),
++
QStringLiteral("showActionSelector"));
++ QDBusConnection::sessionBus().asyncCall(message);
+ }
+- } while (error == OutputConfigurationError::TooManyEnabledOutputs &&
!toEnable.isEmpty());
+-
+- qCCritical(KWIN_CORE, "Applying output configuration failed!");
+- setFallbackOutputOrder();
++ }
+ }
+
+ void Workspace::setupWindowConnections(Window *window)
+--- a/src/workspace.h
++++ b/src/workspace.h
+@@ -466,7 +466,7 @@ public:
+ * Apply the requested output configuration. Note that you must use this
function
+ * instead of Platform::applyOutputChanges().
+ */
+- OutputConfigurationError applyOutputConfiguration(const
OutputConfiguration &config, const std::optional<QList<Output *>> &outputOrder
= std::nullopt);
++ bool applyOutputConfiguration(const OutputConfiguration &config, const
std::optional<QList<Output *>> &outputOrder = std::nullopt);
+
+ public Q_SLOTS:
+ void performWindowOperation(KWin::Window *window,
Options::WindowOperation op);
+--
+GitLab
diff --git a/kde-plasma/kwin/kwin-6.3.2.ebuild
b/kde-plasma/kwin/kwin-6.3.2-r1.ebuild
similarity index 98%
rename from kde-plasma/kwin/kwin-6.3.2.ebuild
rename to kde-plasma/kwin/kwin-6.3.2-r1.ebuild
index ad356a50bab6..9d406dfe2a82 100644
--- a/kde-plasma/kwin/kwin-6.3.2.ebuild
+++ b/kde-plasma/kwin/kwin-6.3.2-r1.ebuild
@@ -115,6 +115,10 @@ BDEPEND="
# -m 0755 to avoid suid with USE="-filecaps"
FILECAPS=( -m 0755 cap_sys_nice=ep usr/bin/kwin_wayland )
+PATCHES=(
+ "${FILESDIR}"/${P}-revert-fix-hang.patch
+)
+
src_prepare() {
ecm_src_prepare