summaryrefslogtreecommitdiffstats
path: root/src/x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/x.cpp')
-rw-r--r--src/x.cpp73
1 files changed, 47 insertions, 26 deletions
diff --git a/src/x.cpp b/src/x.cpp
index 73662c5..ef43f08 100644
--- a/src/x.cpp
+++ b/src/x.cpp
@@ -15,7 +15,7 @@ enum class Projector {
struct OutputInfo {
OutputInfo(RROutput id, XRROutputInfo *output, XRRCrtcInfo *crtc, XRRModeInfo *mode)
- : output(output), crtc(crtc), mode(mode), id(id), position(-1), isProjector(Projector::No) {}
+ : output(output), crtc(crtc), mode(mode), id(id), position(-1), outputType(Projector::No) {}
~OutputInfo() {
XRRFreeOutputInfo(output);
}
@@ -26,12 +26,12 @@ struct OutputInfo {
QString modelName;
QString outputName;
int position;
- Projector isProjector;
+ Projector outputType;
};
ScreenInfo::ScreenInfo(const OutputInfo *oi, const ModeMap &om)
: position(oi->position), name(oi->modelName), output(oi->outputName),
- isProjector(oi->isProjector == Projector::Yes)
+ isProjector(oi->outputType == Projector::Yes)
{
if (oi->mode != nullptr) {
currentResolution = QSize(QSize(int(oi->mode->width), int(oi->mode->height)));
@@ -180,12 +180,15 @@ void ScreenSetup::updateScreenResources()
}
const QString outputName = QString::fromLocal8Bit(info->name, info->nameLen);
tempMap.insert(_screenResources->outputs[i], outputName);
- if (info->connection != RR_Connected) {
+ if (info->connection == RR_Disconnected) {
qDebug() << "Ignoring disconnected output" << outputName;
XRRFreeOutputInfo(info);
continue;
}
+ bool disconnected = false;
if (info->crtc == None) {
+ disconnected = true;
+ qDebug() << "Connected output" << outputName << "has no CRTC -- trying to find free one";
info->crtc = getFreeCrtc(info);
}
if (!_crtcMap.contains(info->crtc)) {
@@ -195,23 +198,25 @@ void ScreenSetup::updateScreenResources()
}
XRRCrtcInfo *crtc = _crtcMap.value(info->crtc);
XRRModeInfo *mode = nullptr;
- if (!_modeMap.contains(crtc->mode)) {
- qDebug() << "Have output" << outputName << " with crtc with no known mode -- offline?";
- } else {
- mode = _modeMap.value(crtc->mode);
+ if (!disconnected) {
+ if (!_modeMap.contains(crtc->mode)) {
+ qDebug() << "Have output" << outputName << " with crtc with no known mode -- offline?";
+ } else {
+ mode = _modeMap.value(crtc->mode);
+ }
}
OutputInfo *oi = new OutputInfo(_screenResources->outputs[i], info, crtc, mode);
oi->outputName = outputName;
if (!this->readEdid(oi)) { // We have no EDID - take it as an indicator that there's a dumb output split/switch box
- oi->isProjector = Projector::Maybe;
+ oi->outputType = Projector::Maybe;
} else if ((info->mm_height == 0 && info->mm_width == 0) || isProjectorName(oi->modelName)) {
- oi->isProjector = Projector::Yes; // Screens with size 0x0 are projectors by convention
+ oi->outputType = Projector::Yes; // Screens with size 0x0 are projectors by convention
} else if (info->mm_width > 500 && info->mm_height > 500) { // Big screen - probably should be handled like a projector
- oi->isProjector = Projector::Yes;
+ oi->outputType = Projector::Yes;
} else if (info->mm_width > 350 && info->mm_height > 350) { // Somewhere in-between
- oi->isProjector = Projector::Maybe;
+ oi->outputType = Projector::Maybe;
}
- typeCount[oi->isProjector]++;
+ typeCount[oi->outputType]++;
_outputMap.insert(_screenResources->outputs[i], oi);
qDebug() << "Connected" << outputName << "-- Clones:" << info->nclone << "Modes:" << info->nmode << "Crtcs:" << info->ncrtc << "Preferred:" << info->npreferred;
}
@@ -221,8 +226,8 @@ void ScreenSetup::updateScreenResources()
if (typeCount[Projector::Maybe] > 0 && typeCount[Projector::No] > 0) {
// Potential projector(s) and normal screen, promote
for (OutputInfo *info : _outputMap) {
- if (info->isProjector == Projector::Maybe) {
- info->isProjector = Projector::Yes;
+ if (info->outputType == Projector::Maybe) {
+ info->outputType = Projector::Yes;
break;
}
}
@@ -244,6 +249,9 @@ void ScreenSetup::updateScreenResources()
int endX = -0xffff;
qDebug() << "From left to right";
for (OutputInfo* output : screens) {
+ if (output->mode == nullptr) {
+ qDebug() << "(Ignoring" << output->outputName << "since it's disconnected)";
+ }
if (output->crtc->x >= endX) {
QSize res(0, 0);
if (_modeMap.contains(output->crtc->mode)) {
@@ -355,7 +363,7 @@ void ScreenSetup::initModes()
// Finally copy all those the projector supports to other outputs
for (auto key : _outputMap.keys()) {
OutputInfo *oi = _outputMap[key];
- if (oi->isProjector == Projector::Yes) {
+ if (oi->outputType == Projector::Yes) {
copyModesToAll(key, oi->output->nmode);
}
}
@@ -421,9 +429,10 @@ bool ScreenSetup::setOutputResolution(OutputInfo *oi, int x, int y, const QSize
{
RRMode mode = getOutputModeForResolution(oi->output, size);
if (mode == None) {
+ qDebug() << "Cannot set" << oi->outputName << "to" << size << " since it's not supported";
if (oi->output->nmode == 0)
return false;
- qDebug() << oi->outputName << "doesn't support" << size << "- falling back to its default";
+ qDebug() << "falling back to its default";
mode = oi->output->modes[0];
}
if (!dryRun) {
@@ -441,19 +450,17 @@ bool ScreenSetup::setOutputResolution(OutputInfo *oi, int x, int y, const QSize
ScreenMode ScreenSetup::getCurrentMode()
{
- int numConnected = 0;
bool notAtOrigin = false;
for (auto oi : _outputMap) {
if (oi->mode != nullptr) {
- ++numConnected;
if (oi->crtc->x != 0 || oi->crtc->y != 0) {
notAtOrigin = true;
}
}
}
- if (numConnected == 1)
+ if (_outputMap.size() == 1)
return ScreenMode::Single;
- if (numConnected > 2)
+ if (_outputMap.size() > 2)
return ScreenMode::Advanced;
if (notAtOrigin)
return ScreenMode::Dual;
@@ -467,8 +474,8 @@ ScreenMode ScreenSetup::setDefaultMode(bool dryRun)
QMap<QString, OutputInfo*> screenMap;
QMap<QString, OutputInfo*> projectorMap;
for (auto o : _outputMap) {
- qDebug() << o->outputName << quint32(o->isProjector);
- if (o->isProjector == Projector::Yes) {
+ qDebug() << o->outputName << quint32(o->outputType);
+ if (o->outputType == Projector::Yes) {
projectorMap.insert(o->outputName, o);
} else {
screenMap.insert(o->outputName, o);
@@ -572,8 +579,16 @@ RRCrtc ScreenSetup::getFreeCrtc(const XRROutputInfo* output) const
{
for (int i = 0; i < output->ncrtc; ++i) {
RRCrtc c = output->crtcs[i];
- for (auto oi : _outputMap) {
- if (oi->output->crtc == c)
+ if (!_crtcMap.contains(c)) {
+ // Unknown CRTC!? Scan already known outputs
+ qDebug() << "BUG: Output has unknown possible CRTC";
+ for (auto oi : _outputMap) {
+ if (oi->output->crtc == c)
+ goto next;
+ }
+ } else {
+ // Known CRTC -- see if free
+ if (_crtcMap[c]->noutput > 0)
goto next;
}
return c;
@@ -690,11 +705,15 @@ bool ScreenSetup::setClone(const QSize &resolution)
bool ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &list)
{
- createCrtcBackup();
QList<QSize> sizes;
for (auto e : list) {
+ if (e.second.isEmpty())
+ continue;
sizes.append(e.first);
}
+ if (sizes.isEmpty())
+ return false;
+ createCrtcBackup();
auto screenSize = getTotalSizeHorz(sizes);
if (screenSize.isEmpty())
return false;
@@ -704,6 +723,8 @@ bool ScreenSetup::setCustom(const QList<QPair<QSize, QList<QString>>> &list)
int x = 0;
bool ok = false;
for (auto e : list) {
+ if (e.second.isEmpty())
+ continue;
const QSize &res = e.first;
for (auto outputName : e.second) {
for (auto oi : _outputMap) {