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