summaryrefslogtreecommitdiffstats
path: root/src/xprivate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xprivate.cpp')
-rw-r--r--src/xprivate.cpp60
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"
+ }
+}