File indexing completed on 2024-04-28 05:36:54
0001 /* 0002 * SPDX-FileCopyrightText: 2018 Red Hat Inc 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 * 0006 * SPDX-FileCopyrightText: 2018 Jan Grulich <jgrulich@redhat.com> 0007 * SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0008 */ 0009 0010 #include "waylandintegration.h" 0011 #include "qwayland-wayland.h" 0012 #include "screencast.h" 0013 #include "screencasting.h" 0014 #include "waylandintegration_debug.h" 0015 #include "waylandintegration_p.h" 0016 0017 #include <QDBusMetaType> 0018 #include <QGuiApplication> 0019 0020 #include <KNotification> 0021 #include <QEventLoop> 0022 #include <QImage> 0023 #include <QMenu> 0024 #include <QScreen> 0025 #include <QThread> 0026 #include <QTimer> 0027 #include <QWaylandClientExtensionTemplate> 0028 0029 #include <KLocalizedString> 0030 0031 // KWayland 0032 #include <KWayland/Client/connection_thread.h> 0033 #include <KWayland/Client/event_queue.h> 0034 #include <KWayland/Client/plasmawindowmanagement.h> 0035 #include <KWayland/Client/plasmawindowmodel.h> 0036 #include <KWayland/Client/registry.h> 0037 #include <KWayland/Client/surface.h> 0038 #include <KWayland/Client/xdgforeign.h> 0039 0040 // system 0041 #include <fcntl.h> 0042 #include <linux/input-event-codes.h> 0043 #include <sys/mman.h> 0044 #include <unistd.h> 0045 #include <xkbcommon/xkbcommon.h> 0046 0047 #include <KWayland/Client/fakeinput.h> 0048 #include <qpa/qplatformnativeinterface.h> 0049 #include <waylandintegration_debug.h> 0050 0051 Q_GLOBAL_STATIC(WaylandIntegration::WaylandIntegrationPrivate, globalWaylandIntegration) 0052 0053 namespace WaylandIntegration 0054 { 0055 QDebug operator<<(QDebug dbg, const Stream &c) 0056 { 0057 dbg.nospace() << "Stream(" << c.map << ", " << c.nodeId << ")"; 0058 return dbg.space(); 0059 } 0060 0061 const QDBusArgument &operator>>(const QDBusArgument &arg, Stream &stream) 0062 { 0063 arg.beginStructure(); 0064 arg >> stream.nodeId; 0065 0066 arg.beginMap(); 0067 while (!arg.atEnd()) { 0068 QString key; 0069 QVariant map; 0070 arg.beginMapEntry(); 0071 arg >> key >> map; 0072 arg.endMapEntry(); 0073 stream.map.insert(key, map); 0074 } 0075 arg.endMap(); 0076 arg.endStructure(); 0077 0078 return arg; 0079 } 0080 0081 const QDBusArgument &operator<<(QDBusArgument &arg, const Stream &stream) 0082 { 0083 arg.beginStructure(); 0084 arg << stream.nodeId; 0085 arg << stream.map; 0086 arg.endStructure(); 0087 0088 return arg; 0089 } 0090 0091 } 0092 0093 void WaylandIntegration::init() 0094 { 0095 globalWaylandIntegration->initWayland(); 0096 } 0097 0098 bool WaylandIntegration::isStreamingEnabled() 0099 { 0100 return globalWaylandIntegration->isStreamingEnabled(); 0101 } 0102 0103 bool WaylandIntegration::isStreamingAvailable() 0104 { 0105 return globalWaylandIntegration->isStreamingAvailable(); 0106 } 0107 0108 void WaylandIntegration::acquireStreamingInput(bool acquire) 0109 { 0110 globalWaylandIntegration->acquireStreamingInput(acquire); 0111 } 0112 0113 WaylandIntegration::Stream WaylandIntegration::startStreamingOutput(QScreen *screen, Screencasting::CursorMode mode) 0114 { 0115 return globalWaylandIntegration->startStreamingOutput(screen, mode); 0116 } 0117 0118 WaylandIntegration::Stream WaylandIntegration::startStreamingWorkspace(Screencasting::CursorMode mode) 0119 { 0120 return globalWaylandIntegration->startStreamingWorkspace(mode); 0121 } 0122 0123 WaylandIntegration::Stream WaylandIntegration::startStreamingRegion(const QRect ®ion, Screencasting::CursorMode mode) 0124 { 0125 return globalWaylandIntegration->startStreamingRegion(region, mode); 0126 } 0127 0128 WaylandIntegration::Stream WaylandIntegration::startStreamingVirtual(const QString &name, const QSize &size, Screencasting::CursorMode mode) 0129 { 0130 return globalWaylandIntegration->startStreamingVirtualOutput(name, size, mode); 0131 } 0132 0133 WaylandIntegration::Stream WaylandIntegration::startStreamingWindow(const QMap<int, QVariant> &win, Screencasting::CursorMode mode) 0134 { 0135 return globalWaylandIntegration->startStreamingWindow(win, mode); 0136 } 0137 0138 void WaylandIntegration::stopStreaming(uint node) 0139 { 0140 globalWaylandIntegration->stopStreaming(node); 0141 } 0142 0143 void WaylandIntegration::requestPointerButtonPress(quint32 linuxButton) 0144 { 0145 globalWaylandIntegration->requestPointerButtonPress(linuxButton); 0146 } 0147 0148 void WaylandIntegration::requestPointerButtonRelease(quint32 linuxButton) 0149 { 0150 globalWaylandIntegration->requestPointerButtonRelease(linuxButton); 0151 } 0152 0153 void WaylandIntegration::requestPointerMotion(const QSizeF &delta) 0154 { 0155 globalWaylandIntegration->requestPointerMotion(delta); 0156 } 0157 0158 void WaylandIntegration::requestPointerMotionAbsolute(uint stream, const QPointF &pos) 0159 { 0160 globalWaylandIntegration->requestPointerMotionAbsolute(stream, pos); 0161 } 0162 0163 void WaylandIntegration::requestPointerAxisDiscrete(Qt::Orientation axis, qreal delta) 0164 { 0165 globalWaylandIntegration->requestPointerAxisDiscrete(axis, delta); 0166 } 0167 0168 void WaylandIntegration::requestPointerAxis(qreal x, qreal y) 0169 { 0170 globalWaylandIntegration->requestPointerAxis(x, y); 0171 } 0172 0173 void WaylandIntegration::requestKeyboardKeycode(int keycode, bool state) 0174 { 0175 globalWaylandIntegration->requestKeyboardKeycode(keycode, state); 0176 } 0177 0178 void WaylandIntegration::requestKeyboardKeysym(int keysym, bool state) 0179 { 0180 globalWaylandIntegration->requestKeyboardKeysym(keysym, state); 0181 } 0182 0183 void WaylandIntegration::requestTouchDown(quint32 touchPoint, const QPointF &pos) 0184 { 0185 globalWaylandIntegration->requestTouchDown(touchPoint, pos); 0186 } 0187 0188 void WaylandIntegration::requestTouchMotion(quint32 touchPoint, const QPointF &pos) 0189 { 0190 globalWaylandIntegration->requestTouchMotion(touchPoint, pos); 0191 } 0192 0193 void WaylandIntegration::requestTouchUp(quint32 touchPoint) 0194 { 0195 globalWaylandIntegration->requestTouchUp(touchPoint); 0196 } 0197 0198 void WaylandIntegration::setParentWindow(QWindow *window, const QString &parentWindow) 0199 { 0200 globalWaylandIntegration->setParentWindow(window, parentWindow); 0201 } 0202 0203 KWayland::Client::PlasmaWindowManagement *WaylandIntegration::plasmaWindowManagement() 0204 { 0205 return globalWaylandIntegration->plasmaWindowManagement(); 0206 } 0207 0208 WaylandIntegration::WaylandIntegration *WaylandIntegration::waylandIntegration() 0209 { 0210 return globalWaylandIntegration; 0211 } 0212 0213 WaylandIntegration::WaylandIntegrationPrivate::WaylandIntegrationPrivate() 0214 : WaylandIntegration() 0215 , m_registryInitialized(false) 0216 , m_registry(nullptr) 0217 , m_fakeInput(nullptr) 0218 , m_screencasting(nullptr) 0219 { 0220 qDBusRegisterMetaType<Stream>(); 0221 qDBusRegisterMetaType<Streams>(); 0222 } 0223 0224 WaylandIntegration::WaylandIntegrationPrivate::~WaylandIntegrationPrivate() = default; 0225 0226 bool WaylandIntegration::WaylandIntegrationPrivate::isStreamingEnabled() const 0227 { 0228 return !m_streams.isEmpty(); 0229 } 0230 0231 bool WaylandIntegration::WaylandIntegrationPrivate::isStreamingAvailable() const 0232 { 0233 return m_screencasting; 0234 } 0235 0236 void WaylandIntegration::WaylandIntegrationPrivate::acquireStreamingInput(bool acquire) 0237 { 0238 if (acquire) { 0239 authenticate(); 0240 ++m_streamInput; 0241 } else { 0242 Q_ASSERT(m_streamInput > 0); 0243 --m_streamInput; 0244 } 0245 } 0246 0247 WaylandIntegration::Stream WaylandIntegration::WaylandIntegrationPrivate::startStreamingWindow(const QMap<int, QVariant> &win, 0248 Screencasting::CursorMode cursorMode) 0249 { 0250 auto uuid = win[KWayland::Client::PlasmaWindowModel::Uuid].toString(); 0251 return startStreaming(m_screencasting->createWindowStream(uuid, cursorMode), {{QLatin1String("source_type"), static_cast<uint>(ScreenCastPortal::Window)}}); 0252 } 0253 0254 WaylandIntegration::Stream WaylandIntegration::WaylandIntegrationPrivate::startStreamingOutput(QScreen *screen, Screencasting::CursorMode mode) 0255 { 0256 auto stream = m_screencasting->createOutputStream(screen, mode); 0257 if (!stream) { 0258 qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Cannot stream, output not found" << screen->name(); 0259 auto notification = new KNotification(QStringLiteral("screencastfailure"), KNotification::CloseOnTimeout); 0260 notification->setTitle(i18n("Failed to start screencasting")); 0261 notification->setIconName(QStringLiteral("dialog-error")); 0262 notification->sendEvent(); 0263 return {}; 0264 } 0265 0266 return startStreaming(stream, 0267 { 0268 {QLatin1String("size"), screen->size()}, 0269 {QLatin1String("source_type"), static_cast<uint>(ScreenCastPortal::Monitor)}, 0270 }); 0271 } 0272 0273 WaylandIntegration::Stream WaylandIntegration::WaylandIntegrationPrivate::startStreamingWorkspace(Screencasting::CursorMode mode) 0274 { 0275 QRect workspace; 0276 const auto screens = qGuiApp->screens(); 0277 for (QScreen *screen : screens) { 0278 workspace |= screen->geometry(); 0279 } 0280 return startStreaming(m_screencasting->createRegionStream(workspace, 1, mode), 0281 { 0282 {QLatin1String("size"), workspace.size()}, 0283 {QLatin1String("source_type"), static_cast<uint>(ScreenCastPortal::Monitor)}, 0284 }); 0285 } 0286 0287 WaylandIntegration::Stream WaylandIntegration::WaylandIntegrationPrivate::startStreamingRegion(const QRect region, Screencasting::CursorMode mode) 0288 { 0289 return startStreaming(m_screencasting->createRegionStream(region, 1, mode), 0290 { 0291 {QLatin1String("size"), region.size()}, 0292 {QLatin1String("source_type"), static_cast<uint>(ScreenCastPortal::Monitor)}, 0293 }); 0294 } 0295 0296 WaylandIntegration::Stream 0297 WaylandIntegration::WaylandIntegrationPrivate::startStreamingVirtualOutput(const QString &name, const QSize &size, Screencasting::CursorMode mode) 0298 { 0299 return startStreaming(m_screencasting->createVirtualOutputStream(name, size, 1, mode), 0300 { 0301 {QLatin1String("size"), size}, 0302 {QLatin1String("source_type"), static_cast<uint>(ScreenCastPortal::Virtual)}, 0303 }); 0304 } 0305 0306 WaylandIntegration::Stream WaylandIntegration::WaylandIntegrationPrivate::startStreaming(ScreencastingStream *stream, const QVariantMap &streamOptions) 0307 { 0308 QEventLoop loop; 0309 Stream ret; 0310 0311 connect(stream, &ScreencastingStream::failed, this, [&](const QString &error) { 0312 qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "failed to start streaming" << stream << error; 0313 0314 KNotification *notification = new KNotification(QStringLiteral("screencastfailure"), KNotification::CloseOnTimeout); 0315 notification->setTitle(i18n("Failed to start screencasting")); 0316 notification->setText(error); 0317 notification->setIconName(QStringLiteral("dialog-error")); 0318 notification->sendEvent(); 0319 0320 loop.quit(); 0321 }); 0322 connect(stream, &ScreencastingStream::created, this, [&](uint32_t nodeid) { 0323 ret.stream = stream; 0324 ret.nodeId = nodeid; 0325 ret.map = streamOptions; 0326 m_streams.append(ret); 0327 0328 connect(stream, &ScreencastingStream::closed, this, [this, nodeid] { 0329 stopStreaming(nodeid); 0330 }); 0331 Q_ASSERT(ret.isValid()); 0332 0333 loop.quit(); 0334 }); 0335 QTimer::singleShot(3000, &loop, &QEventLoop::quit); 0336 loop.exec(); 0337 return ret; 0338 } 0339 0340 void WaylandIntegration::Stream::close() 0341 { 0342 stream->deleteLater(); 0343 } 0344 0345 void WaylandIntegration::WaylandIntegrationPrivate::stopStreaming(uint32_t nodeid) 0346 { 0347 for (auto it = m_streams.begin(), itEnd = m_streams.end(); it != itEnd; ++it) { 0348 if (it->nodeId == nodeid) { 0349 it->close(); 0350 m_streams.erase(it); 0351 break; 0352 } 0353 } 0354 } 0355 0356 void WaylandIntegration::WaylandIntegrationPrivate::requestPointerButtonPress(quint32 linuxButton) 0357 { 0358 if (m_streamInput && m_fakeInput) { 0359 m_fakeInput->requestPointerButtonPress(linuxButton); 0360 } 0361 } 0362 0363 void WaylandIntegration::WaylandIntegrationPrivate::requestPointerButtonRelease(quint32 linuxButton) 0364 { 0365 if (m_streamInput && m_fakeInput) { 0366 m_fakeInput->requestPointerButtonRelease(linuxButton); 0367 } 0368 } 0369 0370 void WaylandIntegration::WaylandIntegrationPrivate::requestPointerMotion(const QSizeF &delta) 0371 { 0372 if (m_streamInput && m_fakeInput) { 0373 m_fakeInput->requestPointerMove(delta); 0374 } 0375 } 0376 0377 void WaylandIntegration::WaylandIntegrationPrivate::requestPointerMotionAbsolute(uint streamNodeId, const QPointF &pos) 0378 { 0379 if (m_streamInput && m_fakeInput) { 0380 for (auto stream : std::as_const(m_streams)) { 0381 if (stream.nodeId == streamNodeId) { 0382 m_fakeInput->requestPointerMoveAbsolute(pos + stream.stream->geometry().topLeft()); 0383 return; 0384 } 0385 } 0386 // If no stream is found, just send it as absolute coordinates relative to the workspace. 0387 m_fakeInput->requestPointerMoveAbsolute(pos); 0388 } 0389 } 0390 0391 void WaylandIntegration::WaylandIntegrationPrivate::requestPointerAxisDiscrete(Qt::Orientation axis, qreal delta) 0392 { 0393 if (m_streamInput && m_fakeInput) { 0394 m_fakeInput->requestPointerAxis(axis, delta); 0395 } 0396 } 0397 void WaylandIntegration::WaylandIntegrationPrivate::requestPointerAxis(qreal x, qreal y) 0398 { 0399 if (m_streamInput && m_fakeInput) { 0400 if (x != 0) { 0401 m_fakeInput->requestPointerAxis(Qt::Horizontal, x); 0402 } 0403 if (y != 0) { 0404 m_fakeInput->requestPointerAxis(Qt::Vertical, -y); 0405 } 0406 } 0407 } 0408 0409 void WaylandIntegration::WaylandIntegrationPrivate::requestKeyboardKeycode(int keycode, bool state) 0410 { 0411 if (m_streamInput && m_fakeInput) { 0412 if (state) { 0413 m_fakeInput->requestKeyboardKeyPress(keycode); 0414 } else { 0415 m_fakeInput->requestKeyboardKeyRelease(keycode); 0416 } 0417 } 0418 } 0419 0420 namespace 0421 { 0422 struct XKBStateDeleter { 0423 void operator()(struct xkb_state *state) const 0424 { 0425 return xkb_state_unref(state); 0426 } 0427 }; 0428 struct XKBKeymapDeleter { 0429 void operator()(struct xkb_keymap *keymap) const 0430 { 0431 return xkb_keymap_unref(keymap); 0432 } 0433 }; 0434 struct XKBContextDeleter { 0435 void operator()(struct xkb_context *context) const 0436 { 0437 return xkb_context_unref(context); 0438 } 0439 }; 0440 using ScopedXKBState = std::unique_ptr<struct xkb_state, XKBStateDeleter>; 0441 using ScopedXKBKeymap = std::unique_ptr<struct xkb_keymap, XKBKeymapDeleter>; 0442 using ScopedXKBContext = std::unique_ptr<struct xkb_context, XKBContextDeleter>; 0443 } 0444 class Xkb : public QtWayland::wl_keyboard 0445 { 0446 public: 0447 struct Code { 0448 const uint32_t level; 0449 const uint32_t code; 0450 }; 0451 std::optional<Code> keycodeFromKeysym(xkb_keysym_t keysym) 0452 { 0453 /* The offset between KEY_* numbering, and keycodes in the XKB evdev 0454 * dataset. */ 0455 static const uint EVDEV_OFFSET = 8; 0456 0457 auto layout = xkb_state_serialize_layout(m_state.get(), XKB_STATE_LAYOUT_EFFECTIVE); 0458 const xkb_keycode_t max = xkb_keymap_max_keycode(m_keymap.get()); 0459 for (xkb_keycode_t keycode = xkb_keymap_min_keycode(m_keymap.get()); keycode < max; keycode++) { 0460 uint levelCount = xkb_keymap_num_levels_for_key(m_keymap.get(), keycode, layout); 0461 for (uint currentLevel = 0; currentLevel < levelCount; currentLevel++) { 0462 const xkb_keysym_t *syms; 0463 uint num_syms = xkb_keymap_key_get_syms_by_level(m_keymap.get(), keycode, layout, currentLevel, &syms); 0464 for (uint sym = 0; sym < num_syms; sym++) { 0465 if (syms[sym] == keysym) { 0466 return Code{currentLevel, keycode - EVDEV_OFFSET}; 0467 } 0468 } 0469 } 0470 } 0471 return {}; 0472 } 0473 0474 static Xkb *self() 0475 { 0476 static Xkb self; 0477 return &self; 0478 } 0479 0480 private: 0481 Xkb() 0482 { 0483 m_ctx.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS)); 0484 if (!m_ctx) { 0485 qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to create xkb context"; 0486 return; 0487 } 0488 m_keymap.reset(xkb_keymap_new_from_names(m_ctx.get(), nullptr, XKB_KEYMAP_COMPILE_NO_FLAGS)); 0489 if (!m_keymap) { 0490 qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to create the keymap"; 0491 return; 0492 } 0493 m_state.reset(xkb_state_new(m_keymap.get())); 0494 if (!m_state) { 0495 qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to create the xkb state"; 0496 return; 0497 } 0498 0499 QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface(); 0500 auto seat = static_cast<wl_seat *>(nativeInterface->nativeResourceForIntegration("wl_seat")); 0501 init(wl_seat_get_keyboard(seat)); 0502 } 0503 0504 void keyboard_keymap(uint32_t format, int32_t fd, uint32_t size) override 0505 { 0506 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { 0507 qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "unknown keymap format:" << format; 0508 close(fd); 0509 return; 0510 } 0511 0512 char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0)); 0513 if (map_str == MAP_FAILED) { 0514 close(fd); 0515 return; 0516 } 0517 0518 m_keymap.reset(xkb_keymap_new_from_string(m_ctx.get(), map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS)); 0519 munmap(map_str, size); 0520 close(fd); 0521 0522 if (m_keymap) 0523 m_state.reset(xkb_state_new(m_keymap.get())); 0524 else 0525 m_state.reset(nullptr); 0526 } 0527 0528 ScopedXKBContext m_ctx; 0529 ScopedXKBKeymap m_keymap; 0530 ScopedXKBState m_state; 0531 }; 0532 0533 void WaylandIntegration::WaylandIntegrationPrivate::requestKeyboardKeysym(int keysym, bool state) 0534 { 0535 if (m_streamInput && m_fakeInput) { 0536 auto keycode = Xkb::self()->keycodeFromKeysym(keysym); 0537 if (!keycode) { 0538 qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to convert keysym into keycode" << keysym; 0539 return; 0540 } 0541 0542 auto sendKey = [this, state](int keycode) { 0543 if (state) { 0544 m_fakeInput->requestKeyboardKeyPress(keycode); 0545 } else { 0546 m_fakeInput->requestKeyboardKeyRelease(keycode); 0547 } 0548 }; 0549 switch (keycode->level) { 0550 case 0: 0551 break; 0552 case 1: 0553 sendKey(KEY_LEFTSHIFT); 0554 break; 0555 case 2: 0556 sendKey(KEY_RIGHTALT); 0557 break; 0558 default: 0559 qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Unsupported key level" << keycode->level; 0560 break; 0561 } 0562 sendKey(keycode->code); 0563 } 0564 } 0565 0566 void WaylandIntegration::WaylandIntegrationPrivate::requestTouchDown(quint32 touchPoint, const QPointF &pos) 0567 { 0568 if (m_streamInput && m_fakeInput) { 0569 m_fakeInput->requestTouchDown(touchPoint, pos); 0570 } 0571 } 0572 0573 void WaylandIntegration::WaylandIntegrationPrivate::requestTouchMotion(quint32 touchPoint, const QPointF &pos) 0574 { 0575 if (m_streamInput && m_fakeInput) { 0576 m_fakeInput->requestTouchMotion(touchPoint, pos); 0577 } 0578 } 0579 0580 void WaylandIntegration::WaylandIntegrationPrivate::requestTouchUp(quint32 touchPoint) 0581 { 0582 if (m_streamInput && m_fakeInput) { 0583 m_fakeInput->requestTouchUp(touchPoint); 0584 } 0585 } 0586 0587 static const char *windowParentHandlePropertyName = "waylandintegration-parentHandle"; 0588 void WaylandIntegration::WaylandIntegrationPrivate::setParentWindow(QWindow *window, const QString &parentHandle) 0589 { 0590 if (!m_xdgImporter) { 0591 return; 0592 } 0593 0594 if (window->isVisible()) { 0595 auto importedParent = m_xdgImporter->importTopLevel(parentHandle, window); 0596 auto surface = KWayland::Client::Surface::fromWindow(window); 0597 importedParent->setParentOf(surface); 0598 } 0599 0600 window->setProperty(windowParentHandlePropertyName, parentHandle); 0601 window->installEventFilter(this); 0602 } 0603 0604 bool WaylandIntegration::WaylandIntegrationPrivate::eventFilter(QObject *watched, QEvent *event) 0605 { 0606 const bool ret = WaylandIntegration::WaylandIntegration::eventFilter(watched, event); 0607 QWindow *window = static_cast<QWindow *>(watched); 0608 if (event->type() == QEvent::Expose && window->isExposed()) { 0609 const QString parentHandle = window->property(windowParentHandlePropertyName).toString(); 0610 auto importedParent = m_xdgImporter->importTopLevel(parentHandle, window); 0611 importedParent->setParentOf(KWayland::Client::Surface::fromWindow(window)); 0612 } 0613 return ret; 0614 } 0615 0616 void WaylandIntegration::WaylandIntegrationPrivate::authenticate() 0617 { 0618 if (!m_waylandAuthenticationRequested) { 0619 m_fakeInput->authenticate(QStringLiteral("xdg-desktop-portals-kde"), i18n("Remote desktop")); 0620 m_waylandAuthenticationRequested = true; 0621 } 0622 } 0623 0624 KWayland::Client::PlasmaWindowManagement *WaylandIntegration::WaylandIntegrationPrivate::plasmaWindowManagement() 0625 { 0626 return m_windowManagement; 0627 } 0628 0629 void WaylandIntegration::WaylandIntegrationPrivate::initWayland() 0630 { 0631 auto connection = KWayland::Client::ConnectionThread::fromApplication(QGuiApplication::instance()); 0632 0633 if (!connection) { 0634 return; 0635 } 0636 0637 m_registry = new KWayland::Client::Registry(this); 0638 0639 connect(m_registry, &KWayland::Client::Registry::fakeInputAnnounced, this, [this](quint32 name, quint32 version) { 0640 m_fakeInput = m_registry->createFakeInput(name, version, this); 0641 }); 0642 0643 connect(m_registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this](const QByteArray &interfaceName, quint32 name, quint32 version) { 0644 if (interfaceName != "zkde_screencast_unstable_v1") 0645 return; 0646 m_screencasting = new Screencasting(m_registry, name, version, this); 0647 }); 0648 connect(m_registry, &KWayland::Client::Registry::plasmaWindowManagementAnnounced, this, [this](quint32 name, quint32 version) { 0649 m_windowManagement = m_registry->createPlasmaWindowManagement(name, version, this); 0650 Q_EMIT waylandIntegration()->plasmaWindowManagementInitialized(); 0651 }); 0652 connect(m_registry, &KWayland::Client::Registry::importerUnstableV2Announced, this, [this](quint32 name, quint32 version) { 0653 m_xdgImporter = m_registry->createXdgImporter(name, std::min(version, quint32(1)), this); 0654 }); 0655 connect(m_registry, &KWayland::Client::Registry::interfacesAnnounced, this, [this] { 0656 m_registryInitialized = true; 0657 qCDebug(XdgDesktopPortalKdeWaylandIntegration) << "Registry initialized"; 0658 }); 0659 0660 m_registry->create(connection); 0661 m_registry->setup(); 0662 }