diff options
Diffstat (limited to 'src/x.cpp')
-rw-r--r-- | src/x.cpp | 73 |
1 files changed, 47 insertions, 26 deletions
@@ -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) { |