summaryrefslogtreecommitdiffstats
path: root/src/xx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xx.cpp')
-rw-r--r--src/xx.cpp131
1 files changed, 60 insertions, 71 deletions
diff --git a/src/xx.cpp b/src/xx.cpp
index 62bd353..b94e42e 100644
--- a/src/xx.cpp
+++ b/src/xx.cpp
@@ -1,9 +1,11 @@
#include "xx.h"
#include "xprivate.h"
#include "cvt.h"
+#include "main.h"
#include <QDebug>
#include <QSocketNotifier>
#include <QThread>
+#include <QProcess>
/*
* This clusterfuck exists because there are name clashes between X11/Xrandr headers
@@ -55,24 +57,24 @@ public:
if (map.isEmpty())
return;
qDebug() << "Starting revert";
- XGrabServer(x->_display);
- x->disconnectAllCrtcs();
+ QStringList cmd;
QSize screenSize;
for (auto e : map) {
if (e->mode == None || !x->_modeMap.contains(e->mode))
continue;
+ XRRModeInfo *mode = x->_modeMap[e->mode];
+ QString rate = QString::number(toVertRefresh(mode), 'f', 2);
+ for (int i = 0; i < e->noutput; ++i) {
+ auto *oi = x->_outputMap[e->outputs[i]];
+ cmd << "--output" << oi->outputName << "--mode" << mode->name << "--rate" << rate;
+ cmd << "--x" << QString::number(oi->crtc->x) << "--y" << QString::number(oi->crtc->y);
+ if (oi->crtc->x == 0 && oi->crtc->y == 0 && !cmd.contains("--primary")) {
+ cmd << "--primary";
+ }
+ }
screenSize = screenSize.expandedTo(QSize(e->x + int(x->_modeMap[e->mode]->width), e->y + int(x->_modeMap[e->mode]->height)));
}
- x->setScreenSize(screenSize);
- for (CrtcMap::iterator it = map.begin(); it != map.end(); ++it) {
- auto e = it.value();
- if (e->mode == None)
- continue;
- XRRSetCrtcConfig(x->_display, x->_screenResources, it.key(), CurrentTime,
- e->x, e->y, e->mode, e->rotation, e->outputs, e->noutput);
- }
- XUngrabServer(x->_display);
- XSync(x->_display, False);
+ ScreenSetup::inst()->runXrandr(cmd);
freeBackup();
}
};
@@ -220,13 +222,6 @@ ScreenSetup::ScreenSetup() : a(new XPrivate())
}
-static double toVertRefresh(const XRRModeInfo *mode)
-{
- if (mode->hTotal > 0 && mode->vTotal > 0)
- return (double(mode->dotClock) / (double(mode->hTotal) * double(mode->vTotal)));
- return 0;
-}
-
void ScreenSetup::addMissingEdidResolutions()
{
a->addMissingEdidResolutions();
@@ -330,7 +325,7 @@ bool ScreenSetup::hasScreenWithoutEdid()
return false;
}
-ConfigBackup ScreenSetup::setDefaultMode(bool dryRun, ScreenMode &mode)
+ConfigBackup ScreenSetup::setDefaultMode(ScreenMode &mode)
{
ConfigBackup retval;
if (a->_outputMap.size() == 1) { // Only one output exists, do nothing
@@ -356,36 +351,24 @@ ConfigBackup ScreenSetup::setDefaultMode(bool dryRun, ScreenMode &mode)
mode = ScreenMode::Advanced; // Dunno lol
return retval;
}
- QSize screenSize = getTotalSizeHorz(outputSizes);
- if (!dryRun) {
- retval = createCrtcBackup();
- XGrabServer(a->_display);
- a->disconnectAllCrtcs();
- // Set new screen size
- a->setScreenSize(screenSize);
- }
+ QSize screenSize = getTotalSizeHorz(outputSizes);
+ QStringList cmd;
+ retval = createCrtcBackup();
qDebug() << "Virtual screen size:" << screenSize << "with" << outputSizes.size() << "different screens.";
int offset = 0;
- for (int i = 0; i < outputSizes.size(); ++i) {
- bool ok = false;
+ for (int i = 0; i < outputSizes.size(); ++i) {
const QSize &size = outputSizes.at(i);
if (i < projectors.size()) {
- ok = a->setOutputResolution(projectors.at(i), offset, 0, size, dryRun) || ok;
+ a->setOutputResolution(cmd, projectors.at(i), offset, 0, size);
}
if (i < screens.size()) {
- ok = a->setOutputResolution(screens.at(i), offset, 0, size, dryRun) || ok;
+ a->setOutputResolution(cmd, screens.at(i), offset, 0, size);
}
- offset += size.width();
- if (ok) {
- retval._ok = true;
- }
- }
- if (!dryRun) {
- XUngrabServer(a->_display);
- XSync(a->_display, False);
- }
+ offset += size.width();
+ }
+ retval._ok = runXrandr(cmd);
updateScreenResources(); // Re-Read
if (outputSizes.size() == 1) {
// One output size, at least 2 outputs in total -- clone mode
@@ -478,9 +461,8 @@ ConfigBackup ScreenSetup::setCenteredClone()
return retval;
break;
}
- XGrabServer(a->_display);
- a->disconnectAllCrtcs();
- QSize screenSize;
+ QStringList cmd;
+ QSize screenSize; // Currently unused
for (auto oi : a->_outputMap) {
auto mode = a->getPreferredMode(oi, fallback);
if (mode != nullptr) {
@@ -492,36 +474,28 @@ ConfigBackup ScreenSetup::setCenteredClone()
}
const int x = (screenSize.width() - int(mode->width)) / 2;
const int y = (screenSize.height() - int(mode->height)) / 2;
- if (a->setOutputResolution(oi, x, y, QSize(int(mode->width), int(mode->height)))) {
- retval._ok = true;
- }
- }
- }
- a->setScreenSize(screenSize);
- XUngrabServer(a->_display);
- XSync(a->_display, False);
+ a->setOutputResolution(cmd, oi, x, y, QSize(int(mode->width), int(mode->height)));
+ }
+ }
+ retval._ok = runXrandr(cmd);
return retval;
}
ConfigBackup ScreenSetup::setClone(const QSize &resolution)
{
+ QStringList cmd;
ConfigBackup retval = createCrtcBackup();
- XGrabServer(a->_display);
- a->disconnectAllCrtcs();
- a->setScreenSize(resolution);
for (auto oi : a->_outputMap) {
- if (a->setOutputResolution(oi, 0, 0, resolution)) {
- retval._ok = true;
- }
- }
- XUngrabServer(a->_display);
- XSync(a->_display, False);
+ a->setOutputResolution(cmd, oi, 0, 0, resolution);
+ }
+ retval._ok = runXrandr(cmd);
return retval;
}
ConfigBackup ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &list)
{
ConfigBackup retval;
+ QStringList cmd;
QList<QSize> sizes;
for (auto e : list) {
if (e.second.isEmpty())
@@ -534,9 +508,6 @@ ConfigBackup ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &l
auto screenSize = getTotalSizeHorz(sizes);
if (screenSize.isEmpty())
return retval;
- XGrabServer(a->_display);
- a->disconnectAllCrtcs();
- a->setScreenSize(screenSize);
int x = 0;
for (auto e : list) {
if (e.second.isEmpty())
@@ -546,15 +517,12 @@ ConfigBackup ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &l
for (auto oi : a->_outputMap) {
if (oi->outputName != outputName)
continue;
- if (a->setOutputResolution(oi, x, 0, res)) {
- retval._ok = true;
- }
- }
+ a->setOutputResolution(cmd, oi, x, 0, res);
+ }
}
x += res.width();
- }
- XUngrabServer(a->_display);
- XSync(a->_display, False);
+ }
+ retval._ok = runXrandr(cmd);
return retval;
}
@@ -634,3 +602,24 @@ const ResolutionVector &ScreenSetup::getVirtualResolutions() const
{
return a->_resolutions;
}
+
+bool ScreenSetup::runXrandr(QStringList &cmd)
+{
+ QProcess proc;
+ // Sloppy: Turn off all outputs not found in argument list. Doesn't actually parse the
+ // command line, so if you have a mode that's called like an output, funny things might happen.
+ for (const auto &name : a->_allOutputs) {
+ if (!cmd.contains(name)) {
+ cmd << "--output" << name << "--off";
+ }
+ }
+ qDebug() << "XRANDR:" << cmd;
+ if (CommandLine::testMode())
+ return true;
+ proc.start("xrandr", cmd);
+ proc.waitForFinished(5000);
+ if (proc.state() == QProcess::Running) {
+ proc.kill();
+ }
+ return proc.exitCode() == 0;
+}