File indexing completed on 2024-04-28 16:49:41

0001 /*
0002  *  SPDX-FileCopyrightText: 2014 Sebastian Kügler <sebas@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.1-or-later
0005  */
0006 
0007 #include "qscreenconfig.h"
0008 #include "qscreenbackend.h"
0009 #include "qscreenoutput.h"
0010 #include "qscreenscreen.h"
0011 
0012 #include <config.h>
0013 #include <mode.h>
0014 #include <output.h>
0015 
0016 #include <QGuiApplication>
0017 #include <QRect>
0018 
0019 #include <utility>
0020 
0021 using namespace KScreen;
0022 
0023 QScreenConfig::QScreenConfig(QObject *parent)
0024     : QObject(parent)
0025     , m_screen(new QScreenScreen(this))
0026     , m_blockSignals(true)
0027 {
0028     for (const QScreen *qscreen : QGuiApplication::screens()) {
0029         screenAdded(qscreen);
0030     }
0031     m_blockSignals = false;
0032     connect(qApp, &QGuiApplication::screenAdded, this, &QScreenConfig::screenAdded);
0033     connect(qApp, &QGuiApplication::screenRemoved, this, &QScreenConfig::screenRemoved);
0034 }
0035 
0036 QScreenConfig::~QScreenConfig()
0037 {
0038     qDeleteAll(m_outputMap);
0039 }
0040 
0041 ConfigPtr QScreenConfig::toKScreenConfig() const
0042 {
0043     ConfigPtr config(new Config);
0044     config->setScreen(m_screen->toKScreenScreen());
0045     updateKScreenConfig(config);
0046     return config;
0047 }
0048 
0049 int QScreenConfig::outputId(const QScreen *qscreen)
0050 {
0051     for (auto output : std::as_const(m_outputMap)) {
0052         if (qscreen == output->qscreen()) {
0053             return output->id();
0054         }
0055     }
0056     m_lastOutputId++;
0057     return m_lastOutputId;
0058 }
0059 
0060 void QScreenConfig::screenAdded(const QScreen *qscreen)
0061 {
0062     qCDebug(KSCREEN_QSCREEN) << "Screen added" << qscreen << qscreen->name();
0063     QScreenOutput *qscreenoutput = new QScreenOutput(qscreen, this);
0064     qscreenoutput->setId(outputId(qscreen));
0065     m_outputMap.insert(qscreenoutput->id(), qscreenoutput);
0066 
0067     if (!m_blockSignals) {
0068         Q_EMIT configChanged(toKScreenConfig());
0069     }
0070 }
0071 
0072 void QScreenConfig::screenRemoved(QScreen *qscreen)
0073 {
0074     qCDebug(KSCREEN_QSCREEN) << "Screen removed" << qscreen << QGuiApplication::screens().count();
0075     // Find output matching the QScreen object and remove it
0076     int removedOutputId = -1;
0077     for (auto output : m_outputMap) {
0078         if (output->qscreen() == qscreen) {
0079             removedOutputId = output->id();
0080             m_outputMap.remove(removedOutputId);
0081             delete output;
0082         }
0083     }
0084     Q_EMIT configChanged(toKScreenConfig());
0085 }
0086 
0087 void QScreenConfig::updateKScreenConfig(ConfigPtr &config) const
0088 {
0089     KScreen::ScreenPtr screen = config->screen();
0090     m_screen->updateKScreenScreen(screen);
0091     config->setScreen(screen);
0092 
0093     // Removing removed outputs
0094     KScreen::OutputList outputs = config->outputs();
0095     for (const KScreen::OutputPtr &output : outputs) {
0096         if (!m_outputMap.contains(output->id())) {
0097             config->removeOutput(output->id());
0098         }
0099     }
0100 
0101     // Add KScreen::Outputs that aren't in the list yet, handle primaryOutput
0102     for (QScreenOutput *output : m_outputMap) {
0103         KScreen::OutputPtr kscreenOutput;
0104         if (config->outputs().contains(output->id())) {
0105             kscreenOutput = config->outputs()[output->id()];
0106             output->updateKScreenOutput(kscreenOutput);
0107         } else {
0108             kscreenOutput = output->toKScreenOutput();
0109             config->addOutput(kscreenOutput);
0110         }
0111         if (QGuiApplication::primaryScreen() == output->qscreen()) {
0112             config->setPrimaryOutput(kscreenOutput);
0113         }
0114     }
0115 }
0116 
0117 QMap<int, QScreenOutput *> QScreenConfig::outputMap() const
0118 {
0119     return m_outputMap;
0120 }