diff options
Diffstat (limited to 'src/xx.cpp')
-rw-r--r-- | src/xx.cpp | 131 |
1 files changed, 60 insertions, 71 deletions
@@ -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; +} |