File indexing completed on 2024-05-19 16:35:22
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_interface.h" 0008 0009 #include "display.h" 0010 #include "display_p.h" 0011 #include "utils.h" 0012 #include "utils/common.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 using namespace KWin; 0023 0024 namespace KWaylandServer 0025 { 0026 0027 static const quint32 s_version = 2; 0028 0029 static QtWaylandServer::kde_output_device_v2::transform kwinTransformToOutputDeviceTransform(Output::Transform transform) 0030 { 0031 return static_cast<QtWaylandServer::kde_output_device_v2::transform>(transform); 0032 } 0033 0034 static QtWaylandServer::kde_output_device_v2::subpixel kwinSubPixelToOutputDeviceSubPixel(Output::SubPixel subPixel) 0035 { 0036 return static_cast<QtWaylandServer::kde_output_device_v2::subpixel>(subPixel); 0037 } 0038 0039 static uint32_t kwinCapabilitiesToOutputDeviceCapabilities(Output::Capabilities caps) 0040 { 0041 uint32_t ret = 0; 0042 if (caps & Output::Capability::Overscan) { 0043 ret |= QtWaylandServer::kde_output_device_v2::capability_overscan; 0044 } 0045 if (caps & Output::Capability::Vrr) { 0046 ret |= QtWaylandServer::kde_output_device_v2::capability_vrr; 0047 } 0048 if (caps & Output::Capability::RgbRange) { 0049 ret |= QtWaylandServer::kde_output_device_v2::capability_rgb_range; 0050 } 0051 return ret; 0052 } 0053 0054 static QtWaylandServer::kde_output_device_v2::vrr_policy kwinVrrPolicyToOutputDeviceVrrPolicy(RenderLoop::VrrPolicy policy) 0055 { 0056 return static_cast<QtWaylandServer::kde_output_device_v2::vrr_policy>(policy); 0057 } 0058 0059 static QtWaylandServer::kde_output_device_v2::rgb_range kwinRgbRangeToOutputDeviceRgbRange(Output::RgbRange range) 0060 { 0061 return static_cast<QtWaylandServer::kde_output_device_v2::rgb_range>(range); 0062 } 0063 0064 class OutputDeviceV2InterfacePrivate : public QtWaylandServer::kde_output_device_v2 0065 { 0066 public: 0067 OutputDeviceV2InterfacePrivate(OutputDeviceV2Interface *q, Display *display, KWin::Output *handle); 0068 ~OutputDeviceV2InterfacePrivate() override; 0069 0070 void sendGeometry(Resource *resource); 0071 wl_resource *sendNewMode(Resource *resource, OutputDeviceModeV2Interface *mode); 0072 void sendCurrentMode(Resource *resource); 0073 void sendDone(Resource *resource); 0074 void sendUuid(Resource *resource); 0075 void sendEdid(Resource *resource); 0076 void sendEnabled(Resource *resource); 0077 void sendScale(Resource *resource); 0078 void sendEisaId(Resource *resource); 0079 void sendName(Resource *resource); 0080 void sendSerialNumber(Resource *resource); 0081 void sendCapabilities(Resource *resource); 0082 void sendOverscan(Resource *resource); 0083 void sendVrrPolicy(Resource *resource); 0084 void sendRgbRange(Resource *resource); 0085 0086 OutputDeviceV2Interface *q; 0087 QPointer<Display> m_display; 0088 KWin::Output *m_handle; 0089 QSize m_physicalSize; 0090 QPoint m_globalPosition; 0091 QString m_manufacturer = QStringLiteral("org.kde.kwin"); 0092 QString m_model = QStringLiteral("none"); 0093 qreal m_scale = 1.0; 0094 QString m_serialNumber; 0095 QString m_eisaId; 0096 QString m_name; 0097 subpixel m_subPixel = subpixel_unknown; 0098 transform m_transform = transform_normal; 0099 QList<OutputDeviceModeV2Interface *> m_modes; 0100 OutputDeviceModeV2Interface *m_currentMode = nullptr; 0101 QByteArray m_edid; 0102 bool m_enabled = true; 0103 QUuid m_uuid; 0104 uint32_t m_capabilities = 0; 0105 uint32_t m_overscan = 0; 0106 vrr_policy m_vrrPolicy = vrr_policy_automatic; 0107 rgb_range m_rgbRange = rgb_range_automatic; 0108 0109 protected: 0110 void kde_output_device_v2_bind_resource(Resource *resource) override; 0111 void kde_output_device_v2_destroy_global() override; 0112 }; 0113 0114 class OutputDeviceModeV2InterfacePrivate : public QtWaylandServer::kde_output_device_mode_v2 0115 { 0116 public: 0117 struct ModeResource : Resource 0118 { 0119 OutputDeviceV2InterfacePrivate::Resource *output; 0120 }; 0121 0122 OutputDeviceModeV2InterfacePrivate(OutputDeviceModeV2Interface *q, std::shared_ptr<KWin::OutputMode> handle); 0123 ~OutputDeviceModeV2InterfacePrivate() override; 0124 0125 Resource *createResource(OutputDeviceV2InterfacePrivate::Resource *output); 0126 Resource *findResource(OutputDeviceV2InterfacePrivate::Resource *output) const; 0127 0128 void bindResource(wl_resource *resource); 0129 0130 static OutputDeviceModeV2InterfacePrivate *get(OutputDeviceModeV2Interface *mode) 0131 { 0132 return mode->d.get(); 0133 } 0134 0135 OutputDeviceModeV2Interface *q; 0136 std::weak_ptr<KWin::OutputMode> m_handle; 0137 QSize m_size; 0138 int m_refreshRate = 60000; 0139 bool m_preferred = false; 0140 0141 protected: 0142 Resource *kde_output_device_mode_v2_allocate() override; 0143 }; 0144 0145 OutputDeviceV2InterfacePrivate::OutputDeviceV2InterfacePrivate(OutputDeviceV2Interface *q, Display *display, KWin::Output *handle) 0146 : QtWaylandServer::kde_output_device_v2(*display, s_version) 0147 , q(q) 0148 , m_display(display) 0149 , m_handle(handle) 0150 { 0151 DisplayPrivate *displayPrivate = DisplayPrivate::get(display); 0152 displayPrivate->outputdevicesV2.append(q); 0153 } 0154 0155 OutputDeviceV2InterfacePrivate::~OutputDeviceV2InterfacePrivate() 0156 { 0157 if (m_display) { 0158 DisplayPrivate *displayPrivate = DisplayPrivate::get(m_display); 0159 displayPrivate->outputdevicesV2.removeOne(q); 0160 } 0161 } 0162 0163 OutputDeviceV2Interface::OutputDeviceV2Interface(Display *display, KWin::Output *handle, QObject *parent) 0164 : QObject(parent) 0165 , d(new OutputDeviceV2InterfacePrivate(this, display, handle)) 0166 { 0167 updateEnabled(); 0168 updateManufacturer(); 0169 updateEdid(); 0170 updateUuid(); 0171 updateModel(); 0172 updatePhysicalSize(); 0173 updateGlobalPosition(); 0174 updateScale(); 0175 updateTransform(); 0176 updateEisaId(); 0177 updateSerialNumber(); 0178 updateSubPixel(); 0179 updateOverscan(); 0180 updateCapabilities(); 0181 updateVrrPolicy(); 0182 updateRgbRange(); 0183 updateName(); 0184 updateModes(); 0185 0186 connect(handle, &Output::geometryChanged, 0187 this, &OutputDeviceV2Interface::updateGlobalPosition); 0188 connect(handle, &Output::scaleChanged, 0189 this, &OutputDeviceV2Interface::updateScale); 0190 connect(handle, &Output::enabledChanged, 0191 this, &OutputDeviceV2Interface::updateEnabled); 0192 connect(handle, &Output::transformChanged, 0193 this, &OutputDeviceV2Interface::updateTransform); 0194 connect(handle, &Output::currentModeChanged, 0195 this, &OutputDeviceV2Interface::updateCurrentMode); 0196 connect(handle, &Output::capabilitiesChanged, 0197 this, &OutputDeviceV2Interface::updateCapabilities); 0198 connect(handle, &Output::overscanChanged, 0199 this, &OutputDeviceV2Interface::updateOverscan); 0200 connect(handle, &Output::vrrPolicyChanged, 0201 this, &OutputDeviceV2Interface::updateVrrPolicy); 0202 connect(handle, &Output::modesChanged, 0203 this, &OutputDeviceV2Interface::updateModes); 0204 connect(handle, &Output::rgbRangeChanged, 0205 this, &OutputDeviceV2Interface::updateRgbRange); 0206 } 0207 0208 OutputDeviceV2Interface::~OutputDeviceV2Interface() 0209 { 0210 d->globalRemove(); 0211 } 0212 0213 void OutputDeviceV2Interface::remove() 0214 { 0215 if (d->isGlobalRemoved()) { 0216 return; 0217 } 0218 0219 if (d->m_display) { 0220 DisplayPrivate *displayPrivate = DisplayPrivate::get(d->m_display); 0221 displayPrivate->outputdevicesV2.removeOne(this); 0222 } 0223 0224 d->globalRemove(); 0225 } 0226 0227 KWin::Output *OutputDeviceV2Interface::handle() const 0228 { 0229 return d->m_handle; 0230 } 0231 0232 void OutputDeviceV2InterfacePrivate::kde_output_device_v2_destroy_global() 0233 { 0234 delete q; 0235 } 0236 0237 void OutputDeviceV2InterfacePrivate::kde_output_device_v2_bind_resource(Resource *resource) 0238 { 0239 sendGeometry(resource); 0240 sendScale(resource); 0241 sendEisaId(resource); 0242 sendName(resource); 0243 sendSerialNumber(resource); 0244 0245 for (OutputDeviceModeV2Interface *mode : std::as_const(m_modes)) { 0246 sendNewMode(resource, mode); 0247 } 0248 sendCurrentMode(resource); 0249 sendUuid(resource); 0250 sendEdid(resource); 0251 sendEnabled(resource); 0252 sendCapabilities(resource); 0253 sendOverscan(resource); 0254 sendVrrPolicy(resource); 0255 sendRgbRange(resource); 0256 sendDone(resource); 0257 } 0258 0259 wl_resource *OutputDeviceV2InterfacePrivate::sendNewMode(Resource *resource, OutputDeviceModeV2Interface *mode) 0260 { 0261 auto privateMode = OutputDeviceModeV2InterfacePrivate::get(mode); 0262 // bind mode to client 0263 const auto modeResource = privateMode->createResource(resource); 0264 0265 send_mode(resource->handle, modeResource->handle); 0266 0267 privateMode->bindResource(modeResource->handle); 0268 0269 return modeResource->handle; 0270 } 0271 0272 void OutputDeviceV2InterfacePrivate::sendCurrentMode(Resource *outputResource) 0273 { 0274 const auto modeResource = OutputDeviceModeV2InterfacePrivate::get(m_currentMode)->findResource(outputResource); 0275 send_current_mode(outputResource->handle, modeResource->handle); 0276 } 0277 0278 void OutputDeviceV2InterfacePrivate::sendGeometry(Resource *resource) 0279 { 0280 send_geometry(resource->handle, 0281 m_globalPosition.x(), 0282 m_globalPosition.y(), 0283 m_physicalSize.width(), 0284 m_physicalSize.height(), 0285 m_subPixel, 0286 m_manufacturer, 0287 m_model, 0288 m_transform); 0289 } 0290 0291 void OutputDeviceV2InterfacePrivate::sendScale(Resource *resource) 0292 { 0293 send_scale(resource->handle, wl_fixed_from_double(m_scale)); 0294 } 0295 0296 void OutputDeviceV2InterfacePrivate::sendSerialNumber(Resource *resource) 0297 { 0298 send_serial_number(resource->handle, m_serialNumber); 0299 } 0300 0301 void OutputDeviceV2InterfacePrivate::sendEisaId(Resource *resource) 0302 { 0303 send_eisa_id(resource->handle, m_eisaId); 0304 } 0305 0306 void OutputDeviceV2InterfacePrivate::sendName(Resource *resource) 0307 { 0308 if (resource->version() >= KDE_OUTPUT_DEVICE_V2_NAME_SINCE_VERSION) { 0309 send_name(resource->handle, m_name); 0310 } 0311 } 0312 0313 void OutputDeviceV2InterfacePrivate::sendDone(Resource *resource) 0314 { 0315 send_done(resource->handle); 0316 } 0317 0318 void OutputDeviceV2InterfacePrivate::sendEdid(Resource *resource) 0319 { 0320 send_edid(resource->handle, QString::fromStdString(m_edid.toBase64().toStdString())); 0321 } 0322 0323 void OutputDeviceV2InterfacePrivate::sendEnabled(Resource *resource) 0324 { 0325 send_enabled(resource->handle, m_enabled); 0326 } 0327 0328 void OutputDeviceV2InterfacePrivate::sendUuid(Resource *resource) 0329 { 0330 send_uuid(resource->handle, m_uuid.toString(QUuid::WithoutBraces)); 0331 } 0332 0333 void OutputDeviceV2InterfacePrivate::sendCapabilities(Resource *resource) 0334 { 0335 send_capabilities(resource->handle, m_capabilities); 0336 } 0337 0338 void OutputDeviceV2InterfacePrivate::sendOverscan(Resource *resource) 0339 { 0340 send_overscan(resource->handle, m_overscan); 0341 } 0342 0343 void OutputDeviceV2InterfacePrivate::sendVrrPolicy(Resource *resource) 0344 { 0345 send_vrr_policy(resource->handle, m_vrrPolicy); 0346 } 0347 0348 void OutputDeviceV2InterfacePrivate::sendRgbRange(Resource *resource) 0349 { 0350 send_rgb_range(resource->handle, m_rgbRange); 0351 } 0352 0353 void OutputDeviceV2Interface::updateGeometry() 0354 { 0355 const auto clientResources = d->resourceMap(); 0356 for (const auto &resource : clientResources) { 0357 d->sendGeometry(resource); 0358 d->sendDone(resource); 0359 } 0360 } 0361 0362 void OutputDeviceV2Interface::updatePhysicalSize() 0363 { 0364 d->m_physicalSize = d->m_handle->physicalSize(); 0365 } 0366 0367 void OutputDeviceV2Interface::updateGlobalPosition() 0368 { 0369 const QPoint arg = d->m_handle->geometry().topLeft(); 0370 if (d->m_globalPosition == arg) { 0371 return; 0372 } 0373 d->m_globalPosition = arg; 0374 updateGeometry(); 0375 } 0376 0377 void OutputDeviceV2Interface::updateManufacturer() 0378 { 0379 d->m_manufacturer = d->m_handle->manufacturer(); 0380 } 0381 0382 void OutputDeviceV2Interface::updateModel() 0383 { 0384 d->m_model = d->m_handle->model(); 0385 } 0386 0387 void OutputDeviceV2Interface::updateSerialNumber() 0388 { 0389 d->m_serialNumber = d->m_handle->serialNumber(); 0390 } 0391 0392 void OutputDeviceV2Interface::updateEisaId() 0393 { 0394 d->m_eisaId = d->m_handle->eisaId(); 0395 } 0396 0397 void OutputDeviceV2Interface::updateName() 0398 { 0399 d->m_name = d->m_handle->name(); 0400 } 0401 0402 void OutputDeviceV2Interface::updateSubPixel() 0403 { 0404 const auto arg = kwinSubPixelToOutputDeviceSubPixel(d->m_handle->subPixel()); 0405 if (d->m_subPixel != arg) { 0406 d->m_subPixel = arg; 0407 updateGeometry(); 0408 } 0409 } 0410 0411 void OutputDeviceV2Interface::updateTransform() 0412 { 0413 const auto arg = kwinTransformToOutputDeviceTransform(d->m_handle->transform()); 0414 if (d->m_transform != arg) { 0415 d->m_transform = arg; 0416 updateGeometry(); 0417 } 0418 } 0419 0420 void OutputDeviceV2Interface::updateScale() 0421 { 0422 const qreal scale = d->m_handle->scale(); 0423 if (qFuzzyCompare(d->m_scale, scale)) { 0424 return; 0425 } 0426 d->m_scale = scale; 0427 const auto clientResources = d->resourceMap(); 0428 for (const auto &resource : clientResources) { 0429 d->sendScale(resource); 0430 d->sendDone(resource); 0431 } 0432 } 0433 0434 void OutputDeviceV2Interface::updateModes() 0435 { 0436 const auto oldModes = d->m_modes; 0437 d->m_modes.clear(); 0438 d->m_currentMode = nullptr; 0439 0440 const auto clientResources = d->resourceMap(); 0441 const auto nativeModes = d->m_handle->modes(); 0442 0443 for (const std::shared_ptr<OutputMode> &mode : nativeModes) { 0444 OutputDeviceModeV2Interface *deviceMode = new OutputDeviceModeV2Interface(mode, this); 0445 d->m_modes.append(deviceMode); 0446 0447 if (d->m_handle->currentMode() == mode) { 0448 d->m_currentMode = deviceMode; 0449 } 0450 0451 for (auto resource : clientResources) { 0452 d->sendNewMode(resource, deviceMode); 0453 } 0454 } 0455 0456 for (auto resource : clientResources) { 0457 d->sendCurrentMode(resource); 0458 } 0459 0460 qDeleteAll(oldModes.crbegin(), oldModes.crend()); 0461 0462 for (auto resource : clientResources) { 0463 d->sendDone(resource); 0464 } 0465 } 0466 0467 void OutputDeviceV2Interface::updateCurrentMode() 0468 { 0469 for (OutputDeviceModeV2Interface *mode : std::as_const(d->m_modes)) { 0470 if (mode->handle().lock() == d->m_handle->currentMode()) { 0471 if (d->m_currentMode != mode) { 0472 d->m_currentMode = mode; 0473 const auto clientResources = d->resourceMap(); 0474 for (auto resource : clientResources) { 0475 d->sendCurrentMode(resource); 0476 d->sendDone(resource); 0477 } 0478 updateGeometry(); 0479 } 0480 return; 0481 } 0482 } 0483 } 0484 0485 void OutputDeviceV2Interface::updateEdid() 0486 { 0487 d->m_edid = d->m_handle->edid(); 0488 const auto clientResources = d->resourceMap(); 0489 for (const auto &resource : clientResources) { 0490 d->sendEdid(resource); 0491 d->sendDone(resource); 0492 } 0493 } 0494 0495 void OutputDeviceV2Interface::updateEnabled() 0496 { 0497 bool enabled = d->m_handle->isEnabled(); 0498 if (d->m_enabled != enabled) { 0499 d->m_enabled = enabled; 0500 const auto clientResources = d->resourceMap(); 0501 for (const auto &resource : clientResources) { 0502 d->sendEnabled(resource); 0503 d->sendDone(resource); 0504 } 0505 } 0506 } 0507 0508 void OutputDeviceV2Interface::updateUuid() 0509 { 0510 const QUuid uuid = d->m_handle->uuid(); 0511 if (d->m_uuid != uuid) { 0512 d->m_uuid = uuid; 0513 const auto clientResources = d->resourceMap(); 0514 for (const auto &resource : clientResources) { 0515 d->sendUuid(resource); 0516 d->sendDone(resource); 0517 } 0518 } 0519 } 0520 0521 void OutputDeviceV2Interface::updateCapabilities() 0522 { 0523 const uint32_t cap = kwinCapabilitiesToOutputDeviceCapabilities(d->m_handle->capabilities()); 0524 if (d->m_capabilities != cap) { 0525 d->m_capabilities = cap; 0526 const auto clientResources = d->resourceMap(); 0527 for (const auto &resource : clientResources) { 0528 d->sendCapabilities(resource); 0529 d->sendDone(resource); 0530 } 0531 } 0532 } 0533 0534 void OutputDeviceV2Interface::updateOverscan() 0535 { 0536 const uint32_t overscan = d->m_handle->overscan(); 0537 if (d->m_overscan != overscan) { 0538 d->m_overscan = overscan; 0539 const auto clientResources = d->resourceMap(); 0540 for (const auto &resource : clientResources) { 0541 d->sendOverscan(resource); 0542 d->sendDone(resource); 0543 } 0544 } 0545 } 0546 0547 void OutputDeviceV2Interface::updateVrrPolicy() 0548 { 0549 const auto policy = kwinVrrPolicyToOutputDeviceVrrPolicy(d->m_handle->vrrPolicy()); 0550 if (d->m_vrrPolicy != policy) { 0551 d->m_vrrPolicy = policy; 0552 const auto clientResources = d->resourceMap(); 0553 for (const auto &resource : clientResources) { 0554 d->sendVrrPolicy(resource); 0555 d->sendDone(resource); 0556 } 0557 } 0558 } 0559 0560 void OutputDeviceV2Interface::updateRgbRange() 0561 { 0562 const auto rgbRange = kwinRgbRangeToOutputDeviceRgbRange(d->m_handle->rgbRange()); 0563 if (d->m_rgbRange != rgbRange) { 0564 d->m_rgbRange = rgbRange; 0565 const auto clientResources = d->resourceMap(); 0566 for (const auto &resource : clientResources) { 0567 d->sendRgbRange(resource); 0568 d->sendDone(resource); 0569 } 0570 } 0571 } 0572 0573 OutputDeviceV2Interface *OutputDeviceV2Interface::get(wl_resource *native) 0574 { 0575 if (auto devicePrivate = resource_cast<OutputDeviceV2InterfacePrivate *>(native); devicePrivate && !devicePrivate->isGlobalRemoved()) { 0576 return devicePrivate->q; 0577 } 0578 return nullptr; 0579 } 0580 0581 OutputDeviceModeV2InterfacePrivate::OutputDeviceModeV2InterfacePrivate(OutputDeviceModeV2Interface *q, std::shared_ptr<KWin::OutputMode> handle) 0582 : QtWaylandServer::kde_output_device_mode_v2() 0583 , q(q) 0584 , m_handle(handle) 0585 , m_size(handle->size()) 0586 , m_refreshRate(handle->refreshRate()) 0587 , m_preferred(handle->flags() & OutputMode::Flag::Preferred) 0588 { 0589 } 0590 0591 OutputDeviceModeV2Interface::OutputDeviceModeV2Interface(std::shared_ptr<KWin::OutputMode> handle, QObject *parent) 0592 : QObject(parent) 0593 , d(new OutputDeviceModeV2InterfacePrivate(this, handle)) 0594 { 0595 } 0596 0597 OutputDeviceModeV2Interface::~OutputDeviceModeV2Interface() = default; 0598 0599 OutputDeviceModeV2InterfacePrivate::~OutputDeviceModeV2InterfacePrivate() 0600 { 0601 const auto map = resourceMap(); 0602 for (Resource *resource : map) { 0603 send_removed(resource->handle); 0604 } 0605 } 0606 0607 OutputDeviceModeV2InterfacePrivate::Resource *OutputDeviceModeV2InterfacePrivate::createResource(OutputDeviceV2InterfacePrivate::Resource *output) 0608 { 0609 const auto modeResource = static_cast<ModeResource *>(add(output->client(), output->version())); 0610 modeResource->output = output; 0611 return modeResource; 0612 } 0613 0614 OutputDeviceModeV2InterfacePrivate::Resource *OutputDeviceModeV2InterfacePrivate::findResource(OutputDeviceV2InterfacePrivate::Resource *output) const 0615 { 0616 const auto resources = resourceMap(); 0617 for (const auto &resource : resources) { 0618 auto modeResource = static_cast<ModeResource *>(resource); 0619 if (modeResource->output == output) { 0620 return resource; 0621 } 0622 } 0623 return nullptr; 0624 } 0625 0626 OutputDeviceModeV2InterfacePrivate::Resource *OutputDeviceModeV2InterfacePrivate::kde_output_device_mode_v2_allocate() 0627 { 0628 return new ModeResource; 0629 } 0630 0631 std::weak_ptr<KWin::OutputMode> OutputDeviceModeV2Interface::handle() const 0632 { 0633 return d->m_handle; 0634 } 0635 0636 void OutputDeviceModeV2InterfacePrivate::bindResource(wl_resource *resource) 0637 { 0638 send_size(resource, m_size.width(), m_size.height()); 0639 send_refresh(resource, m_refreshRate); 0640 0641 if (m_preferred) { 0642 send_preferred(resource); 0643 } 0644 } 0645 0646 OutputDeviceModeV2Interface *OutputDeviceModeV2Interface::get(wl_resource *native) 0647 { 0648 if (auto devicePrivate = resource_cast<OutputDeviceModeV2InterfacePrivate *>(native)) { 0649 return devicePrivate->q; 0650 } 0651 return nullptr; 0652 } 0653 0654 }