File indexing completed on 2025-03-23 11:13:32
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