backends/drm: don't wake displays up when outputs get temporarily removed

When some displays go to sleep, that can be wrongly detected as a temporary
hotunplug by the driver. In order to not wrongly wake up the system with
such a display, detect that scenario and set the 'new' output to dpms off
again.

BUG: 452553
BUG: 379474
This commit is contained in:
Xaver Hugl 2022-09-13 16:54:55 +02:00
parent 99244efa3b
commit 482a1f0fb5
3 changed files with 26 additions and 1 deletions

View file

@ -212,6 +212,21 @@ DrmGpu *DrmBackend::addGpu(const QString &fileName)
void DrmBackend::addOutput(DrmAbstractOutput *o)
{
const bool allOff = std::all_of(m_outputs.begin(), m_outputs.end(), [](Output *output) {
return output->dpmsMode() != Output::DpmsMode::On;
});
if (allOff && m_recentlyUnpluggedDpmsOffOutputs.contains(o->uuid())) {
if (DrmOutput *drmOutput = qobject_cast<DrmOutput *>(o)) {
// When the system is in dpms power saving mode, KWin turns on all outputs if the user plugs a new output in
// as that's an intentional action and they expect to see the output light up.
// Some outputs however temporarily disconnect in some situations, most often shortly after they go into standby.
// To not turn on outputs in that case, restore the previous dpms state
drmOutput->updateDpmsMode(Output::DpmsMode::Off);
drmOutput->pipeline()->setActive(false);
drmOutput->renderLoop()->inhibit();
m_recentlyUnpluggedDpmsOffOutputs.removeOne(drmOutput->uuid());
}
}
m_outputs.append(o);
Q_EMIT outputAdded(o);
o->updateEnabled(true);
@ -219,6 +234,13 @@ void DrmBackend::addOutput(DrmAbstractOutput *o)
void DrmBackend::removeOutput(DrmAbstractOutput *o)
{
if (o->dpmsMode() == Output::DpmsMode::Off) {
const QUuid id = o->uuid();
m_recentlyUnpluggedDpmsOffOutputs.push_back(id);
QTimer::singleShot(1000, this, [this, id]() {
m_recentlyUnpluggedDpmsOffOutputs.removeOne(id);
});
}
o->updateEnabled(false);
m_outputs.removeOne(o);
Q_EMIT outputRemoved(o);

View file

@ -89,7 +89,7 @@ private:
std::unique_ptr<QSocketNotifier> m_socketNotifier;
Session *m_session;
QVector<DrmAbstractOutput *> m_outputs;
DrmVirtualOutput *m_placeHolderOutput = nullptr;
QVector<QUuid> m_recentlyUnpluggedDpmsOffOutputs;
const QStringList m_explicitGpus;
std::vector<std::unique_ptr<DrmGpu>> m_gpus;

View file

@ -1292,6 +1292,9 @@ void Workspace::updateOutputs(const QVector<Output *> &outputOrder)
m_tileManagers[output] = std::make_unique<TileManager>(output);
connect(output, &Output::aboutToTurnOff, this, &Workspace::createDpmsFilter);
connect(output, &Output::dpmsModeChanged, this, &Workspace::maybeDestroyDpmsFilter);
if (output->dpmsMode() != Output::DpmsMode::On) {
createDpmsFilter();
}
Q_EMIT outputAdded(output);
}
maybeDestroyDpmsFilter();