You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
4.1 KiB
149 lines
4.1 KiB
/* |
|
SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org> |
|
|
|
SPDX-License-Identifier: LGPL-2.0-or-later |
|
*/ |
|
|
|
#include "screenpool.h" |
|
|
|
#include <KWindowSystem> |
|
#include <QGuiApplication> |
|
#include <QScreen> |
|
|
|
ScreenPool::ScreenPool(const KSharedConfig::Ptr &config, QObject *parent) |
|
: QObject(parent) |
|
, m_configGroup(KConfigGroup(config, QStringLiteral("ScreenConnectors"))) |
|
{ |
|
m_configSaveTimer.setSingleShot(true); |
|
connect(&m_configSaveTimer, &QTimer::timeout, this, [this]() { |
|
m_configGroup.sync(); |
|
}); |
|
} |
|
|
|
void ScreenPool::load(QScreen *primary) |
|
{ |
|
m_primaryConnector = QString(); |
|
m_connectorForId.clear(); |
|
m_idForConnector.clear(); |
|
|
|
if (primary) { |
|
m_primaryConnector = primary->name(); |
|
if (!m_primaryConnector.isEmpty()) { |
|
m_connectorForId[0] = m_primaryConnector; |
|
m_idForConnector[m_primaryConnector] = 0; |
|
} |
|
} |
|
|
|
// restore the known ids to connector mappings |
|
const auto keys = m_configGroup.keyList(); |
|
for (const QString &key : keys) { |
|
QString connector = m_configGroup.readEntry(key, QString()); |
|
const int currentId = key.toInt(); |
|
if (!key.isEmpty() && !connector.isEmpty() && !m_connectorForId.contains(currentId) && !m_idForConnector.contains(connector)) { |
|
m_connectorForId[currentId] = connector; |
|
m_idForConnector[connector] = currentId; |
|
} else if (m_idForConnector.value(connector) != currentId) { |
|
m_configGroup.deleteEntry(key); |
|
} |
|
} |
|
|
|
// if there are already connected unknown screens, map those |
|
// all needs to be populated as soon as possible, otherwise |
|
// containment->screen() will return an incorrect -1 |
|
// at startup, if it' asked before corona::addOutput() |
|
// is performed, driving to the creation of a new containment |
|
for (QScreen *screen : qGuiApp->screens()) { |
|
if (!m_idForConnector.contains(screen->name())) { |
|
insertScreenMapping(firstAvailableId(), screen->name()); |
|
} |
|
} |
|
} |
|
|
|
ScreenPool::~ScreenPool() |
|
{ |
|
m_configGroup.sync(); |
|
} |
|
|
|
QString ScreenPool::primaryConnector() const |
|
{ |
|
return m_primaryConnector; |
|
} |
|
|
|
void ScreenPool::setPrimaryConnector(const QString &primary) |
|
{ |
|
if (m_primaryConnector == primary) { |
|
return; |
|
} |
|
|
|
int oldIdForPrimary = m_idForConnector.value(primary, -1); |
|
if (oldIdForPrimary == -1) { |
|
// move old primary to new free id |
|
oldIdForPrimary = firstAvailableId(); |
|
insertScreenMapping(oldIdForPrimary, m_primaryConnector); |
|
} |
|
|
|
m_idForConnector[primary] = 0; |
|
m_connectorForId[0] = primary; |
|
m_idForConnector[m_primaryConnector] = oldIdForPrimary; |
|
m_connectorForId[oldIdForPrimary] = m_primaryConnector; |
|
m_primaryConnector = primary; |
|
save(); |
|
} |
|
|
|
void ScreenPool::save() |
|
{ |
|
QMap<int, QString>::const_iterator i; |
|
for (i = m_connectorForId.constBegin(); i != m_connectorForId.constEnd(); ++i) { |
|
m_configGroup.writeEntry(QString::number(i.key()), i.value()); |
|
} |
|
// write to disck every 30 seconds at most |
|
m_configSaveTimer.start(30000); |
|
} |
|
|
|
void ScreenPool::insertScreenMapping(int id, const QString &connector) |
|
{ |
|
Q_ASSERT(!m_connectorForId.contains(id) || m_connectorForId.value(id) == connector); |
|
Q_ASSERT(!m_idForConnector.contains(connector) || m_idForConnector.value(connector) == id); |
|
|
|
if (id == 0) { |
|
m_primaryConnector = connector; |
|
} |
|
|
|
m_connectorForId[id] = connector; |
|
m_idForConnector[connector] = id; |
|
save(); |
|
} |
|
|
|
int ScreenPool::id(const QString &connector) const |
|
{ |
|
return m_idForConnector.value(connector, -1); |
|
} |
|
|
|
QString ScreenPool::connector(int id) const |
|
{ |
|
Q_ASSERT(m_connectorForId.contains(id)); |
|
|
|
return m_connectorForId.value(id); |
|
} |
|
|
|
int ScreenPool::firstAvailableId() const |
|
{ |
|
int i = 0; |
|
// find the first integer not stored in m_connectorForId |
|
// m_connectorForId is the only map, so the ids are sorted |
|
foreach (int existingId, m_connectorForId.keys()) { |
|
if (i != existingId) { |
|
return i; |
|
} |
|
++i; |
|
} |
|
|
|
return i; |
|
} |
|
|
|
QList<int> ScreenPool::knownIds() const |
|
{ |
|
return m_connectorForId.keys(); |
|
} |
|
|
|
#include "moc_screenpool.cpp"
|
|
|