File indexing completed on 2024-05-12 17:02:07

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "output.h"
0011 #include "outputconfiguration.h"
0012 
0013 #include <KConfigGroup>
0014 #include <KLocalizedString>
0015 #include <KSharedConfig>
0016 
0017 namespace KWin
0018 {
0019 
0020 QDebug operator<<(QDebug debug, const Output *output)
0021 {
0022     QDebugStateSaver saver(debug);
0023     debug.nospace();
0024     if (output) {
0025         debug << output->metaObject()->className() << '(' << static_cast<const void *>(output);
0026         debug << ", name=" << output->name();
0027         debug << ", geometry=" << output->geometry();
0028         debug << ", scale=" << output->scale();
0029         if (debug.verbosity() > 2) {
0030             debug << ", manufacturer=" << output->manufacturer();
0031             debug << ", model=" << output->model();
0032             debug << ", serialNumber=" << output->serialNumber();
0033         }
0034         debug << ')';
0035     } else {
0036         debug << "Output(0x0)";
0037     }
0038     return debug;
0039 }
0040 
0041 OutputMode::OutputMode(const QSize &size, uint32_t refreshRate, Flags flags)
0042     : m_size(size)
0043     , m_refreshRate(refreshRate)
0044     , m_flags(flags)
0045 {
0046 }
0047 
0048 QSize OutputMode::size() const
0049 {
0050     return m_size;
0051 }
0052 
0053 uint32_t OutputMode::refreshRate() const
0054 {
0055     return m_refreshRate;
0056 }
0057 
0058 OutputMode::Flags OutputMode::flags() const
0059 {
0060     return m_flags;
0061 }
0062 
0063 Output::Output(QObject *parent)
0064     : QObject(parent)
0065 {
0066 }
0067 
0068 Output::~Output()
0069 {
0070 }
0071 
0072 void Output::ref()
0073 {
0074     m_refCount++;
0075 }
0076 
0077 void Output::unref()
0078 {
0079     Q_ASSERT(m_refCount > 0);
0080     m_refCount--;
0081     if (m_refCount == 0) {
0082         delete this;
0083     }
0084 }
0085 
0086 QString Output::name() const
0087 {
0088     return m_information.name;
0089 }
0090 
0091 QUuid Output::uuid() const
0092 {
0093     return m_uuid;
0094 }
0095 
0096 Output::Transform Output::transform() const
0097 {
0098     return m_state.transform;
0099 }
0100 
0101 QString Output::eisaId() const
0102 {
0103     return m_information.eisaId;
0104 }
0105 
0106 QString Output::manufacturer() const
0107 {
0108     return m_information.manufacturer;
0109 }
0110 
0111 QString Output::model() const
0112 {
0113     return m_information.model;
0114 }
0115 
0116 QString Output::serialNumber() const
0117 {
0118     return m_information.serialNumber;
0119 }
0120 
0121 bool Output::isInternal() const
0122 {
0123     return m_information.internal;
0124 }
0125 
0126 void Output::inhibitDirectScanout()
0127 {
0128     m_directScanoutCount++;
0129 }
0130 
0131 void Output::uninhibitDirectScanout()
0132 {
0133     m_directScanoutCount--;
0134 }
0135 
0136 bool Output::directScanoutInhibited() const
0137 {
0138     return m_directScanoutCount;
0139 }
0140 
0141 std::chrono::milliseconds Output::dimAnimationTime()
0142 {
0143     // See kscreen.kcfg
0144     return std::chrono::milliseconds(KSharedConfig::openConfig()->group("Effect-Kscreen").readEntry("Duration", 250));
0145 }
0146 
0147 QRect Output::mapFromGlobal(const QRect &rect) const
0148 {
0149     return rect.translated(-geometry().topLeft());
0150 }
0151 
0152 QRectF Output::mapFromGlobal(const QRectF &rect) const
0153 {
0154     return rect.translated(-geometry().topLeft());
0155 }
0156 
0157 QRectF Output::mapToGlobal(const QRectF &rect) const
0158 {
0159     return rect.translated(geometry().topLeft());
0160 }
0161 
0162 Output::Capabilities Output::capabilities() const
0163 {
0164     return m_information.capabilities;
0165 }
0166 
0167 qreal Output::scale() const
0168 {
0169     return m_state.scale;
0170 }
0171 
0172 QRect Output::geometry() const
0173 {
0174     return QRect(m_state.position, pixelSize() / scale());
0175 }
0176 
0177 QRectF Output::fractionalGeometry() const
0178 {
0179     return QRectF(m_state.position, QSizeF(pixelSize()) / scale());
0180 }
0181 
0182 QSize Output::physicalSize() const
0183 {
0184     return m_information.physicalSize;
0185 }
0186 
0187 int Output::refreshRate() const
0188 {
0189     return m_state.currentMode ? m_state.currentMode->refreshRate() : 0;
0190 }
0191 
0192 QSize Output::modeSize() const
0193 {
0194     return m_state.currentMode ? m_state.currentMode->size() : QSize();
0195 }
0196 
0197 QSize Output::pixelSize() const
0198 {
0199     return orientateSize(modeSize());
0200 }
0201 
0202 QByteArray Output::edid() const
0203 {
0204     return m_information.edid;
0205 }
0206 
0207 QList<std::shared_ptr<OutputMode>> Output::modes() const
0208 {
0209     return m_state.modes;
0210 }
0211 
0212 std::shared_ptr<OutputMode> Output::currentMode() const
0213 {
0214     return m_state.currentMode;
0215 }
0216 
0217 Output::SubPixel Output::subPixel() const
0218 {
0219     return m_information.subPixel;
0220 }
0221 
0222 void Output::applyChanges(const OutputConfiguration &config)
0223 {
0224     auto props = config.constChangeSet(this);
0225     Q_EMIT aboutToChange();
0226 
0227     State next = m_state;
0228     next.enabled = props->enabled;
0229     next.transform = props->transform;
0230     next.position = props->pos;
0231     next.scale = props->scale;
0232     next.rgbRange = props->rgbRange;
0233 
0234     setState(next);
0235     setVrrPolicy(props->vrrPolicy);
0236 
0237     Q_EMIT changed();
0238 }
0239 
0240 bool Output::isEnabled() const
0241 {
0242     return m_state.enabled;
0243 }
0244 
0245 QString Output::description() const
0246 {
0247     return manufacturer() + ' ' + model();
0248 }
0249 
0250 static QUuid generateOutputId(const QString &eisaId, const QString &model,
0251                               const QString &serialNumber, const QString &name)
0252 {
0253     static const QUuid urlNs = QUuid("6ba7b811-9dad-11d1-80b4-00c04fd430c8"); // NameSpace_URL
0254     static const QUuid kwinNs = QUuid::createUuidV5(urlNs, QStringLiteral("https://kwin.kde.org/o/"));
0255 
0256     const QString payload = QStringList{name, eisaId, model, serialNumber}.join(':');
0257     return QUuid::createUuidV5(kwinNs, payload);
0258 }
0259 
0260 void Output::setInformation(const Information &information)
0261 {
0262     m_information = information;
0263     m_uuid = generateOutputId(eisaId(), model(), serialNumber(), name());
0264 }
0265 
0266 void Output::setState(const State &state)
0267 {
0268     const QRect oldGeometry = geometry();
0269     const State oldState = m_state;
0270 
0271     m_state = state;
0272 
0273     if (oldGeometry != geometry()) {
0274         Q_EMIT geometryChanged();
0275     }
0276     if (oldState.scale != state.scale) {
0277         Q_EMIT scaleChanged();
0278     }
0279     if (oldState.modes != state.modes) {
0280         Q_EMIT modesChanged();
0281     }
0282     if (oldState.currentMode != state.currentMode) {
0283         Q_EMIT currentModeChanged();
0284     }
0285     if (oldState.transform != state.transform) {
0286         Q_EMIT transformChanged();
0287     }
0288     if (oldState.overscan != state.overscan) {
0289         Q_EMIT overscanChanged();
0290     }
0291     if (oldState.dpmsMode != state.dpmsMode) {
0292         Q_EMIT dpmsModeChanged();
0293     }
0294     if (oldState.rgbRange != state.rgbRange) {
0295         Q_EMIT rgbRangeChanged();
0296     }
0297     if (oldState.enabled != state.enabled) {
0298         Q_EMIT enabledChanged();
0299     }
0300 }
0301 
0302 QSize Output::orientateSize(const QSize &size) const
0303 {
0304     switch (m_state.transform) {
0305     case Transform::Rotated90:
0306     case Transform::Rotated270:
0307     case Transform::Flipped90:
0308     case Transform::Flipped270:
0309         return size.transposed();
0310     default:
0311         return size;
0312     }
0313 }
0314 
0315 void Output::setDpmsMode(DpmsMode mode)
0316 {
0317 }
0318 
0319 Output::DpmsMode Output::dpmsMode() const
0320 {
0321     return m_state.dpmsMode;
0322 }
0323 
0324 QMatrix4x4 Output::logicalToNativeMatrix(const QRect &rect, qreal scale, Transform transform)
0325 {
0326     QMatrix4x4 matrix;
0327     matrix.scale(scale);
0328 
0329     switch (transform) {
0330     case Transform::Normal:
0331     case Transform::Flipped:
0332         break;
0333     case Transform::Rotated90:
0334     case Transform::Flipped90:
0335         matrix.translate(0, rect.width());
0336         matrix.rotate(-90, 0, 0, 1);
0337         break;
0338     case Transform::Rotated180:
0339     case Transform::Flipped180:
0340         matrix.translate(rect.width(), rect.height());
0341         matrix.rotate(-180, 0, 0, 1);
0342         break;
0343     case Transform::Rotated270:
0344     case Transform::Flipped270:
0345         matrix.translate(rect.height(), 0);
0346         matrix.rotate(-270, 0, 0, 1);
0347         break;
0348     }
0349 
0350     switch (transform) {
0351     case Transform::Flipped:
0352     case Transform::Flipped90:
0353     case Transform::Flipped180:
0354     case Transform::Flipped270:
0355         matrix.translate(rect.width(), 0);
0356         matrix.scale(-1, 1);
0357         break;
0358     default:
0359         break;
0360     }
0361 
0362     matrix.translate(-rect.x(), -rect.y());
0363 
0364     return matrix;
0365 }
0366 
0367 uint32_t Output::overscan() const
0368 {
0369     return m_state.overscan;
0370 }
0371 
0372 void Output::setVrrPolicy(RenderLoop::VrrPolicy policy)
0373 {
0374     if (renderLoop()->vrrPolicy() != policy && (capabilities() & Capability::Vrr)) {
0375         renderLoop()->setVrrPolicy(policy);
0376         Q_EMIT vrrPolicyChanged();
0377     }
0378 }
0379 
0380 RenderLoop::VrrPolicy Output::vrrPolicy() const
0381 {
0382     return renderLoop()->vrrPolicy();
0383 }
0384 
0385 bool Output::isPlaceholder() const
0386 {
0387     return m_information.placeholder;
0388 }
0389 
0390 bool Output::isNonDesktop() const
0391 {
0392     return m_information.nonDesktop;
0393 }
0394 
0395 Output::RgbRange Output::rgbRange() const
0396 {
0397     return m_state.rgbRange;
0398 }
0399 
0400 bool Output::setGammaRamp(const std::shared_ptr<ColorTransformation> &transformation)
0401 {
0402     return false;
0403 }
0404 
0405 bool Output::setCTM(const QMatrix3x3 &ctm)
0406 {
0407     return false;
0408 }
0409 
0410 ContentType Output::contentType() const
0411 {
0412     return m_contentType;
0413 }
0414 
0415 void Output::setContentType(ContentType contentType)
0416 {
0417     m_contentType = contentType;
0418 }
0419 
0420 Output::Transform Output::panelOrientation() const
0421 {
0422     return m_information.panelOrientation;
0423 }
0424 
0425 bool Output::setCursor(CursorSource *source)
0426 {
0427     return false;
0428 }
0429 
0430 bool Output::moveCursor(const QPoint &position)
0431 {
0432     return false;
0433 }
0434 
0435 } // namespace KWin