From 19033eebd821813bc1b1ad54094bfcea673bc0ac Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 17 Feb 2020 08:24:24 +0100 Subject: Add -d to dump all screen geometry This ignores cloned outputs and overlapping screens. In case of overlapping screens it will remove those screens from the list that cause the least decrease in total screen size (in pixels). --- src/main.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/xprivate.cpp | 2 +- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 59c886b..eac930b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,9 +7,10 @@ #include #include #include +#include namespace { -bool _testMode, _autoSetup, _showGui, _backgroundMode, _wakeup, _center; +bool _testMode, _autoSetup, _showGui, _backgroundMode, _wakeup, _center, _dumpScreens; } namespace CommandLine @@ -20,10 +21,13 @@ bool showGui() { return _showGui; } bool backgroundMode() { return _backgroundMode; } bool wakeup() { return _wakeup; } bool center() { return _center; } +bool dumpScreens() { return _dumpScreens; } } static void parseCommandLine(const QCoreApplication &a); +static void dumpScreens(); + int main(int argc, char *argv[]) { QCoreApplication *a; @@ -54,6 +58,10 @@ int main(int argc, char *argv[]) if (CommandLine::wakeup()) { return Bus::inst()->registerService() ? 0 : 1; } + if (CommandLine::dumpScreens()) { + dumpScreens(); + return 0; + } ScreenSetup::inst()->addMissingEdidResolutions(); ScreenSetup::inst()->initModes(); @@ -110,6 +118,10 @@ static void parseCommandLine(const QCoreApplication &a) QCommandLineOption oCenter(QStringList() << "c" << "center", QCoreApplication::translate("main", "Set all outputs to clone mode. If size differs, center outputs according to largest output.")); parser.addOption(oCenter); + // Dump all screens, non-overlapping (ie. exclude clones) + QCommandLineOption oDumpScreens(QStringList() << "d" << "dump", + QCoreApplication::translate("main", "Dump all non-overlapping screens.")); + parser.addOption(oDumpScreens); // PARSE parser.process(a); _testMode = parser.isSet(oTest); @@ -118,5 +130,73 @@ static void parseCommandLine(const QCoreApplication &a) _backgroundMode = parser.isSet(oBackground); _wakeup = parser.isSet(oWakeup); _center = parser.isSet(oCenter); + _dumpScreens = parser.isSet(oDumpScreens); } +QTextStream& qStdOut() +{ + static QTextStream ts(stdout); + return ts; +} + +static int findConfig(QVector &list) +{ + int area = 0; + bool overlap = false; + struct { + QVector list; + int area = 0; + } best; + for (int i = 0; i < list.size(); ++i) { + const QRect &first = list[i]; + for (int j = i + 1; j < list.size(); ++j) { + if (!list[j].intersects(first)) + continue; + overlap = true; + QVector copy1 = list, copy2 = list; + copy1.remove(i); + copy2.remove(j); + int a1 = findConfig(copy1); + int a2 = findConfig(copy2); + if (a1 > best.area && a1 > a2) { + best.area = a1; + best.list = copy1; + } else if (a2 > best.area) { + best.area = a2; + best.list = copy2; + } + } + area += first.width() * first.height(); + } + if (!overlap) + return area; + list = best.list; + return best.area; +} + +static void dumpScreens() +{ + QVector list; + for (auto *scr : QGuiApplication::screens()) { + list.append(scr->geometry()); + } + findConfig(list); + qSort(list.begin(), list.end(), [](const QRect &one, const QRect &other) -> bool { + return one.y() < other.y() || (one.y() == other.y() && one.x() < other.x()); + }); + int nextX = 0; + int lastY = 0; + qStdOut() << "# x y width height" << endl; + for (const auto &geo : list) { + if (geo.x() != nextX) { + qStdOut() << "# Warning: Next screen has gap to previous one" << endl; + } + qStdOut() << geo.x() << ' ' << geo.y() << ' ' << geo.width() << ' ' << geo.height() << endl; + if (lastY == geo.y()) { + nextX += geo.width(); + } else { + lastY = 0; + } + lastY = geo.y(); + } +} diff --git a/src/xprivate.cpp b/src/xprivate.cpp index 01f265f..c8a45b2 100644 --- a/src/xprivate.cpp +++ b/src/xprivate.cpp @@ -488,7 +488,7 @@ QList XPrivate::getOutputModeForResolution(const XRROutputInfo *output, } } // Sort others descending by dotClock - qSort(others.begin(), others.end(), [](const XRRModeInfo *a, const XRRModeInfo *b) { + qSort(others.begin(), others.end(), [](const XRRModeInfo *a, const XRRModeInfo *b) -> bool { if ((a->modeFlags & RR_DoubleScan) != (b->modeFlags & RR_DoubleScan)) return (a->modeFlags & RR_DoubleScan) == 0; // Prefer non-interlaced resolutions return toVertRefresh(a) > toVertRefresh(b); -- cgit v1.2.3-55-g7522