Package: libkf5screen8
Version: 4:5.27.0-1
Severity: normal
Tags: patch upstream

This is to note that the upstream bug titled "On X11 with proprietary NVIDIA
GPU drivers, external monitor disabled after reboot or wake-from-sleep" applies
to Debian package 4.27.0-1.

See https://bugs.kde.org/show_bug.cgi?id=460341

Today a fix has finally been found.  There are at least a few reports that it
solves the issue -- I've tested it myself and it does solve the symptom I've
been having since October 2022.

The patch is:
https://invent.kde.org/plasma/libkscreen/-/commit/1d237c29655c7e3fb15fb9b71e5f167bd207593f

I'd love to see it applied before the release.  Happy to do an upload myself if
that's preferred.

-Steve


-- System Information:
Debian Release: bookworm/sid
  APT prefers unstable
  APT policy: (700, 'unstable'), (500, 'testing')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 6.1.0-5-amd64 (SMP w/16 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, 
TAINT_UNSIGNED_MODULE
Locale: LANG=en_CA.UTF-8, LC_CTYPE=en_CA.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_CA:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages libkf5screen8 depends on:
ii  libc6              2.36-8
ii  libkf5screen-data  4:5.27.0-1.1
ii  libqt5core5a       5.15.8+dfsg-2
ii  libqt5dbus5        5.15.8+dfsg-2
ii  libqt5gui5         5.15.8+dfsg-2
ii  libqt5x11extras5   5.15.8-2
ii  libstdc++6         12.2.0-14

Versions of packages libkf5screen8 recommends:
ii  hwdata  0.367-1

libkf5screen8 suggests no packages.

-- no debconf information
diff --git a/backends/xrandr/xrandrconfig.cpp b/backends/xrandr/xrandrconfig.cpp
index 
4ab5b3c4e1f49752c80eb6fca4f39691954024f9..50910d44f766b755208c28bfdccee4821e9ed7e3
 100644
--- a/backends/xrandr/xrandrconfig.cpp
+++ b/backends/xrandr/xrandrconfig.cpp
@@ -128,11 +128,16 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
     const QSize newScreenSize = screenSize(config);
     const QSize currentScreenSize = m_screen->currentSize();
 
-    // Previously we initially set such screen size, that it can take the 
current
-    // as well  as the new configuration, then we apply the output changes,
-    // and finally then (if necessary) we reduce the screen size to
-    // fix the new configuration precisely.Now we initially disable the output,
-    // then set the target screen size, and finally we apply the output 
changes.
+    // When the current screen configuration is bigger than the new size (like
+    // when rotating an output), the XSetScreenSize can fail or apply the 
smaller
+    // size only partially, because we apply the size (we have to) before the
+    // output changes. To prevent all kinds of weird screen sizes from 
happening,
+    // we initially set such screen size, that it can take the current as well
+    // as the new configuration, then we apply the output changes, and finally 
then
+    // (if necessary) we reduce the screen size to fix the new configuration 
precisely.
+    const QSize intermediateScreenSize =
+        QSize(qMax(newScreenSize.width(), currentScreenSize.width()), 
qMax(newScreenSize.height(), currentScreenSize.height()));
+
     int neededCrtcs = 0;
 
     // pairs of before/after
@@ -246,6 +251,7 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
     qCDebug(KSCREEN_XRANDR) << "\tChange Screen Size:" << (newScreenSize != 
currentScreenSize);
     if (newScreenSize != currentScreenSize) {
         qCDebug(KSCREEN_XRANDR) << "\t\tOld:" << currentScreenSize << "\n"
+                                << "\t\tIntermediate:" << 
intermediateScreenSize << "\n"
                                 << "\t\tNew:" << newScreenSize;
     }
 
@@ -280,14 +286,24 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
         disableOutput(output);
     }
 
-    if (currentScreenSize != newScreenSize) {
-        for (const KScreen::OutputPtr &output : toChange) {
-            disableOutput(output);
-        }
+    if (intermediateScreenSize != currentScreenSize) {
+        setScreenSize(intermediateScreenSize);
     }
 
     bool forceScreenSizeUpdate = false;
 
+    for (const KScreen::OutputPtr &output : toChange) {
+        if (!changeOutput(output)) {
+            /* If we disabled the output before changing it and XRandR failed
+             * to re-enable it, then update screen size too */
+            if (toDisable.contains(output->id())) {
+                output->setEnabled(false);
+                qCDebug(KSCREEN_XRANDR) << "Output failed to change: " << 
output->name();
+                forceScreenSizeUpdate = true;
+            }
+        }
+    }
+
     for (const KScreen::OutputPtr &output : toEnable) {
         if (!enableOutput(output)) {
             qCDebug(KSCREEN_XRANDR) << "Output failed to be Enabled: " << 
output->name();
@@ -302,7 +318,7 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
         setOutputPriority(outputId, priority);
     }
 
-    if (forceScreenSizeUpdate || currentScreenSize != newScreenSize) {
+    if (forceScreenSizeUpdate || intermediateScreenSize != newScreenSize) {
         QSize newSize = newScreenSize;
         if (forceScreenSizeUpdate) {
             newSize = screenSize(config);
@@ -310,17 +326,6 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
         }
         setScreenSize(newSize);
     }
-
-    for (const KScreen::OutputPtr &output : toChange) {
-        if (!changeOutput(output)) {
-            /* If we disabled the output before changing it and XRandR failed
-             * to re-enable it, then update screen size too */
-            if (toDisable.contains(output->id())) {
-                output->setEnabled(false);
-                qCDebug(KSCREEN_XRANDR) << "Output failed to change: " << 
output->name();
-            }
-        }
-    }
 }
 
 void XRandRConfig::printConfig(const ConfigPtr &config) const
diff --git a/backends/xrandr/xrandrconfig.cpp b/backends/xrandr/xrandrconfig.cpp
index 
4ab5b3c4e1f49752c80eb6fca4f39691954024f9..50910d44f766b755208c28bfdccee4821e9ed7e3
 100644
--- a/backends/xrandr/xrandrconfig.cpp
+++ b/backends/xrandr/xrandrconfig.cpp
@@ -128,11 +128,16 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
     const QSize newScreenSize = screenSize(config);
     const QSize currentScreenSize = m_screen->currentSize();
 
-    // Previously we initially set such screen size, that it can take the 
current
-    // as well  as the new configuration, then we apply the output changes,
-    // and finally then (if necessary) we reduce the screen size to
-    // fix the new configuration precisely.Now we initially disable the output,
-    // then set the target screen size, and finally we apply the output 
changes.
+    // When the current screen configuration is bigger than the new size (like
+    // when rotating an output), the XSetScreenSize can fail or apply the 
smaller
+    // size only partially, because we apply the size (we have to) before the
+    // output changes. To prevent all kinds of weird screen sizes from 
happening,
+    // we initially set such screen size, that it can take the current as well
+    // as the new configuration, then we apply the output changes, and finally 
then
+    // (if necessary) we reduce the screen size to fix the new configuration 
precisely.
+    const QSize intermediateScreenSize =
+        QSize(qMax(newScreenSize.width(), currentScreenSize.width()), 
qMax(newScreenSize.height(), currentScreenSize.height()));
+
     int neededCrtcs = 0;
 
     // pairs of before/after
@@ -246,6 +251,7 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
     qCDebug(KSCREEN_XRANDR) << "\tChange Screen Size:" << (newScreenSize != 
currentScreenSize);
     if (newScreenSize != currentScreenSize) {
         qCDebug(KSCREEN_XRANDR) << "\t\tOld:" << currentScreenSize << "\n"
+                                << "\t\tIntermediate:" << 
intermediateScreenSize << "\n"
                                 << "\t\tNew:" << newScreenSize;
     }
 
@@ -280,14 +286,24 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
         disableOutput(output);
     }
 
-    if (currentScreenSize != newScreenSize) {
-        for (const KScreen::OutputPtr &output : toChange) {
-            disableOutput(output);
-        }
+    if (intermediateScreenSize != currentScreenSize) {
+        setScreenSize(intermediateScreenSize);
     }
 
     bool forceScreenSizeUpdate = false;
 
+    for (const KScreen::OutputPtr &output : toChange) {
+        if (!changeOutput(output)) {
+            /* If we disabled the output before changing it and XRandR failed
+             * to re-enable it, then update screen size too */
+            if (toDisable.contains(output->id())) {
+                output->setEnabled(false);
+                qCDebug(KSCREEN_XRANDR) << "Output failed to change: " << 
output->name();
+                forceScreenSizeUpdate = true;
+            }
+        }
+    }
+
     for (const KScreen::OutputPtr &output : toEnable) {
         if (!enableOutput(output)) {
             qCDebug(KSCREEN_XRANDR) << "Output failed to be Enabled: " << 
output->name();
@@ -302,7 +318,7 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
         setOutputPriority(outputId, priority);
     }
 
-    if (forceScreenSizeUpdate || currentScreenSize != newScreenSize) {
+    if (forceScreenSizeUpdate || intermediateScreenSize != newScreenSize) {
         QSize newSize = newScreenSize;
         if (forceScreenSizeUpdate) {
             newSize = screenSize(config);
@@ -310,17 +326,6 @@ void XRandRConfig::applyKScreenConfig(const 
KScreen::ConfigPtr &config)
         }
         setScreenSize(newSize);
     }
-
-    for (const KScreen::OutputPtr &output : toChange) {
-        if (!changeOutput(output)) {
-            /* If we disabled the output before changing it and XRandR failed
-             * to re-enable it, then update screen size too */
-            if (toDisable.contains(output->id())) {
-                output->setEnabled(false);
-                qCDebug(KSCREEN_XRANDR) << "Output failed to change: " << 
output->name();
-            }
-        }
-    }
 }
 
 void XRandRConfig::printConfig(const ConfigPtr &config) const

Reply via email to