File indexing completed on 2024-05-05 17:39:43
0001 /* 0002 * SPDX-FileCopyrightText: 2014-2015 Sebastian Kügler <sebas@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "waylandtestserver.h" 0008 0009 #include "waylandconfigreader.h" 0010 0011 #include <QFile> 0012 #include <QJsonArray> 0013 #include <QJsonDocument> 0014 #include <QJsonObject> 0015 #include <QLoggingCategory> 0016 #include <QStandardPaths> 0017 0018 #include <utility> 0019 0020 #include "../src/edid.h" 0021 0022 Q_LOGGING_CATEGORY(KSCREEN_WAYLAND_TESTSERVER, "kscreen.kwayland.testserver") 0023 0024 using namespace KScreen; 0025 using namespace KWayland::Server; 0026 0027 WaylandTestServer::WaylandTestServer(QObject *parent) 0028 : QObject(parent) 0029 , m_configFile(QLatin1String(TEST_DATA) + QLatin1String("default.json")) 0030 , m_display(nullptr) 0031 , m_outputManagement(nullptr) 0032 , m_dpmsManager(nullptr) 0033 , m_suspendChanges(false) 0034 , m_waiting(nullptr) 0035 { 0036 } 0037 0038 WaylandTestServer::~WaylandTestServer() 0039 { 0040 stop(); 0041 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "Wayland server shut down."; 0042 } 0043 0044 void WaylandTestServer::start() 0045 { 0046 using namespace KWayland::Server; 0047 delete m_display; 0048 m_display = new KWayland::Server::Display(this); 0049 if (qgetenv("WAYLAND_DISPLAY").isEmpty()) { 0050 m_display->setSocketName(s_socketName); 0051 } else { 0052 m_display->setSocketName(QString::fromLatin1(qgetenv("WAYLAND_DISPLAY"))); 0053 } 0054 m_display->start(); 0055 0056 auto manager = m_display->createDpmsManager(); 0057 manager->create(); 0058 0059 m_outputManagement = m_display->createOutputManagement(); 0060 m_outputManagement->create(); 0061 connect(m_outputManagement, &OutputManagementInterface::configurationChangeRequested, this, &WaylandTestServer::configurationChangeRequested); 0062 0063 KScreen::WaylandConfigReader::outputsFromConfig(m_configFile, m_display, m_outputs); 0064 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << QStringLiteral("export WAYLAND_DISPLAY=") + m_display->socketName(); 0065 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << QStringLiteral("You can specify the WAYLAND_DISPLAY for this server by exporting it in the environment"); 0066 // showOutputs(); 0067 } 0068 0069 void WaylandTestServer::stop() 0070 { 0071 qDeleteAll(m_outputs); 0072 m_outputs.clear(); 0073 // actually stop the Wayland server 0074 delete m_display; 0075 m_display = nullptr; 0076 } 0077 0078 KWayland::Server::Display *WaylandTestServer::display() 0079 { 0080 return m_display; 0081 } 0082 0083 void WaylandTestServer::setConfig(const QString &configfile) 0084 { 0085 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "Creating Wayland server from " << configfile; 0086 m_configFile = configfile; 0087 } 0088 0089 int WaylandTestServer::outputCount() const 0090 { 0091 return m_outputs.count(); 0092 } 0093 QList<KWayland::Server::OutputDeviceInterface *> WaylandTestServer::outputs() const 0094 { 0095 return m_outputs; 0096 } 0097 0098 void WaylandTestServer::suspendChanges(bool suspend) 0099 { 0100 if (m_suspendChanges == suspend) { 0101 return; 0102 } 0103 m_suspendChanges = suspend; 0104 if (!suspend && m_waiting) { 0105 m_waiting->setApplied(); 0106 m_waiting = nullptr; 0107 Q_EMIT configChanged(); 0108 } 0109 } 0110 0111 void WaylandTestServer::configurationChangeRequested(KWayland::Server::OutputConfigurationInterface *configurationInterface) 0112 { 0113 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "Server received change request, changes:" << configurationInterface->changes().count(); 0114 Q_EMIT configReceived(); 0115 0116 auto changes = configurationInterface->changes(); 0117 for (auto it = changes.constBegin(); it != changes.constEnd(); ++it) { 0118 auto outputdevice = it.key(); 0119 auto c = it.value(); 0120 if (c->enabledChanged()) { 0121 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "Setting enabled:"; 0122 outputdevice->setEnabled(c->enabled()); 0123 } 0124 if (c->modeChanged()) { 0125 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "Setting new mode:" << c->mode() << modeString(outputdevice, c->mode()); 0126 outputdevice->setCurrentMode(c->mode()); 0127 } 0128 if (c->transformChanged()) { 0129 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "Server setting transform: " << (int)(c->transform()); 0130 outputdevice->setTransform(c->transform()); 0131 } 0132 if (c->positionChanged()) { 0133 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "Server setting position: " << c->position(); 0134 outputdevice->setGlobalPosition(c->position()); 0135 } 0136 if (c->scaleChanged()) { 0137 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "Setting scale:" << c->scaleF(); 0138 outputdevice->setScaleF(c->scaleF()); 0139 } 0140 } 0141 0142 if (m_suspendChanges) { 0143 Q_ASSERT(!m_waiting); 0144 m_waiting = configurationInterface; 0145 return; 0146 } 0147 0148 configurationInterface->setApplied(); 0149 // showOutputs(); 0150 Q_EMIT configChanged(); 0151 } 0152 0153 void WaylandTestServer::showOutputs() 0154 { 0155 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "******** Wayland server running: " << m_outputs.count() << " outputs. ********"; 0156 for (const auto &o : std::as_const(m_outputs)) { 0157 bool enabled = (o->enabled() == KWayland::Server::OutputDeviceInterface::Enablement::Enabled); 0158 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << " * Output id: " << o->uuid(); 0159 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << " Enabled: " << (enabled ? "enabled" : "disabled"); 0160 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << " Name: " << QStringLiteral("%2-%3").arg(o->manufacturer(), o->model()); 0161 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << " Mode: " << modeString(o, o->currentModeId()); 0162 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << " Pos: " << o->globalPosition(); 0163 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << " Edid: " << o->edid(); 0164 // << o->currentMode().size(); 0165 } 0166 qCDebug(KSCREEN_WAYLAND_TESTSERVER) << "******************************************************"; 0167 } 0168 0169 QString WaylandTestServer::modeString(KWayland::Server::OutputDeviceInterface *outputdevice, int mid) 0170 { 0171 QString s; 0172 QString ids; 0173 int _i = 0; 0174 for (const auto &_m : outputdevice->modes()) { 0175 _i++; 0176 if (_i < 6) { 0177 ids.append(QString::number(_m.id) + QLatin1String(", ")); 0178 } else { 0179 ids.append(QLatin1Char('.')); 0180 } 0181 if (_m.id == mid) { 0182 s = QStringLiteral("%1x%2 @%3").arg(QString::number(_m.size.width()), QString::number(_m.size.height()), QString::number(_m.refreshRate)); 0183 } 0184 } 0185 return QStringLiteral("[%1] %2 (%4 modes: %3)").arg(QString::number(mid), s, ids, QString::number(outputdevice->modes().count())); 0186 }