drm config: auto load and save

Signed-off-by: Hongfei Shang <shanghongfei@kylinos.cn>
This commit is contained in:
Hongfei Shang 2022-07-17 22:50:00 +08:00
parent 71b3e39e18
commit 41db6a7a48
5 changed files with 212 additions and 2 deletions

View File

@ -431,12 +431,205 @@ namespace KWinKScreenIntegration
Q_UNREACHABLE();
}
}
static int stringToRotation(const QString &text)
{
static const QHash<QString, int> stringToTransform {
{ QStringLiteral("normal"), Rotation::None },
{ QStringLiteral("rotate-90"), Rotation::Left },
{ QStringLiteral("rotate-180"), Rotation::Inverted },
{ QStringLiteral("rotate-270"), Rotation::Right },
};
return stringToTransform.value(text, Rotation::None);
}
QJsonObject configToJson(const KConfigGroup &outputConfig)
{
QJsonObject obj;
const auto serializePoint = [](const QPoint &point) {
QJsonObject obj;
obj[QLatin1String("x")] = point.x();
obj[QLatin1String("y")] = point.y();
return obj;
};
const auto serializeSize = [](const QSize &size) {
QJsonObject obj;
obj[QLatin1String("width")] = size.width();
obj[QLatin1String("height")] = size.height();
return obj;
};
const auto serializeMode = [serializeSize](const QSize &size, const int& refresh) {
QJsonObject obj;
obj[QLatin1String("size")] = serializeSize(size);
obj[QLatin1String("refreshRate")] = refresh;
return obj;
};
if (outputConfig.hasKey("Primary")) {
obj[QLatin1String("primary")] = outputConfig.readEntry<bool>("Primary", false);
}
obj[QLatin1String("enabled")] = outputConfig.readEntry<bool>("Enable", true);
obj[QLatin1String("pos")] = serializePoint(outputConfig.readEntry<QPoint>("Position", QPoint(0, 0)));
obj[QLatin1String("scale")] = outputConfig.readEntry("Scale", 1.0);
obj[QLatin1String("rotation")] = stringToRotation(outputConfig.readEntry("Transform", "normal"));
if (outputConfig.hasKey("Mode")) {
QString mode = outputConfig.readEntry("Mode");
QStringList list = mode.split("_");
QStringList size = list[0].split("x");
if (list.size() > 1 && size.size() > 1) {
int width = size[0].toInt();
int height = size[1].toInt();
int refreshRate = list[1].toInt();
obj["mode"] = serializeMode(QSize(width, height), qRound(refreshRate / 1000.0));
qCDebug(KWIN_DRM) << " mode:" << width << "x" << height << "@" << refreshRate;
}
}
return obj;
}
QString enabledOutputsHash(const QVector<DrmAbstractOutput*> &outputs)
{
bool cloned = true;
QStringList hashedOutputs;
QRect geo;
AbstractWaylandOutput::Transform trans = AbstractWaylandOutput::Transform::Normal;
hashedOutputs.reserve(outputs.count());
for (auto output : qAsConst(outputs)) {
if (geo.isEmpty()) {
geo = output->geometry();
trans = output->transform();
}
if (!output->isPlaceholder() && output->isEnabled()) {
cloned = cloned && (geo == output->geometry()) && (trans == output->transform());
hashedOutputs << outputHash(output);
}
}
std::sort(hashedOutputs.begin(), hashedOutputs.end());
const auto hash = QCryptographicHash::hash(hashedOutputs.join(QString()).toLatin1(), QCryptographicHash::Md5);
QString result = QString(cloned ? "1" : "0").append(hash.toHex());
return result;
}
void checkOutputsIntersects(const QVector<DrmAbstractOutput*> &outputs)
{
QVector<QRect> rects;
for (const auto &output : qAsConst(outputs)) {
if (output->isPlaceholder()) {
continue;
}
for (const auto &rect : qAsConst(rects)) {
if (rect == output->geometry()) {
break;
}
QRect rectWithExtra = rect.adjusted(-1, -1, 1, 1);
if (!rectWithExtra.intersects(output->geometry())) {
qCWarning(KWIN_DRM) << "Oops," << output->geometry() << "not align with" << rects;
break;
}
}
rects.append(output->geometry());
}
}
static QString transformToString(DrmOutput::Transform transform)
{
switch (transform) {
case DrmOutput::Transform::Normal:
return QStringLiteral("normal");
case DrmOutput::Transform::Rotated90:
return QStringLiteral("rotate-90");
case DrmOutput::Transform::Rotated180:
return QStringLiteral("rotate-180");
case DrmOutput::Transform::Rotated270:
return QStringLiteral("rotate-270");
case DrmOutput::Transform::Flipped:
return QStringLiteral("flip");
case DrmOutput::Transform::Flipped90:
return QStringLiteral("flip-90");
case DrmOutput::Transform::Flipped180:
return QStringLiteral("flip-180");
case DrmOutput::Transform::Flipped270:
return QStringLiteral("flip-270");
default:
return QStringLiteral("normal");
}
}
QMap<DrmAbstractOutput*, QJsonObject> outputsKylinConfig(const QVector<DrmAbstractOutput*> &outputs)
{
const auto outputGroup = kwinApp()->config()->group("DrmOutputs");
const auto outputRootCfg = outputGroup.group(connectedOutputsHash(outputs));
const auto activeUuid = outputRootCfg.readEntry("Active", enabledOutputsHash(outputs));
const auto outputConfigGroup = outputGroup.group(activeUuid);
QMap<DrmAbstractOutput*, QJsonObject> ret;
for (const auto &output : qAsConst(outputs)) {
if (output->isPlaceholder()) {
continue;
}
const auto outputConfig = outputConfigGroup.group(outputHash(output));
if (!ret.contains(output) && outputConfig.exists()) {
ret[output] = configToJson(outputConfig);
}
}
return ret;
}
void writeOutputsKylinConfig(const QVector<DrmAbstractOutput*> &outputs, const AbstractOutput* primaryOutput)
{
if (outputs.isEmpty())
return;
auto outputRootCfg = KSharedConfig::openConfig()->group("DrmOutputs").group(connectedOutputsHash(outputs));
const QString activeHash = enabledOutputsHash(outputs);
outputRootCfg.writeEntry("Active", activeHash);
outputRootCfg.sync();
auto outputCfgGroup = KSharedConfig::openConfig()->group("DrmOutputs").group(activeHash);
for (const auto &output : qAsConst(outputs)) {
if (output->isPlaceholder()) {
continue;
}
auto outputCfg = outputCfgGroup.group(outputHash(output));
qCDebug(KWIN_DRM) << "Writing [" << activeHash << "]["<< outputHash(output) << "]";
const QString info = QString(output->manufacturer() + QLatin1Char(' ') + output->model() + QLatin1Char(' ') + output->name());
qCDebug(KWIN_DRM) << " info:" << info;
outputCfg.writeEntry("A_Info", info);
outputCfg.writeEntry<bool>("Primary", primaryOutput == output);
outputCfg.writeEntry<bool>("Enable", output->isEnabled());
QPoint pos(0, 0);
pos.setX(output->geometry().x());
pos.setY(output->geometry().y());
outputCfg.writeEntry<QPoint>("Position", pos);
qCDebug(KWIN_DRM) << " pos:" << pos;
QString mode;
mode += QString::number(output->modeSize().width());
mode += "x";
mode += QString::number(output->modeSize().height());
mode += "_";
mode += QString::number(output->refreshRate());
outputCfg.writeEntry("Mode", mode);
qCDebug(KWIN_DRM) << " mode:" << mode;
outputCfg.writeEntry("Scale", output->scale());
outputCfg.writeEntry("Transform", transformToString(output->transform()));
}
outputRootCfg.sync();
checkOutputsIntersects(outputs);
}
}
bool DrmBackend::readOutputsConfiguration(const QVector<DrmAbstractOutput*> &outputs)
{
Q_ASSERT(!outputs.isEmpty());
const auto outputsInfo = KWinKScreenIntegration::outputsConfig(outputs);
const auto outputsKylinInfo = KWinKScreenIntegration::outputsKylinConfig(outputs);
const auto outputsInfo = outputsKylinInfo.isEmpty() ? KWinKScreenIntegration::outputsConfig(outputs) : outputsKylinInfo;
AbstractWaylandOutput *primaryOutput = outputs.constFirst();
WaylandOutputConfig cfg;
@ -687,4 +880,9 @@ bool DrmBackend::applyOutputChanges(const WaylandOutputConfig &config)
return true;
}
void DrmBackend::saveOutputsConfig()
{
KWinKScreenIntegration::writeOutputsKylinConfig(m_outputs, primaryOutput());
}
}

View File

@ -78,6 +78,7 @@ Q_SIGNALS:
protected:
bool applyOutputChanges(const WaylandOutputConfig &config) override;
void saveOutputsConfig() override;
private:
friend class DrmGpu;

View File

@ -198,7 +198,8 @@ QVector<AbstractWaylandOutput::Mode> DrmOutput::getModes() const
void DrmOutput::initOutputDevice()
{
const auto conn = m_pipeline->connector();
setName(conn->connectorName());
QString name = conn->connectorName() + QLatin1Char('-') + QString::number(conn->id());
setName(name);
initialize(conn->modelName(), conn->edid()->manufacturerString(),
conn->edid()->eisaId(), conn->edid()->serialNumber(),
conn->physicalSize(), getModes(), conn->edid()->raw());

View File

@ -141,6 +141,7 @@ void Platform::requestOutputsChange(KWaylandServer::OutputConfigurationV2Interfa
setPrimaryOutput(defaultPrimaryOutput);
}
}
saveOutputsConfig();
Q_EMIT screens()->changed();
config->setApplied();
} else {
@ -170,6 +171,10 @@ bool Platform::applyOutputChanges(const WaylandOutputConfig &config)
return true;
}
void Platform::saveOutputsConfig()
{
}
AbstractOutput *Platform::findOutput(int screenId) const
{
return enabledOutputs().value(screenId);

View File

@ -370,6 +370,11 @@ public:
*/
virtual bool applyOutputChanges(const WaylandOutputConfig &config);
/**
* save outputs configure
*/
virtual void saveOutputsConfig();
public Q_SLOTS:
void pointerMotion(const QPointF &position, quint32 time);
void pointerButtonPressed(quint32 button, quint32 time);