summaryrefslogtreecommitdiffstats
path: root/src/xx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xx.cpp')
-rw-r--r--src/xx.cpp268
1 files changed, 201 insertions, 67 deletions
diff --git a/src/xx.cpp b/src/xx.cpp
index a5f9d92..d0b6a3d 100644
--- a/src/xx.cpp
+++ b/src/xx.cpp
@@ -4,9 +4,137 @@
#include <QDebug>
#include <QSocketNotifier>
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * This clusterfuck exists because there are name clashes between X11/Xrandr headers
+ * and Qt classes. Hence the split into xx.* and xprivate.* as well as those idiotic
+ * matrjoschka classes. Or I'm just stupid.
+ */
+
+class BackupInternalInternal
+{
+private:
+ XPrivate *x;
+public:
+ CrtcMap map;
+ BackupInternalInternal() : x(nullptr) {
+ qDebug() << "new BackupInternalInternal";
+ }
+ ~BackupInternalInternal() {
+ qDebug() << "delete BackupInternalInternal";
+ freeBackup();
+ }
+ void createBackup(XPrivate *x) {
+ this->x = x;
+ freeBackup();
+ for (CrtcMap::iterator it = x->_crtcMap.begin(); it != x->_crtcMap.end(); ++it) {
+ const auto src = it.value();
+ XRRCrtcInfo *copy = static_cast<XRRCrtcInfo*>(calloc(1, sizeof(XRRCrtcInfo)));
+ copy->outputs = static_cast<RROutput*>(calloc(size_t(src->noutput), sizeof(RROutput)));
+ copy->x = src->x;
+ copy->y = src->y;
+ copy->mode = src->mode;
+ copy->rotation = src->rotation;
+ copy->noutput = src->noutput;
+ for (int i = 0; i < src->noutput; ++i) {
+ copy->outputs[i] = src->outputs[i];
+ }
+ map[it.key()] = copy;
+ }
+ qDebug() << "Created CRTC backup with entries:" << map.size();
+ }
+ void freeBackup() {
+ for (auto i : map) {
+ free(i->outputs);
+ free(i);
+ }
+ map.clear();
+ }
+ void revertChanges()
+ {
+ if (map.isEmpty())
+ return;
+ qDebug() << "Starting revert";
+ XGrabServer(x->_display);
+ x->disconnectAllCrtcs();
+ QSize screenSize;
+ for (auto e : map) {
+ if (e->mode == None || !x->_modeMap.contains(e->mode))
+ continue;
+ 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);
+ freeBackup();
+ }
+};
+
+class BackupInternal
+{
+public:
+ BackupInternal() {
+ qDebug() << "new BackupInternal";
+ }
+ ~BackupInternal() {
+ qDebug() << "delete BackupInternal";
+ }
+ QSharedPointer<BackupInternalInternal> backup;
+};
+
+ConfigBackup::ConfigBackup()
+{
+ _ok = false;
+ a = new BackupInternal;
+}
+
+ConfigBackup::ConfigBackup(XPrivate *x)
+{
+ _ok = false;
+ a = new BackupInternal;
+ a->backup = QSharedPointer<BackupInternalInternal>(new BackupInternalInternal);
+ a->backup->createBackup(x);
+}
+
+ConfigBackup::~ConfigBackup()
+{
+ delete a;
+}
+
+ConfigBackup& ConfigBackup::operator=(const ConfigBackup &other)
+{
+ if (this == &other)
+ return *this;
+ delete a;
+ _ok = other._ok;
+ a = new BackupInternal;
+ a->backup = other.a->backup;
+ return *this;
+}
+
+ConfigBackup::ConfigBackup(const ConfigBackup &other)
+{
+ _ok = other._ok;
+ a = new BackupInternal;
+ a->backup = other.a->backup;
+}
+
+void ConfigBackup::revert()
+{
+ a->backup->revertChanges();
+}
+
+static QWeakPointer<BackupInternalInternal> currentBackup;
+
+/*
+ * Slightly more normal code starts here
+ */
static ScreenInfo initScreenInfo(const OutputInfo *oi, const ModeMap &om)
@@ -183,10 +311,14 @@ ScreenMode ScreenSetup::getCurrentMode()
return ScreenMode::Clone;
}
-ScreenMode ScreenSetup::setDefaultMode(bool dryRun)
+ConfigBackup ScreenSetup::setDefaultMode(bool dryRun, ScreenMode &mode)
{
- if (a->_outputMap.size() == 1) // Only one output exists, do nothing
- return ScreenMode::Single;
+ ConfigBackup retval;
+ if (a->_outputMap.size() == 1) { // Only one output exists, do nothing
+ retval._ok = (a->_outputMap.begin().value()->mode != nullptr);
+ mode = ScreenMode::Single;
+ return retval;
+ }
QMap<QString, OutputInfo*> screenMap;
QMap<QString, OutputInfo*> projectorMap;
for (auto o : a->_outputMap) {
@@ -201,11 +333,13 @@ ScreenMode ScreenSetup::setDefaultMode(bool dryRun)
auto screens = screenMap.values();
qDebug() << projectors.size() << "projectors," << screens.size() << "screens.";
QList<QSize> outputSizes = a->getTotalSize(projectors, screens);
- if (outputSizes.isEmpty())
- return ScreenMode::Advanced; // Dunno lol
+ if (outputSizes.isEmpty()) {
+ mode = ScreenMode::Advanced; // Dunno lol
+ return retval;
+ }
QSize screenSize = getTotalSizeHorz(outputSizes);
if (!dryRun) {
- a->createCrtcBackup();
+ retval = createCrtcBackup();
XGrabServer(a->_display);
a->disconnectAllCrtcs();
// Set new screen size
@@ -216,25 +350,34 @@ ScreenMode ScreenSetup::setDefaultMode(bool dryRun)
int offset = 0;
for (int i = 0; i < outputSizes.size(); ++i) {
+ bool ok = false;
const QSize &size = outputSizes.at(i);
if (i < projectors.size()) {
- a->setOutputResolution(projectors.at(i), offset, 0, size, dryRun);
+ ok = a->setOutputResolution(projectors.at(i), offset, 0, size, dryRun) || ok;
}
if (i < screens.size()) {
- a->setOutputResolution(screens.at(i), offset, 0, size, dryRun);
+ ok = a->setOutputResolution(screens.at(i), offset, 0, size, dryRun) || ok;
}
offset += size.width();
+ if (ok) {
+ retval._ok = true;
+ }
}
if (!dryRun) {
XUngrabServer(a->_display);
XSync(a->_display, False);
}
updateScreenResources(); // Re-Read
- if (outputSizes.size() == 1) // One output size, at least 2 outputs in total -- clone mode
- return ScreenMode::Clone;
- if (outputSizes.size() == 2 && a->_outputMap.size() == 2) // Two outputs, two sizes -- extended
- return ScreenMode::Dual;
- return ScreenMode::Advanced; // Must be more than 2 outputs -> something more involved
+ if (outputSizes.size() == 1) {
+ // One output size, at least 2 outputs in total -- clone mode
+ mode = ScreenMode::Clone;
+ } else if (outputSizes.size() == 2 && a->_outputMap.size() == 2) {
+ // Two outputs, two sizes -- extended
+ mode = ScreenMode::Dual;
+ } else {
+ mode = ScreenMode::Advanced; // Must be more than 2 outputs -> something more involved
+ }
+ return retval;
}
//___________________________________________________________________________
@@ -282,9 +425,9 @@ ScreenSetup::~ScreenSetup()
delete a;
}
-bool ScreenSetup::setCenteredClone()
+ConfigBackup ScreenSetup::setCenteredClone()
{
- a->createCrtcBackup();
+ ConfigBackup retval = createCrtcBackup();
XRRModeInfo *fallback = nullptr;
for (auto m : a->_modeMap) {
if (m->width == 1024 && m->height == 768) {
@@ -294,46 +437,48 @@ bool ScreenSetup::setCenteredClone()
}
XGrabServer(a->_display);
a->disconnectAllCrtcs();
- QSize screenSize;
- bool ok = false;
+ QSize screenSize;
for (auto oi : a->_outputMap) {
auto mode = a->getPreferredMode(oi, fallback);
if (mode != nullptr) {
if (int(mode->width) > screenSize.width()) {
- screenSize.setWidth(mode->width);
+ screenSize.setWidth(int(mode->width));
}
if (int(mode->height) > screenSize.height()) {
- screenSize.setHeight(mode->height);
- }
- // TODO: CENTER
- const int x = (screenSize.width() - mode->width) / 2;
- const int y = (screenSize.height() - mode->height) / 2;
- ok = a->setOutputResolution(oi, x, y, QSize(int(mode->width), int(mode->height))) || ok;
+ screenSize.setHeight(int(mode->height));
+ }
+ 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);
- return ok;
+ return retval;
}
-bool ScreenSetup::setClone(const QSize &resolution)
+ConfigBackup ScreenSetup::setClone(const QSize &resolution)
{
- a->createCrtcBackup();
+ ConfigBackup retval = createCrtcBackup();
XGrabServer(a->_display);
a->disconnectAllCrtcs();
- a->setScreenSize(resolution);
- bool ok = false;
+ a->setScreenSize(resolution);
for (auto oi : a->_outputMap) {
- ok = a->setOutputResolution(oi, 0, 0, resolution) || ok;
+ if (a->setOutputResolution(oi, 0, 0, resolution)) {
+ retval._ok = true;
+ }
}
XUngrabServer(a->_display);
XSync(a->_display, False);
- return ok;
+ return retval;
}
-bool ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &list)
+ConfigBackup ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &list)
{
+ ConfigBackup retval;
QList<QSize> sizes;
for (auto e : list) {
if (e.second.isEmpty())
@@ -341,16 +486,15 @@ bool ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &list)
sizes.append(e.first);
}
if (sizes.isEmpty())
- return false;
- a->createCrtcBackup();
+ return retval;
+ retval = createCrtcBackup();
auto screenSize = getTotalSizeHorz(sizes);
if (screenSize.isEmpty())
- return false;
+ return retval;
XGrabServer(a->_display);
a->disconnectAllCrtcs();
a->setScreenSize(screenSize);
- int x = 0;
- bool ok = false;
+ int x = 0;
for (auto e : list) {
if (e.second.isEmpty())
continue;
@@ -359,39 +503,16 @@ bool ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &list)
for (auto oi : a->_outputMap) {
if (oi->outputName != outputName)
continue;
- ok = a->setOutputResolution(oi, x, 0, res) || ok;
+ if (a->setOutputResolution(oi, x, 0, res)) {
+ retval._ok = true;
+ }
}
}
x += res.width();
}
XUngrabServer(a->_display);
XSync(a->_display, False);
- return ok;
-}
-
-void ScreenSetup::revertChanges()
-{
- if (a->_crtcBackup.isEmpty())
- return;
- qDebug() << "Starting revert";
- XGrabServer(a->_display);
- a->disconnectAllCrtcs();
- QSize screenSize;
- for (auto e : a->_crtcBackup) {
- if (e->mode == None || !a->_modeMap.contains(e->mode))
- continue;
- screenSize = screenSize.expandedTo(QSize(e->x + int(a->_modeMap[e->mode]->width), e->y + int(a->_modeMap[e->mode]->height)));
- }
- a->setScreenSize(screenSize);
- for (CrtcMap::iterator it = a->_crtcBackup.begin(); it != a->_crtcBackup.end(); ++it) {
- auto e = it.value();
- if (e->mode == None)
- continue;
- XRRSetCrtcConfig(a->_display, a->_screenResources, it.key(), CurrentTime,
- e->x, e->y, e->mode, e->rotation, e->outputs, e->noutput);
- }
- XUngrabServer(a->_display);
- XSync(a->_display, False);
+ return retval;
}
static bool modeBiggerThan(const QSize &a, const QSize &b)
@@ -423,6 +544,19 @@ ResolutionVector ScreenSetup::getCommonModes() const
return ret;
}
+ConfigBackup ScreenSetup::createCrtcBackup()
+{
+ auto bd = currentBackup.toStrongRef();
+ if (bd.data() != nullptr && !bd->map.isEmpty()) {
+ ConfigBackup backup;
+ backup.a->backup = bd;
+ return backup;
+ }
+ ConfigBackup backup(a);
+ currentBackup = backup.a->backup.toWeakRef();
+ return backup;
+}
+
/**
* Return number of connected (no active) outputs according to last query
*/