diff options
Diffstat (limited to 'src/xprivate.cpp')
-rw-r--r-- | src/xprivate.cpp | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/xprivate.cpp b/src/xprivate.cpp index 7cb0949..53059e4 100644 --- a/src/xprivate.cpp +++ b/src/xprivate.cpp @@ -1,4 +1,5 @@ #include "xprivate.h" +#include "cvt.h" #include <QDebug> #include <QRegularExpression> @@ -658,3 +659,62 @@ XRRModeInfo* XPrivate::setOutputResolution(QStringList &args, OutputInfo *oi, in } return best; } + +/** + * !! oi pointer might be invalid after calling this !! + * @return true if updateScreenResources() should be called later + */ +bool XPrivate::addResolutionToOutput(OutputInfo *oi, const QSize &res) +{ + if (!getOutputModeForResolution(oi->output, res).empty()) + return false; // Nothing to do + XRRModeInfo *bestMode = nullptr; + for (auto *mode : _modeMap) { + if (int(mode->width) != res.width() || int(mode->height) != res.height()) + continue; + if (toVertRefresh(mode) < 59 || toVertRefresh(mode) > 70) + continue; // Play it safe + if (bestMode == nullptr || abs(toVertRefresh(bestMode) - 60) > abs(toVertRefresh(mode) - 60)) { + bestMode = mode; // As close to 60 as possible + } + } + if (bestMode != nullptr) { + qDebug() << "Adding existing mode" << res.width() << 'x' << res.height() << "to" << oi->outputName; + XRRAddOutputMode(_display, oi->id, bestMode->id); + return true; + } else { + // From scratch + qDebug() << "Creating requested mode" << res.width() << 'x' << res.height() << "from scratch"; + QByteArray ba = QString::asprintf("%dx%d_BG", res.width(), res.height()).toLocal8Bit(); + mode *mode = vert_refresh(res.width(), res.height(), 60, 0, 0, 0); + if (mode == nullptr) + return false; // Failed + XRRModeInfo m; + memset(&m, 0, sizeof(m)); + m.width = static_cast<unsigned int>(mode->hr); + m.height = static_cast<unsigned int>(mode->vr); + m.dotClock = static_cast<unsigned long>(mode->pclk) * 1000ul * 1000ul; + m.hSyncStart= static_cast<unsigned int>(mode->hss); + m.hSyncEnd = static_cast<unsigned int>(mode->hse); + m.hTotal = static_cast<unsigned int>(mode->hfl); + m.hSkew = 0; + m.vSyncStart= static_cast<unsigned int>(mode->vss); + m.vSyncEnd = static_cast<unsigned int>(mode->vse); + m.vTotal = static_cast<unsigned int>(mode->vfl); + m.id = 0; + m.name = ba.data(); + m.nameLength= static_cast<unsigned int>(ba.length()); + m.modeFlags = RR_VSyncPositive | RR_HSyncNegative; + free(mode); + RRMode xid = XRRCreateMode(_display, DefaultRootWindow(_display), &m); + if (xid <= 0) { + qDebug() << "Creating mode failed"; + return false; + } + qDebug() << "Adding created mode to" << oi->outputName; + XRRAddOutputMode(_display, oi->id, xid); + // Stuff changed, update now in case other screens want the same resolution + updateScreenResources(); + return false; // We just updated ourselves, don't signal "update required" + } +} |