outputconfigurationstore: add a fallback for when edid parsing fails
When edid parsing fails, KWin will base output settings on the connector, which isn't great on its own, but at least works in many cases. When the edid can be parsed later though, the display settings will reset because now the edid identifier is used to exclude the old config (in which the latter is missing). To work around that, this commit adds output identification based on the edid hash, which is also not ideal, but can be safely matched with in case no output config with a matching edid identifier exists.
This commit is contained in:
parent
3cafc20981
commit
7e095412aa
2 changed files with 30 additions and 1 deletions
|
@ -133,10 +133,13 @@ std::optional<size_t> OutputConfigurationStore::findOutput(Output *output, const
|
||||||
const bool uniqueEdid = !output->edid().identifier().isEmpty() && std::none_of(allOutputs.begin(), allOutputs.end(), [output](Output *otherOutput) {
|
const bool uniqueEdid = !output->edid().identifier().isEmpty() && std::none_of(allOutputs.begin(), allOutputs.end(), [output](Output *otherOutput) {
|
||||||
return otherOutput != output && otherOutput->edid().identifier() == output->edid().identifier();
|
return otherOutput != output && otherOutput->edid().identifier() == output->edid().identifier();
|
||||||
});
|
});
|
||||||
|
const bool uniqueEdidHash = !output->edid().hash().isEmpty() && std::none_of(allOutputs.begin(), allOutputs.end(), [output](Output *otherOutput) {
|
||||||
|
return otherOutput != output && otherOutput->edid().hash() == output->edid().hash();
|
||||||
|
});
|
||||||
const bool uniqueMst = !output->mstPath().isEmpty() && std::none_of(allOutputs.begin(), allOutputs.end(), [output](Output *otherOutput) {
|
const bool uniqueMst = !output->mstPath().isEmpty() && std::none_of(allOutputs.begin(), allOutputs.end(), [output](Output *otherOutput) {
|
||||||
return otherOutput != output && otherOutput->edid().identifier() == output->edid().identifier() && otherOutput->mstPath() == output->mstPath();
|
return otherOutput != output && otherOutput->edid().identifier() == output->edid().identifier() && otherOutput->mstPath() == output->mstPath();
|
||||||
});
|
});
|
||||||
const auto it = std::find_if(m_outputs.begin(), m_outputs.end(), [uniqueEdid, uniqueMst, output](const auto &outputState) {
|
auto it = std::find_if(m_outputs.begin(), m_outputs.end(), [&](const auto &outputState) {
|
||||||
if (output->edid().isValid()) {
|
if (output->edid().isValid()) {
|
||||||
if (outputState.edidIdentifier != output->edid().identifier()) {
|
if (outputState.edidIdentifier != output->edid().identifier()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -144,6 +147,13 @@ std::optional<size_t> OutputConfigurationStore::findOutput(Output *output, const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!output->edid().hash().isEmpty()) {
|
||||||
|
if (outputState.edidHash != output->edid().hash()) {
|
||||||
|
return false;
|
||||||
|
} else if (uniqueEdidHash) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (outputState.mstPath != output->mstPath()) {
|
if (outputState.mstPath != output->mstPath()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (uniqueMst) {
|
} else if (uniqueMst) {
|
||||||
|
@ -151,6 +161,12 @@ std::optional<size_t> OutputConfigurationStore::findOutput(Output *output, const
|
||||||
}
|
}
|
||||||
return outputState.connectorName == output->name();
|
return outputState.connectorName == output->name();
|
||||||
});
|
});
|
||||||
|
if (it == m_outputs.end() && uniqueEdidHash) {
|
||||||
|
// handle the edge case of EDID parsing failing in the past but not failing anymore
|
||||||
|
it = std::find_if(m_outputs.begin(), m_outputs.end(), [&](const auto &outputState) {
|
||||||
|
return outputState.edidHash == output->edid().hash();
|
||||||
|
});
|
||||||
|
}
|
||||||
if (it != m_outputs.end()) {
|
if (it != m_outputs.end()) {
|
||||||
return std::distance(m_outputs.begin(), it);
|
return std::distance(m_outputs.begin(), it);
|
||||||
} else {
|
} else {
|
||||||
|
@ -197,6 +213,7 @@ void OutputConfigurationStore::storeConfig(const QList<Output *> &allOutputs, bo
|
||||||
m_outputs[*outputIndex] = OutputState{
|
m_outputs[*outputIndex] = OutputState{
|
||||||
.edidIdentifier = output->edid().identifier(),
|
.edidIdentifier = output->edid().identifier(),
|
||||||
.connectorName = output->name(),
|
.connectorName = output->name(),
|
||||||
|
.edidHash = output->edid().isValid() ? output->edid().hash() : QString{},
|
||||||
.mstPath = output->mstPath(),
|
.mstPath = output->mstPath(),
|
||||||
.mode = ModeData{
|
.mode = ModeData{
|
||||||
.size = mode->size(),
|
.size = mode->size(),
|
||||||
|
@ -229,6 +246,7 @@ void OutputConfigurationStore::storeConfig(const QList<Output *> &allOutputs, bo
|
||||||
m_outputs[*outputIndex] = OutputState{
|
m_outputs[*outputIndex] = OutputState{
|
||||||
.edidIdentifier = output->edid().identifier(),
|
.edidIdentifier = output->edid().identifier(),
|
||||||
.connectorName = output->name(),
|
.connectorName = output->name(),
|
||||||
|
.edidHash = output->edid().isValid() ? output->edid().hash() : QString{},
|
||||||
.mstPath = output->mstPath(),
|
.mstPath = output->mstPath(),
|
||||||
.mode = ModeData{
|
.mode = ModeData{
|
||||||
.size = mode->size(),
|
.size = mode->size(),
|
||||||
|
@ -554,6 +572,12 @@ void OutputConfigurationStore::load()
|
||||||
hasIdentifier = true;
|
hasIdentifier = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (const auto it = data.find("edidHash"); it != data.end()) {
|
||||||
|
if (const auto str = it->toString(); !str.isEmpty()) {
|
||||||
|
state.edidHash = str;
|
||||||
|
hasIdentifier = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (const auto it = data.find("connectorName"); it != data.end()) {
|
if (const auto it = data.find("connectorName"); it != data.end()) {
|
||||||
if (const auto str = it->toString(); !str.isEmpty()) {
|
if (const auto str = it->toString(); !str.isEmpty()) {
|
||||||
state.connectorName = str;
|
state.connectorName = str;
|
||||||
|
@ -576,6 +600,7 @@ void OutputConfigurationStore::load()
|
||||||
const bool hasDuplicate = std::any_of(outputDatas.begin(), outputDatas.end(), [&state](const auto &data) {
|
const bool hasDuplicate = std::any_of(outputDatas.begin(), outputDatas.end(), [&state](const auto &data) {
|
||||||
return data
|
return data
|
||||||
&& data->edidIdentifier == state.edidIdentifier
|
&& data->edidIdentifier == state.edidIdentifier
|
||||||
|
&& data->edidHash == state.edidHash
|
||||||
&& data->mstPath == state.mstPath
|
&& data->mstPath == state.mstPath
|
||||||
&& data->connectorName == state.connectorName;
|
&& data->connectorName == state.connectorName;
|
||||||
});
|
});
|
||||||
|
@ -808,6 +833,9 @@ void OutputConfigurationStore::save()
|
||||||
if (output.edidIdentifier) {
|
if (output.edidIdentifier) {
|
||||||
o["edidIdentifier"] = *output.edidIdentifier;
|
o["edidIdentifier"] = *output.edidIdentifier;
|
||||||
}
|
}
|
||||||
|
if (!output.edidHash.isEmpty()) {
|
||||||
|
o["edidHash"] = output.edidHash;
|
||||||
|
}
|
||||||
if (output.connectorName) {
|
if (output.connectorName) {
|
||||||
o["connectorName"] = *output.connectorName;
|
o["connectorName"] = *output.connectorName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ private:
|
||||||
std::optional<QString> edidIdentifier;
|
std::optional<QString> edidIdentifier;
|
||||||
std::optional<QString> connectorName;
|
std::optional<QString> connectorName;
|
||||||
// empty if invalid
|
// empty if invalid
|
||||||
|
QString edidHash;
|
||||||
QString mstPath;
|
QString mstPath;
|
||||||
// actual state
|
// actual state
|
||||||
std::optional<ModeData> mode;
|
std::optional<ModeData> mode;
|
||||||
|
|
Loading…
Reference in a new issue