mirror of https://gitee.com/openkylin/kwin.git
drm config: auto load and save
Signed-off-by: Hongfei Shang <shanghongfei@kylinos.cn>
This commit is contained in:
parent
71b3e39e18
commit
41db6a7a48
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ Q_SIGNALS:
|
|||
|
||||
protected:
|
||||
bool applyOutputChanges(const WaylandOutputConfig &config) override;
|
||||
void saveOutputsConfig() override;
|
||||
|
||||
private:
|
||||
friend class DrmGpu;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue