File indexing completed on 2024-05-19 05:32:37

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003     SPDX-FileCopyrightText: 2021 Méven Car <meven.car@enioka.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 #include "outputdevice_v2.h"
0008 
0009 #include "display.h"
0010 #include "display_p.h"
0011 #include "utils/common.h"
0012 #include "utils/resource.h"
0013 
0014 #include "core/output.h"
0015 
0016 #include <QDebug>
0017 #include <QPointer>
0018 #include <QString>
0019 
0020 #include "qwayland-server-kde-output-device-v2.h"
0021 
0022 namespace KWin
0023 {
0024 
0025 static const quint32 s_version = 6;
0026 
0027 static QtWaylandServer::kde_output_device_v2::transform kwinTransformToOutputDeviceTransform(OutputTransform transform)
0028 {
0029     return static_cast<QtWaylandServer::kde_output_device_v2::transform>(transform.kind());
0030 }
0031 
0032 static QtWaylandServer::kde_output_device_v2::subpixel kwinSubPixelToOutputDeviceSubPixel(Output::SubPixel subPixel)
0033 {
0034     return static_cast<QtWaylandServer::kde_output_device_v2::subpixel>(subPixel);
0035 }
0036 
0037 static uint32_t kwinCapabilitiesToOutputDeviceCapabilities(Output::Capabilities caps)
0038 {
0039     uint32_t ret = 0;
0040     if (caps & Output::Capability::Overscan) {
0041         ret |= QtWaylandServer::kde_output_device_v2::capability_overscan;
0042     }
0043     if (caps & Output::Capability::Vrr) {
0044         ret |= QtWaylandServer::kde_output_device_v2::capability_vrr;
0045     }
0046     if (caps & Output::Capability::RgbRange) {
0047         ret |= QtWaylandServer::kde_output_device_v2::capability_rgb_range;
0048     }
0049     if (caps & Output::Capability::HighDynamicRange) {
0050         ret |= QtWaylandServer::kde_output_device_v2::capability_high_dynamic_range;
0051     }
0052     if (caps & Output::Capability::WideColorGamut) {
0053         ret |= QtWaylandServer::kde_output_device_v2::capability_wide_color_gamut;
0054     }
0055     if (caps & Output::Capability::AutoRotation) {
0056         ret |= QtWaylandServer::kde_output_device_v2::capability_auto_rotate;
0057     }
0058     if (caps & Output::Capability::IccProfile) {
0059         ret |= QtWaylandServer::kde_output_device_v2::capability_icc_profile;
0060     }
0061     return ret;
0062 }
0063 
0064 static QtWaylandServer::kde_output_device_v2::vrr_policy kwinVrrPolicyToOutputDeviceVrrPolicy(VrrPolicy policy)
0065 {
0066     return static_cast<QtWaylandServer::kde_output_device_v2::vrr_policy>(policy);
0067 }
0068 
0069 static QtWaylandServer::kde_output_device_v2::rgb_range kwinRgbRangeToOutputDeviceRgbRange(Output::RgbRange range)
0070 {
0071     return static_cast<QtWaylandServer::kde_output_device_v2::rgb_range>(range);
0072 }
0073 
0074 static QtWaylandServer::kde_output_device_v2::auto_rotate_policy kwinAutoRotationToOutputDeviceAutoRotation(Output::AutoRotationPolicy policy)
0075 {
0076     return static_cast<QtWaylandServer::kde_output_device_v2::auto_rotate_policy>(policy);
0077 }
0078 
0079 class OutputDeviceV2InterfacePrivate : public QtWaylandServer::kde_output_device_v2
0080 {
0081 public:
0082     OutputDeviceV2InterfacePrivate(OutputDeviceV2Interface *q, Display *display, Output *handle);
0083     ~OutputDeviceV2InterfacePrivate() override;
0084 
0085     void sendGeometry(Resource *resource);
0086     wl_resource *sendNewMode(Resource *resource, OutputDeviceModeV2Interface *mode);
0087     void sendCurrentMode(Resource *resource);
0088     void sendDone(Resource *resource);
0089     void sendUuid(Resource *resource);
0090     void sendEdid(Resource *resource);
0091     void sendEnabled(Resource *resource);
0092     void sendScale(Resource *resource);
0093     void sendEisaId(Resource *resource);
0094     void sendName(Resource *resource);
0095     void sendSerialNumber(Resource *resource);
0096     void sendCapabilities(Resource *resource);
0097     void sendOverscan(Resource *resource);
0098     void sendVrrPolicy(Resource *resource);
0099     void sendRgbRange(Resource *resource);
0100     void sendHighDynamicRange(Resource *resource);
0101     void sendSdrBrightness(Resource *resource);
0102     void sendWideColorGamut(Resource *resource);
0103     void sendAutoRotationPolicy(Resource *resource);
0104     void sendIccProfilePath(Resource *resource);
0105     void sendBrightnessMetadata(Resource *resource);
0106     void sendBrightnessOverrides(Resource *resource);
0107     void sendSdrGamutWideness(Resource *resource);
0108 
0109     OutputDeviceV2Interface *q;
0110     QPointer<Display> m_display;
0111     Output *m_handle;
0112     QSize m_physicalSize;
0113     QPoint m_globalPosition;
0114     QString m_manufacturer = QStringLiteral("org.kde.kwin");
0115     QString m_model = QStringLiteral("none");
0116     qreal m_scale = 1.0;
0117     QString m_serialNumber;
0118     QString m_eisaId;
0119     QString m_name;
0120     subpixel m_subPixel = subpixel_unknown;
0121     transform m_transform = transform_normal;
0122     QList<OutputDeviceModeV2Interface *> m_modes;
0123     OutputDeviceModeV2Interface *m_currentMode = nullptr;
0124     QByteArray m_edid;
0125     bool m_enabled = true;
0126     QUuid m_uuid;
0127     uint32_t m_capabilities = 0;
0128     uint32_t m_overscan = 0;
0129     vrr_policy m_vrrPolicy = vrr_policy_automatic;
0130     rgb_range m_rgbRange = rgb_range_automatic;
0131     bool m_highDynamicRange = false;
0132     uint32_t m_sdrBrightness = 200;
0133     bool m_wideColorGamut = false;
0134     auto_rotate_policy m_autoRotation = auto_rotate_policy::auto_rotate_policy_in_tablet_mode;
0135     QString m_iccProfilePath;
0136     std::optional<double> m_maxPeakBrightness;
0137     std::optional<double> m_maxAverageBrightness;
0138     double m_minBrightness = 0;
0139     double m_sdrGamutWideness = 0;
0140     std::optional<double> m_maxPeakBrightnessOverride;
0141     std::optional<double> m_maxAverageBrightnessOverride;
0142     std::optional<double> m_minBrightnessOverride;
0143 
0144 protected:
0145     void kde_output_device_v2_bind_resource(Resource *resource) override;
0146     void kde_output_device_v2_destroy_global() override;
0147 };
0148 
0149 class OutputDeviceModeV2InterfacePrivate : public QtWaylandServer::kde_output_device_mode_v2
0150 {
0151 public:
0152     struct ModeResource : Resource
0153     {
0154         OutputDeviceV2InterfacePrivate::Resource *output;
0155     };
0156 
0157     OutputDeviceModeV2InterfacePrivate(OutputDeviceModeV2Interface *q, std::shared_ptr<OutputMode> handle);
0158     ~OutputDeviceModeV2InterfacePrivate() override;
0159 
0160     Resource *createResource(OutputDeviceV2InterfacePrivate::Resource *output);
0161     Resource *findResource(OutputDeviceV2InterfacePrivate::Resource *output) const;
0162 
0163     void bindResource(wl_resource *resource);
0164 
0165     static OutputDeviceModeV2InterfacePrivate *get(OutputDeviceModeV2Interface *mode)
0166     {
0167         return mode->d.get();
0168     }
0169 
0170     OutputDeviceModeV2Interface *q;
0171     std::weak_ptr<OutputMode> m_handle;
0172     QSize m_size;
0173     int m_refreshRate = 60000;
0174     bool m_preferred = false;
0175 
0176 protected:
0177     Resource *kde_output_device_mode_v2_allocate() override;
0178 };
0179 
0180 OutputDeviceV2InterfacePrivate::OutputDeviceV2InterfacePrivate(OutputDeviceV2Interface *q, Display *display, Output *handle)
0181     : QtWaylandServer::kde_output_device_v2(*display, s_version)
0182     , q(q)
0183     , m_display(display)
0184     , m_handle(handle)
0185 {
0186     DisplayPrivate *displayPrivate = DisplayPrivate::get(display);
0187     displayPrivate->outputdevicesV2.append(q);
0188 }
0189 
0190 OutputDeviceV2InterfacePrivate::~OutputDeviceV2InterfacePrivate()
0191 {
0192     if (m_display) {
0193         DisplayPrivate *displayPrivate = DisplayPrivate::get(m_display);
0194         displayPrivate->outputdevicesV2.removeOne(q);
0195     }
0196 }
0197 
0198 OutputDeviceV2Interface::OutputDeviceV2Interface(Display *display, Output *handle, QObject *parent)
0199     : QObject(parent)
0200     , d(new OutputDeviceV2InterfacePrivate(this, display, handle))
0201 {
0202     updateEnabled();
0203     updateManufacturer();
0204     updateEdid();
0205     updateUuid();
0206     updateModel();
0207     updatePhysicalSize();
0208     updateGlobalPosition();
0209     updateScale();
0210     updateTransform();
0211     updateEisaId();
0212     updateSerialNumber();
0213     updateSubPixel();
0214     updateOverscan();
0215     updateCapabilities();
0216     updateVrrPolicy();
0217     updateRgbRange();
0218     updateName();
0219     updateModes();
0220     updateHighDynamicRange();
0221     updateSdrBrightness();
0222     updateWideColorGamut();
0223     updateAutoRotate();
0224     updateIccProfilePath();
0225     updateBrightnessMetadata();
0226     updateBrightnessOverrides();
0227     updateSdrGamutWideness();
0228 
0229     connect(handle, &Output::geometryChanged,
0230             this, &OutputDeviceV2Interface::updateGlobalPosition);
0231     connect(handle, &Output::scaleChanged,
0232             this, &OutputDeviceV2Interface::updateScale);
0233     connect(handle, &Output::enabledChanged,
0234             this, &OutputDeviceV2Interface::updateEnabled);
0235     connect(handle, &Output::transformChanged,
0236             this, &OutputDeviceV2Interface::updateTransform);
0237     connect(handle, &Output::currentModeChanged,
0238             this, &OutputDeviceV2Interface::updateCurrentMode);
0239     connect(handle, &Output::capabilitiesChanged,
0240             this, &OutputDeviceV2Interface::updateCapabilities);
0241     connect(handle, &Output::overscanChanged,
0242             this, &OutputDeviceV2Interface::updateOverscan);
0243     connect(handle, &Output::vrrPolicyChanged,
0244             this, &OutputDeviceV2Interface::updateVrrPolicy);
0245     connect(handle, &Output::modesChanged,
0246             this, &OutputDeviceV2Interface::updateModes);
0247     connect(handle, &Output::rgbRangeChanged,
0248             this, &OutputDeviceV2Interface::updateRgbRange);
0249     connect(handle, &Output::highDynamicRangeChanged, this, &OutputDeviceV2Interface::updateHighDynamicRange);
0250     connect(handle, &Output::sdrBrightnessChanged, this, &OutputDeviceV2Interface::updateSdrBrightness);
0251     connect(handle, &Output::wideColorGamutChanged, this, &OutputDeviceV2Interface::updateWideColorGamut);
0252     connect(handle, &Output::autoRotationPolicyChanged, this, &OutputDeviceV2Interface::updateAutoRotate);
0253     connect(handle, &Output::iccProfileChanged, this, &OutputDeviceV2Interface::updateIccProfilePath);
0254     connect(handle, &Output::brightnessMetadataChanged, this, &OutputDeviceV2Interface::updateBrightnessMetadata);
0255     connect(handle, &Output::brightnessMetadataChanged, this, &OutputDeviceV2Interface::updateBrightnessOverrides);
0256     connect(handle, &Output::sdrGamutWidenessChanged, this, &OutputDeviceV2Interface::updateSdrGamutWideness);
0257 }
0258 
0259 OutputDeviceV2Interface::~OutputDeviceV2Interface()
0260 {
0261     d->globalRemove();
0262 }
0263 
0264 void OutputDeviceV2Interface::remove()
0265 {
0266     if (d->isGlobalRemoved()) {
0267         return;
0268     }
0269 
0270     if (d->m_display) {
0271         DisplayPrivate *displayPrivate = DisplayPrivate::get(d->m_display);
0272         displayPrivate->outputdevicesV2.removeOne(this);
0273     }
0274 
0275     d->globalRemove();
0276 }
0277 
0278 Output *OutputDeviceV2Interface::handle() const
0279 {
0280     return d->m_handle;
0281 }
0282 
0283 void OutputDeviceV2InterfacePrivate::kde_output_device_v2_destroy_global()
0284 {
0285     delete q;
0286 }
0287 
0288 void OutputDeviceV2InterfacePrivate::kde_output_device_v2_bind_resource(Resource *resource)
0289 {
0290     sendGeometry(resource);
0291     sendScale(resource);
0292     sendEisaId(resource);
0293     sendName(resource);
0294     sendSerialNumber(resource);
0295 
0296     for (OutputDeviceModeV2Interface *mode : std::as_const(m_modes)) {
0297         sendNewMode(resource, mode);
0298     }
0299     sendCurrentMode(resource);
0300     sendUuid(resource);
0301     sendEdid(resource);
0302     sendEnabled(resource);
0303     sendCapabilities(resource);
0304     sendOverscan(resource);
0305     sendVrrPolicy(resource);
0306     sendRgbRange(resource);
0307     sendHighDynamicRange(resource);
0308     sendSdrBrightness(resource);
0309     sendWideColorGamut(resource);
0310     sendAutoRotationPolicy(resource);
0311     sendIccProfilePath(resource);
0312     sendBrightnessMetadata(resource);
0313     sendBrightnessOverrides(resource);
0314     sendSdrGamutWideness(resource);
0315     sendDone(resource);
0316 }
0317 
0318 wl_resource *OutputDeviceV2InterfacePrivate::sendNewMode(Resource *resource, OutputDeviceModeV2Interface *mode)
0319 {
0320     auto privateMode = OutputDeviceModeV2InterfacePrivate::get(mode);
0321     // bind mode to client
0322     const auto modeResource = privateMode->createResource(resource);
0323 
0324     send_mode(resource->handle, modeResource->handle);
0325 
0326     privateMode->bindResource(modeResource->handle);
0327 
0328     return modeResource->handle;
0329 }
0330 
0331 void OutputDeviceV2InterfacePrivate::sendCurrentMode(Resource *outputResource)
0332 {
0333     const auto modeResource = OutputDeviceModeV2InterfacePrivate::get(m_currentMode)->findResource(outputResource);
0334     send_current_mode(outputResource->handle, modeResource->handle);
0335 }
0336 
0337 void OutputDeviceV2InterfacePrivate::sendGeometry(Resource *resource)
0338 {
0339     send_geometry(resource->handle,
0340                   m_globalPosition.x(),
0341                   m_globalPosition.y(),
0342                   m_physicalSize.width(),
0343                   m_physicalSize.height(),
0344                   m_subPixel,
0345                   m_manufacturer,
0346                   m_model,
0347                   m_transform);
0348 }
0349 
0350 void OutputDeviceV2InterfacePrivate::sendScale(Resource *resource)
0351 {
0352     send_scale(resource->handle, wl_fixed_from_double(m_scale));
0353 }
0354 
0355 void OutputDeviceV2InterfacePrivate::sendSerialNumber(Resource *resource)
0356 {
0357     send_serial_number(resource->handle, m_serialNumber);
0358 }
0359 
0360 void OutputDeviceV2InterfacePrivate::sendEisaId(Resource *resource)
0361 {
0362     send_eisa_id(resource->handle, m_eisaId);
0363 }
0364 
0365 void OutputDeviceV2InterfacePrivate::sendName(Resource *resource)
0366 {
0367     if (resource->version() >= KDE_OUTPUT_DEVICE_V2_NAME_SINCE_VERSION) {
0368         send_name(resource->handle, m_name);
0369     }
0370 }
0371 
0372 void OutputDeviceV2InterfacePrivate::sendDone(Resource *resource)
0373 {
0374     send_done(resource->handle);
0375 }
0376 
0377 void OutputDeviceV2InterfacePrivate::sendEdid(Resource *resource)
0378 {
0379     send_edid(resource->handle, QString::fromStdString(m_edid.toBase64().toStdString()));
0380 }
0381 
0382 void OutputDeviceV2InterfacePrivate::sendEnabled(Resource *resource)
0383 {
0384     send_enabled(resource->handle, m_enabled);
0385 }
0386 
0387 void OutputDeviceV2InterfacePrivate::sendUuid(Resource *resource)
0388 {
0389     send_uuid(resource->handle, m_uuid.toString(QUuid::WithoutBraces));
0390 }
0391 
0392 void OutputDeviceV2InterfacePrivate::sendCapabilities(Resource *resource)
0393 {
0394     send_capabilities(resource->handle, m_capabilities);
0395 }
0396 
0397 void OutputDeviceV2InterfacePrivate::sendOverscan(Resource *resource)
0398 {
0399     send_overscan(resource->handle, m_overscan);
0400 }
0401 
0402 void OutputDeviceV2InterfacePrivate::sendVrrPolicy(Resource *resource)
0403 {
0404     send_vrr_policy(resource->handle, m_vrrPolicy);
0405 }
0406 
0407 void OutputDeviceV2InterfacePrivate::sendRgbRange(Resource *resource)
0408 {
0409     send_rgb_range(resource->handle, m_rgbRange);
0410 }
0411 
0412 void OutputDeviceV2InterfacePrivate::sendHighDynamicRange(Resource *resource)
0413 {
0414     if (resource->version() >= KDE_OUTPUT_DEVICE_V2_HIGH_DYNAMIC_RANGE_SINCE_VERSION) {
0415         send_high_dynamic_range(resource->handle, m_highDynamicRange ? 1 : 0);
0416     }
0417 }
0418 
0419 void OutputDeviceV2InterfacePrivate::sendSdrBrightness(Resource *resource)
0420 {
0421     if (resource->version() >= KDE_OUTPUT_DEVICE_V2_SDR_BRIGHTNESS_SINCE_VERSION) {
0422         send_sdr_brightness(resource->handle, m_sdrBrightness);
0423     }
0424 }
0425 
0426 void OutputDeviceV2InterfacePrivate::sendWideColorGamut(Resource *resource)
0427 {
0428     if (resource->version() >= KDE_OUTPUT_DEVICE_V2_WIDE_COLOR_GAMUT_SINCE_VERSION) {
0429         send_wide_color_gamut(resource->handle, m_wideColorGamut ? 1 : 0);
0430     }
0431 }
0432 
0433 void OutputDeviceV2InterfacePrivate::sendAutoRotationPolicy(Resource *resource)
0434 {
0435     if (resource->version() >= KDE_OUTPUT_DEVICE_V2_AUTO_ROTATE_POLICY_SINCE_VERSION) {
0436         send_auto_rotate_policy(resource->handle, m_autoRotation);
0437     }
0438 }
0439 
0440 void OutputDeviceV2InterfacePrivate::sendIccProfilePath(Resource *resource)
0441 {
0442     if (resource->version() >= KDE_OUTPUT_DEVICE_V2_ICC_PROFILE_PATH_SINCE_VERSION) {
0443         send_icc_profile_path(resource->handle, m_iccProfilePath);
0444     }
0445 }
0446 
0447 void OutputDeviceV2InterfacePrivate::sendBrightnessMetadata(Resource *resource)
0448 {
0449     if (resource->version() >= KDE_OUTPUT_DEVICE_V2_BRIGHTNESS_METADATA_SINCE_VERSION) {
0450         send_brightness_metadata(resource->handle, std::round(m_maxPeakBrightness.value_or(0)), std::round(m_maxAverageBrightness.value_or(0)), std::round(m_minBrightness * 10'000));
0451     }
0452 }
0453 
0454 void OutputDeviceV2InterfacePrivate::sendBrightnessOverrides(Resource *resource)
0455 {
0456     if (resource->version() >= KDE_OUTPUT_DEVICE_V2_BRIGHTNESS_OVERRIDES_SINCE_VERSION) {
0457         send_brightness_overrides(resource->handle, std::round(m_maxPeakBrightnessOverride.value_or(-1)), std::round(m_maxAverageBrightnessOverride.value_or(-1)), std::round(m_minBrightnessOverride.value_or(-0.000'1) * 10'000));
0458     }
0459 }
0460 
0461 void OutputDeviceV2InterfacePrivate::sendSdrGamutWideness(Resource *resource)
0462 {
0463     if (resource->version() >= KDE_OUTPUT_DEVICE_V2_SDR_GAMUT_WIDENESS_SINCE_VERSION) {
0464         send_sdr_gamut_wideness(resource->handle, std::clamp<uint32_t>(m_sdrGamutWideness * 10'000, 0, 10'000));
0465     }
0466 }
0467 
0468 void OutputDeviceV2Interface::updateGeometry()
0469 {
0470     const auto clientResources = d->resourceMap();
0471     for (const auto &resource : clientResources) {
0472         d->sendGeometry(resource);
0473         d->sendDone(resource);
0474     }
0475 }
0476 
0477 void OutputDeviceV2Interface::updatePhysicalSize()
0478 {
0479     d->m_physicalSize = d->m_handle->physicalSize();
0480 }
0481 
0482 void OutputDeviceV2Interface::updateGlobalPosition()
0483 {
0484     const QPoint arg = d->m_handle->geometry().topLeft();
0485     if (d->m_globalPosition == arg) {
0486         return;
0487     }
0488     d->m_globalPosition = arg;
0489     updateGeometry();
0490 }
0491 
0492 void OutputDeviceV2Interface::updateManufacturer()
0493 {
0494     d->m_manufacturer = d->m_handle->manufacturer();
0495 }
0496 
0497 void OutputDeviceV2Interface::updateModel()
0498 {
0499     d->m_model = d->m_handle->model();
0500 }
0501 
0502 void OutputDeviceV2Interface::updateSerialNumber()
0503 {
0504     d->m_serialNumber = d->m_handle->serialNumber();
0505 }
0506 
0507 void OutputDeviceV2Interface::updateEisaId()
0508 {
0509     d->m_eisaId = d->m_handle->eisaId();
0510 }
0511 
0512 void OutputDeviceV2Interface::updateName()
0513 {
0514     d->m_name = d->m_handle->name();
0515 }
0516 
0517 void OutputDeviceV2Interface::updateSubPixel()
0518 {
0519     const auto arg = kwinSubPixelToOutputDeviceSubPixel(d->m_handle->subPixel());
0520     if (d->m_subPixel != arg) {
0521         d->m_subPixel = arg;
0522         updateGeometry();
0523     }
0524 }
0525 
0526 void OutputDeviceV2Interface::updateTransform()
0527 {
0528     const auto arg = kwinTransformToOutputDeviceTransform(d->m_handle->transform());
0529     if (d->m_transform != arg) {
0530         d->m_transform = arg;
0531         updateGeometry();
0532     }
0533 }
0534 
0535 void OutputDeviceV2Interface::updateScale()
0536 {
0537     const qreal scale = d->m_handle->scale();
0538     if (qFuzzyCompare(d->m_scale, scale)) {
0539         return;
0540     }
0541     d->m_scale = scale;
0542     const auto clientResources = d->resourceMap();
0543     for (const auto &resource : clientResources) {
0544         d->sendScale(resource);
0545         d->sendDone(resource);
0546     }
0547 }
0548 
0549 void OutputDeviceV2Interface::updateModes()
0550 {
0551     const auto oldModes = d->m_modes;
0552     d->m_modes.clear();
0553     d->m_currentMode = nullptr;
0554 
0555     const auto clientResources = d->resourceMap();
0556     const auto nativeModes = d->m_handle->modes();
0557 
0558     for (const std::shared_ptr<OutputMode> &mode : nativeModes) {
0559         OutputDeviceModeV2Interface *deviceMode = new OutputDeviceModeV2Interface(mode, this);
0560         d->m_modes.append(deviceMode);
0561 
0562         if (d->m_handle->currentMode() == mode) {
0563             d->m_currentMode = deviceMode;
0564         }
0565 
0566         for (auto resource : clientResources) {
0567             d->sendNewMode(resource, deviceMode);
0568         }
0569     }
0570 
0571     for (auto resource : clientResources) {
0572         d->sendCurrentMode(resource);
0573     }
0574 
0575     qDeleteAll(oldModes.crbegin(), oldModes.crend());
0576 
0577     for (auto resource : clientResources) {
0578         d->sendDone(resource);
0579     }
0580 }
0581 
0582 void OutputDeviceV2Interface::updateCurrentMode()
0583 {
0584     for (OutputDeviceModeV2Interface *mode : std::as_const(d->m_modes)) {
0585         if (mode->handle().lock() == d->m_handle->currentMode()) {
0586             if (d->m_currentMode != mode) {
0587                 d->m_currentMode = mode;
0588                 const auto clientResources = d->resourceMap();
0589                 for (auto resource : clientResources) {
0590                     d->sendCurrentMode(resource);
0591                     d->sendDone(resource);
0592                 }
0593                 updateGeometry();
0594             }
0595             return;
0596         }
0597     }
0598 }
0599 
0600 void OutputDeviceV2Interface::updateEdid()
0601 {
0602     d->m_edid = d->m_handle->edid().raw();
0603     const auto clientResources = d->resourceMap();
0604     for (const auto &resource : clientResources) {
0605         d->sendEdid(resource);
0606         d->sendDone(resource);
0607     }
0608 }
0609 
0610 void OutputDeviceV2Interface::updateEnabled()
0611 {
0612     bool enabled = d->m_handle->isEnabled();
0613     if (d->m_enabled != enabled) {
0614         d->m_enabled = enabled;
0615         const auto clientResources = d->resourceMap();
0616         for (const auto &resource : clientResources) {
0617             d->sendEnabled(resource);
0618             d->sendDone(resource);
0619         }
0620     }
0621 }
0622 
0623 void OutputDeviceV2Interface::updateUuid()
0624 {
0625     const QUuid uuid = d->m_handle->uuid();
0626     if (d->m_uuid != uuid) {
0627         d->m_uuid = uuid;
0628         const auto clientResources = d->resourceMap();
0629         for (const auto &resource : clientResources) {
0630             d->sendUuid(resource);
0631             d->sendDone(resource);
0632         }
0633     }
0634 }
0635 
0636 void OutputDeviceV2Interface::updateCapabilities()
0637 {
0638     const uint32_t cap = kwinCapabilitiesToOutputDeviceCapabilities(d->m_handle->capabilities());
0639     if (d->m_capabilities != cap) {
0640         d->m_capabilities = cap;
0641         const auto clientResources = d->resourceMap();
0642         for (const auto &resource : clientResources) {
0643             d->sendCapabilities(resource);
0644             d->sendDone(resource);
0645         }
0646     }
0647 }
0648 
0649 void OutputDeviceV2Interface::updateOverscan()
0650 {
0651     const uint32_t overscan = d->m_handle->overscan();
0652     if (d->m_overscan != overscan) {
0653         d->m_overscan = overscan;
0654         const auto clientResources = d->resourceMap();
0655         for (const auto &resource : clientResources) {
0656             d->sendOverscan(resource);
0657             d->sendDone(resource);
0658         }
0659     }
0660 }
0661 
0662 void OutputDeviceV2Interface::updateVrrPolicy()
0663 {
0664     const auto policy = kwinVrrPolicyToOutputDeviceVrrPolicy(d->m_handle->vrrPolicy());
0665     if (d->m_vrrPolicy != policy) {
0666         d->m_vrrPolicy = policy;
0667         const auto clientResources = d->resourceMap();
0668         for (const auto &resource : clientResources) {
0669             d->sendVrrPolicy(resource);
0670             d->sendDone(resource);
0671         }
0672     }
0673 }
0674 
0675 void OutputDeviceV2Interface::updateRgbRange()
0676 {
0677     const auto rgbRange = kwinRgbRangeToOutputDeviceRgbRange(d->m_handle->rgbRange());
0678     if (d->m_rgbRange != rgbRange) {
0679         d->m_rgbRange = rgbRange;
0680         const auto clientResources = d->resourceMap();
0681         for (const auto &resource : clientResources) {
0682             d->sendRgbRange(resource);
0683             d->sendDone(resource);
0684         }
0685     }
0686 }
0687 
0688 void OutputDeviceV2Interface::updateHighDynamicRange()
0689 {
0690     if (d->m_highDynamicRange != d->m_handle->highDynamicRange()) {
0691         d->m_highDynamicRange = d->m_handle->highDynamicRange();
0692         const auto clientResources = d->resourceMap();
0693         for (const auto &resource : clientResources) {
0694             d->sendHighDynamicRange(resource);
0695             d->sendDone(resource);
0696         }
0697     }
0698 }
0699 
0700 void OutputDeviceV2Interface::updateSdrBrightness()
0701 {
0702     if (d->m_sdrBrightness != d->m_handle->sdrBrightness()) {
0703         d->m_sdrBrightness = d->m_handle->sdrBrightness();
0704         const auto clientResources = d->resourceMap();
0705         for (const auto &resource : clientResources) {
0706             d->sendSdrBrightness(resource);
0707             d->sendDone(resource);
0708         }
0709     }
0710 }
0711 
0712 void OutputDeviceV2Interface::updateWideColorGamut()
0713 {
0714     if (d->m_wideColorGamut != d->m_handle->wideColorGamut()) {
0715         d->m_wideColorGamut = d->m_handle->wideColorGamut();
0716         const auto clientResources = d->resourceMap();
0717         for (const auto &resource : clientResources) {
0718             d->sendWideColorGamut(resource);
0719             d->sendDone(resource);
0720         }
0721     }
0722 }
0723 
0724 void OutputDeviceV2Interface::updateAutoRotate()
0725 {
0726     const auto policy = kwinAutoRotationToOutputDeviceAutoRotation(d->m_handle->autoRotationPolicy());
0727     if (d->m_autoRotation != policy) {
0728         d->m_autoRotation = policy;
0729         const auto clientResources = d->resourceMap();
0730         for (const auto &resource : clientResources) {
0731             d->sendAutoRotationPolicy(resource);
0732             d->sendDone(resource);
0733         }
0734     }
0735 }
0736 
0737 void OutputDeviceV2Interface::updateIccProfilePath()
0738 {
0739     if (d->m_iccProfilePath != d->m_handle->iccProfilePath()) {
0740         d->m_iccProfilePath = d->m_handle->iccProfilePath();
0741         const auto clientResources = d->resourceMap();
0742         for (const auto &resource : clientResources) {
0743             d->sendIccProfilePath(resource);
0744             d->sendDone(resource);
0745         }
0746     }
0747 }
0748 
0749 void OutputDeviceV2Interface::updateBrightnessMetadata()
0750 {
0751     if (d->m_maxPeakBrightness != d->m_handle->maxPeakBrightness() || d->m_maxAverageBrightness != d->m_handle->maxAverageBrightness() || d->m_minBrightness != d->m_handle->minBrightness()) {
0752         d->m_maxPeakBrightness = d->m_handle->maxPeakBrightness();
0753         d->m_maxAverageBrightness = d->m_handle->maxAverageBrightness();
0754         d->m_minBrightness = d->m_handle->minBrightness();
0755         const auto clientResources = d->resourceMap();
0756         for (const auto &resource : clientResources) {
0757             d->sendBrightnessMetadata(resource);
0758             d->sendDone(resource);
0759         }
0760     }
0761 }
0762 
0763 void OutputDeviceV2Interface::updateBrightnessOverrides()
0764 {
0765     if (d->m_maxPeakBrightnessOverride != d->m_handle->maxPeakBrightnessOverride() || d->m_maxAverageBrightnessOverride != d->m_handle->maxAverageBrightnessOverride() || d->m_minBrightnessOverride != d->m_handle->minBrightnessOverride()) {
0766         d->m_maxPeakBrightnessOverride = d->m_handle->maxPeakBrightnessOverride();
0767         d->m_maxAverageBrightnessOverride = d->m_handle->maxAverageBrightnessOverride();
0768         d->m_minBrightnessOverride = d->m_handle->minBrightnessOverride();
0769         const auto clientResources = d->resourceMap();
0770         for (const auto &resource : clientResources) {
0771             d->sendBrightnessOverrides(resource);
0772             d->sendDone(resource);
0773         }
0774     }
0775 }
0776 
0777 void OutputDeviceV2Interface::updateSdrGamutWideness()
0778 {
0779     if (d->m_sdrGamutWideness != d->m_handle->sdrGamutWideness()) {
0780         d->m_sdrGamutWideness = d->m_handle->sdrGamutWideness();
0781         const auto clientResources = d->resourceMap();
0782         for (const auto &resource : clientResources) {
0783             d->sendSdrGamutWideness(resource);
0784             d->sendDone(resource);
0785         }
0786     }
0787 }
0788 
0789 OutputDeviceV2Interface *OutputDeviceV2Interface::get(wl_resource *native)
0790 {
0791     if (auto devicePrivate = resource_cast<OutputDeviceV2InterfacePrivate *>(native); devicePrivate && !devicePrivate->isGlobalRemoved()) {
0792         return devicePrivate->q;
0793     }
0794     return nullptr;
0795 }
0796 
0797 OutputDeviceModeV2InterfacePrivate::OutputDeviceModeV2InterfacePrivate(OutputDeviceModeV2Interface *q, std::shared_ptr<OutputMode> handle)
0798     : QtWaylandServer::kde_output_device_mode_v2()
0799     , q(q)
0800     , m_handle(handle)
0801     , m_size(handle->size())
0802     , m_refreshRate(handle->refreshRate())
0803     , m_preferred(handle->flags() & OutputMode::Flag::Preferred)
0804 {
0805 }
0806 
0807 OutputDeviceModeV2Interface::OutputDeviceModeV2Interface(std::shared_ptr<OutputMode> handle, QObject *parent)
0808     : QObject(parent)
0809     , d(new OutputDeviceModeV2InterfacePrivate(this, handle))
0810 {
0811 }
0812 
0813 OutputDeviceModeV2Interface::~OutputDeviceModeV2Interface() = default;
0814 
0815 OutputDeviceModeV2InterfacePrivate::~OutputDeviceModeV2InterfacePrivate()
0816 {
0817     const auto map = resourceMap();
0818     for (Resource *resource : map) {
0819         send_removed(resource->handle);
0820     }
0821 }
0822 
0823 OutputDeviceModeV2InterfacePrivate::Resource *OutputDeviceModeV2InterfacePrivate::createResource(OutputDeviceV2InterfacePrivate::Resource *output)
0824 {
0825     const auto modeResource = static_cast<ModeResource *>(add(output->client(), output->version()));
0826     modeResource->output = output;
0827     return modeResource;
0828 }
0829 
0830 OutputDeviceModeV2InterfacePrivate::Resource *OutputDeviceModeV2InterfacePrivate::findResource(OutputDeviceV2InterfacePrivate::Resource *output) const
0831 {
0832     const auto resources = resourceMap();
0833     for (const auto &resource : resources) {
0834         auto modeResource = static_cast<ModeResource *>(resource);
0835         if (modeResource->output == output) {
0836             return resource;
0837         }
0838     }
0839     return nullptr;
0840 }
0841 
0842 OutputDeviceModeV2InterfacePrivate::Resource *OutputDeviceModeV2InterfacePrivate::kde_output_device_mode_v2_allocate()
0843 {
0844     return new ModeResource;
0845 }
0846 
0847 std::weak_ptr<OutputMode> OutputDeviceModeV2Interface::handle() const
0848 {
0849     return d->m_handle;
0850 }
0851 
0852 void OutputDeviceModeV2InterfacePrivate::bindResource(wl_resource *resource)
0853 {
0854     send_size(resource, m_size.width(), m_size.height());
0855     send_refresh(resource, m_refreshRate);
0856 
0857     if (m_preferred) {
0858         send_preferred(resource);
0859     }
0860 }
0861 
0862 OutputDeviceModeV2Interface *OutputDeviceModeV2Interface::get(wl_resource *native)
0863 {
0864     if (auto devicePrivate = resource_cast<OutputDeviceModeV2InterfacePrivate *>(native)) {
0865         return devicePrivate->q;
0866     }
0867     return nullptr;
0868 }
0869 
0870 }
0871 
0872 #include "moc_outputdevice_v2.cpp"