Changeset View
Changeset View
Standalone View
Standalone View
src/waylandintegration.cpp
Show All 15 Lines | |||||
16 | * | 16 | * | ||
17 | * Authors: | 17 | * Authors: | ||
18 | * Jan Grulich <jgrulich@redhat.com> | 18 | * Jan Grulich <jgrulich@redhat.com> | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "waylandintegration.h" | 21 | #include "waylandintegration.h" | ||
22 | #include "waylandintegration_p.h" | 22 | #include "waylandintegration_p.h" | ||
23 | 23 | | |||
24 | | ||||
25 | #include <QDBusArgument> | 24 | #include <QDBusArgument> | ||
26 | #include <QDBusMetaType> | 25 | #include <QDBusMetaType> | ||
27 | 26 | | |||
28 | #include <QEventLoop> | 27 | #include <QEventLoop> | ||
29 | #include <QLoggingCategory> | 28 | #include <QLoggingCategory> | ||
30 | #include <QThread> | 29 | #include <QThread> | ||
31 | #include <QTimer> | 30 | #include <QTimer> | ||
31 | #include <KNotification> | ||||
32 | 32 | | |||
33 | #include <QImage> | 33 | #include <QImage> | ||
34 | 34 | | |||
35 | #include <KLocalizedString> | 35 | #include <KLocalizedString> | ||
36 | 36 | | |||
37 | // KWayland | 37 | // KWayland | ||
38 | #include <KWayland/Client/connection_thread.h> | 38 | #include <KWayland/Client/connection_thread.h> | ||
39 | #include <KWayland/Client/event_queue.h> | 39 | #include <KWayland/Client/event_queue.h> | ||
40 | #include <KWayland/Client/registry.h> | 40 | #include <KWayland/Client/registry.h> | ||
41 | #include <KWayland/Client/plasmawindowmanagement.h> | 41 | #include <KWayland/Client/plasmawindowmanagement.h> | ||
42 | 42 | | |||
43 | // system | 43 | // system | ||
44 | #include <fcntl.h> | 44 | #include <fcntl.h> | ||
45 | #include <unistd.h> | 45 | #include <unistd.h> | ||
46 | 46 | | |||
47 | #if HAVE_PIPEWIRE_SUPPORT | 47 | #if HAVE_PIPEWIRE_SUPPORT | ||
48 | #include "screencaststream.h" | | |||
49 | | ||||
50 | #include <KWayland/Client/fakeinput.h> | 48 | #include <KWayland/Client/fakeinput.h> | ||
51 | #include <KWayland/Client/output.h> | 49 | #include <KWayland/Client/output.h> | ||
52 | #include <KWayland/Client/remote_access.h> | 50 | #include <KWayland/Client/screencasting.h> | ||
53 | #endif | 51 | #endif | ||
54 | 52 | | |||
55 | Q_LOGGING_CATEGORY(XdgDesktopPortalKdeWaylandIntegration, "xdp-kde-wayland-integration") | 53 | Q_LOGGING_CATEGORY(XdgDesktopPortalKdeWaylandIntegration, "xdp-kde-wayland-integration") | ||
56 | 54 | | |||
57 | Q_GLOBAL_STATIC(WaylandIntegration::WaylandIntegrationPrivate, globalWaylandIntegration) | 55 | Q_GLOBAL_STATIC(WaylandIntegration::WaylandIntegrationPrivate, globalWaylandIntegration) | ||
58 | 56 | | |||
59 | void WaylandIntegration::init() | 57 | void WaylandIntegration::init() | ||
60 | { | 58 | { | ||
Show All 19 Lines | 77 | { | |||
80 | return globalWaylandIntegration->isStreamingEnabled(); | 78 | return globalWaylandIntegration->isStreamingEnabled(); | ||
81 | } | 79 | } | ||
82 | 80 | | |||
83 | void WaylandIntegration::startStreamingInput() | 81 | void WaylandIntegration::startStreamingInput() | ||
84 | { | 82 | { | ||
85 | globalWaylandIntegration->startStreamingInput(); | 83 | globalWaylandIntegration->startStreamingInput(); | ||
86 | } | 84 | } | ||
87 | 85 | | |||
88 | bool WaylandIntegration::startStreaming(quint32 outputName) | 86 | bool WaylandIntegration::startStreaming(const KWayland::Client::ScreencastingSource &source) | ||
89 | { | 87 | { | ||
90 | return globalWaylandIntegration->startStreaming(outputName); | 88 | return globalWaylandIntegration->startStreaming(source); | ||
91 | } | 89 | } | ||
92 | 90 | | |||
93 | void WaylandIntegration::stopStreaming() | 91 | void WaylandIntegration::stopAllStreaming() | ||
94 | { | 92 | { | ||
95 | globalWaylandIntegration->stopStreaming(); | 93 | globalWaylandIntegration->stopAllStreaming(); | ||
96 | } | 94 | } | ||
97 | 95 | | |||
98 | void WaylandIntegration::requestPointerButtonPress(quint32 linuxButton) | 96 | void WaylandIntegration::requestPointerButtonPress(quint32 linuxButton) | ||
99 | { | 97 | { | ||
100 | globalWaylandIntegration->requestPointerButtonPress(linuxButton); | 98 | globalWaylandIntegration->requestPointerButtonPress(linuxButton); | ||
101 | } | 99 | } | ||
102 | 100 | | |||
103 | void WaylandIntegration::requestPointerButtonRelease(quint32 linuxButton) | 101 | void WaylandIntegration::requestPointerButtonRelease(quint32 linuxButton) | ||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Line(s) | |||||
166 | void WaylandIntegration::WaylandOutput::setOutputType(const QString &type) | 164 | void WaylandIntegration::WaylandOutput::setOutputType(const QString &type) | ||
167 | { | 165 | { | ||
168 | const auto embedded = { QLatin1String("LVDS"), | 166 | const auto embedded = { QLatin1String("LVDS"), | ||
169 | QLatin1String("IDP"), | 167 | QLatin1String("IDP"), | ||
170 | QLatin1String("EDP"), | 168 | QLatin1String("EDP"), | ||
171 | QLatin1String("LCD") }; | 169 | QLatin1String("LCD") }; | ||
172 | 170 | | |||
173 | for (const QLatin1String &pre : embedded) { | 171 | for (const QLatin1String &pre : embedded) { | ||
174 | if (type.toUpper().startsWith(pre)) { | 172 | if (type.startsWith(pre, Qt::CaseInsensitive)) { | ||
175 | m_outputType = OutputType::Laptop; | 173 | m_outputType = OutputType::Laptop; | ||
176 | return; | 174 | return; | ||
177 | } | 175 | } | ||
178 | } | 176 | } | ||
179 | 177 | | |||
180 | if (type.contains(QLatin1String("VGA")) || type.contains(QLatin1String("DVI")) || type.contains(QLatin1String("HDMI")) || type.contains(QLatin1String("Panel")) || | 178 | if (type.contains(QLatin1String("VGA")) || type.contains(QLatin1String("DVI")) || type.contains(QLatin1String("HDMI")) || type.contains(QLatin1String("Panel")) || | ||
181 | type.contains(QLatin1String("DisplayPort")) || type.startsWith(QLatin1String("DP")) || type.contains(QLatin1String("unknown"))) { | 179 | type.contains(QLatin1String("DisplayPort")) || type.startsWith(QLatin1String("DP")) || type.contains(QLatin1String("unknown"))) { | ||
182 | m_outputType = OutputType::Monitor; | 180 | m_outputType = OutputType::Monitor; | ||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Line(s) | |||||
234 | WaylandIntegration::WaylandIntegrationPrivate::WaylandIntegrationPrivate() | 232 | WaylandIntegration::WaylandIntegrationPrivate::WaylandIntegrationPrivate() | ||
235 | : WaylandIntegration() | 233 | : WaylandIntegration() | ||
236 | , m_registryInitialized(false) | 234 | , m_registryInitialized(false) | ||
237 | , m_connection(nullptr) | 235 | , m_connection(nullptr) | ||
238 | , m_queue(nullptr) | 236 | , m_queue(nullptr) | ||
239 | , m_registry(nullptr) | 237 | , m_registry(nullptr) | ||
240 | #if HAVE_PIPEWIRE_SUPPORT | 238 | #if HAVE_PIPEWIRE_SUPPORT | ||
241 | , m_fakeInput(nullptr) | 239 | , m_fakeInput(nullptr) | ||
242 | , m_remoteAccessManager(nullptr) | 240 | , m_screencasting(nullptr) | ||
243 | #endif | 241 | #endif | ||
244 | { | 242 | { | ||
245 | #if HAVE_PIPEWIRE_SUPPORT | 243 | #if HAVE_PIPEWIRE_SUPPORT | ||
246 | qDBusRegisterMetaType<WaylandIntegrationPrivate::Stream>(); | 244 | qDBusRegisterMetaType<WaylandIntegrationPrivate::Stream>(); | ||
247 | qDBusRegisterMetaType<WaylandIntegrationPrivate::Streams>(); | 245 | qDBusRegisterMetaType<WaylandIntegrationPrivate::Streams>(); | ||
248 | #endif | 246 | #endif | ||
249 | } | 247 | } | ||
250 | 248 | | |||
251 | WaylandIntegration::WaylandIntegrationPrivate::~WaylandIntegrationPrivate() | 249 | WaylandIntegration::WaylandIntegrationPrivate::~WaylandIntegrationPrivate() | ||
252 | { | 250 | { | ||
253 | #if HAVE_PIPEWIRE_SUPPORT | 251 | #if HAVE_PIPEWIRE_SUPPORT | ||
254 | if (m_remoteAccessManager) { | | |||
255 | m_remoteAccessManager->destroy(); | | |||
256 | } | | |||
257 | | ||||
258 | if (m_gbmDevice) { | 252 | if (m_gbmDevice) { | ||
259 | gbm_device_destroy(m_gbmDevice); | 253 | gbm_device_destroy(m_gbmDevice); | ||
260 | } | 254 | } | ||
261 | #endif | 255 | #endif | ||
262 | } | 256 | } | ||
263 | 257 | | |||
264 | #if HAVE_PIPEWIRE_SUPPORT | 258 | #if HAVE_PIPEWIRE_SUPPORT | ||
265 | bool WaylandIntegration::WaylandIntegrationPrivate::isEGLInitialized() const | 259 | bool WaylandIntegration::WaylandIntegrationPrivate::isEGLInitialized() const | ||
266 | { | 260 | { | ||
267 | return m_eglInitialized; | 261 | return m_eglInitialized; | ||
268 | } | 262 | } | ||
269 | 263 | | |||
270 | bool WaylandIntegration::WaylandIntegrationPrivate::isStreamingEnabled() const | 264 | bool WaylandIntegration::WaylandIntegrationPrivate::isStreamingEnabled() const | ||
271 | { | 265 | { | ||
272 | return m_streamingEnabled; | 266 | return m_streams.isEmpty(); | ||
273 | } | | |||
274 | | ||||
275 | void WaylandIntegration::WaylandIntegrationPrivate::bindOutput(int outputName, int outputVersion) | | |||
276 | { | | |||
277 | KWayland::Client::Output *output = new KWayland::Client::Output(this); | | |||
278 | output->setup(m_registry->bindOutput(outputName, outputVersion)); | | |||
279 | m_bindOutputs << output; | | |||
280 | } | 267 | } | ||
281 | 268 | | |||
282 | void WaylandIntegration::WaylandIntegrationPrivate::startStreamingInput() | 269 | void WaylandIntegration::WaylandIntegrationPrivate::startStreamingInput() | ||
283 | { | 270 | { | ||
284 | m_streamInput = true; | 271 | m_streamInput = true; | ||
285 | } | 272 | } | ||
286 | 273 | | |||
287 | bool WaylandIntegration::WaylandIntegrationPrivate::startStreaming(quint32 outputName) | 274 | QVector<KWayland::Client::ScreencastingSource> WaylandIntegration::screencastingSources() | ||
288 | { | 275 | { | ||
289 | WaylandOutput output = m_outputMap.value(outputName); | 276 | return globalWaylandIntegration->videoStreamingSources(); | ||
290 | m_streamedScreenPosition = output.globalPosition(); | 277 | } | ||
291 | 278 | | |||
292 | m_stream = new ScreenCastStream(output.resolution()); | 279 | bool WaylandIntegration::WaylandIntegrationPrivate::startStreaming(const KWayland::Client::ScreencastingSource &source) | ||
293 | m_stream->init(); | 280 | { | ||
281 | m_streamedScreenPosition = source.geometry().topLeft(); | ||||
294 | 282 | | |||
295 | connect(m_stream, &ScreenCastStream::startStreaming, this, [this, output] { | 283 | m_screencasting->create(source); | ||
296 | m_streamingEnabled = true; | 284 | QEventLoop loop; | ||
297 | startStreamingInput(); | 285 | bool streamReady = false; | ||
298 | bindOutput(output.waylandOutputName(), output.waylandOutputVersion()); | 286 | connect(m_screencasting, &KWayland::Client::Screencasting::failed, this, [&] (const KWayland::Client::ScreencastingSource &newSource, const QString &error) { | ||
299 | }); | 287 | if (source != newSource) { | ||
288 | return; | ||||
289 | } | ||||
290 | qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "failed to start streaming" << source.description() << error; | ||||
300 | 291 | | |||
301 | connect(m_stream, &ScreenCastStream::stopStreaming, this, &WaylandIntegrationPrivate::stopStreaming); | 292 | KNotification *notification = new KNotification(QStringLiteral("screencastfailure"), KNotification::CloseOnTimeout); | ||
293 | notification->setTitle(i18n("Failed to start screencasting")); | ||||
294 | notification->setText(error); | ||||
295 | notification->setIconName(QStringLiteral("dialog-error")); | ||||
296 | notification->sendEvent(); | ||||
302 | 297 | | |||
303 | bool streamReady = false; | 298 | streamReady = false; | ||
304 | QEventLoop loop; | | |||
305 | connect(m_stream, &ScreenCastStream::streamReady, this, [&loop, &streamReady] { | | |||
306 | loop.quit(); | 299 | loop.quit(); | ||
300 | }); | ||||
301 | connect(m_screencasting, &KWayland::Client::Screencasting::created, this, [&] (const KWayland::Client::ScreencastingSource& newSource, uint32_t nodeid) { | ||||
302 | if (source != newSource) { | ||||
303 | return; | ||||
304 | } | ||||
305 | m_streams.append({nodeid, {{QLatin1String("size"), source.geometry().size()}}}); | ||||
306 | startStreamingInput(); | ||||
307 | | ||||
307 | streamReady = true; | 308 | streamReady = true; | ||
309 | loop.quit(); | ||||
308 | }); | 310 | }); | ||
309 | 311 | | |||
310 | // HACK wait for stream to be ready | 312 | connect(m_screencasting, &KWayland::Client::Screencasting::closed, this, &WaylandIntegrationPrivate::stopStreaming); | ||
jgrulich: This has been removed, but I think it will still be needed. | |||||
311 | QTimer::singleShot(3000, &loop, &QEventLoop::quit); | | |||
312 | loop.exec(); | | |||
313 | 313 | | |||
314 | disconnect(m_stream, &ScreenCastStream::streamReady, this, nullptr); | 314 | disconnect(m_screencasting, &KWayland::Client::Screencasting::created, this, nullptr); | ||
315 | 315 | | |||
316 | if (!streamReady) { | 316 | return streamReady; | ||
317 | if (m_stream) { | | |||
318 | delete m_stream; | | |||
319 | m_stream = nullptr; | | |||
320 | } | 317 | } | ||
321 | return false; | | |||
322 | } | | |||
323 | | ||||
324 | // TODO support multiple outputs | | |||
325 | 318 | | |||
326 | if (m_registry->hasInterface(KWayland::Client::Registry::Interface::RemoteAccessManager)) { | 319 | void WaylandIntegration::WaylandIntegrationPrivate::Stream::close() | ||
327 | KWayland::Client::Registry::AnnouncedInterface interface = m_registry->interface(KWayland::Client::Registry::Interface::RemoteAccessManager); | 320 | { | ||
328 | if (!interface.name && !interface.version) { | 321 | globalWaylandIntegration->m_screencasting->close(nodeId); | ||
329 | qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to start streaming: remote access manager interface is not initialized yet"; | | |||
330 | return false; | | |||
331 | } | | |||
332 | m_remoteAccessManager = m_registry->createRemoteAccessManager(interface.name, interface.version); | | |||
333 | connect(m_remoteAccessManager, &KWayland::Client::RemoteAccessManager::bufferReady, this, [this] (const void *output, const KWayland::Client::RemoteBuffer * rbuf) { | | |||
334 | Q_UNUSED(output); | | |||
335 | connect(rbuf, &KWayland::Client::RemoteBuffer::parametersObtained, this, [this, rbuf] { | | |||
336 | processBuffer(rbuf); | | |||
337 | }); | | |||
338 | }); | | |||
339 | m_output = output.waylandOutputName(); | | |||
340 | return true; | | |||
341 | } | 322 | } | ||
342 | 323 | | |||
343 | if (m_stream) { | 324 | void WaylandIntegration::WaylandIntegrationPrivate::stopAllStreaming() | ||
344 | delete m_stream; | 325 | { | ||
345 | m_stream = nullptr; | 326 | for (auto & stream : m_streams) { | ||
327 | stream.close(); | ||||
346 | } | 328 | } | ||
329 | m_streams.clear(); | ||||
347 | 330 | | |||
348 | qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to start streaming: no remote access manager interface"; | 331 | m_streamInput = false; | ||
349 | return false; | 332 | // First unbound outputs and destroy remote access manager so we no longer receive buffers | ||
350 | } | 333 | } | ||
351 | 334 | | |||
352 | void WaylandIntegration::WaylandIntegrationPrivate::stopStreaming() | 335 | void WaylandIntegration::WaylandIntegrationPrivate::stopStreaming(uint32_t nodeid) | ||
353 | { | 336 | { | ||
354 | m_streamInput = false; | 337 | for(auto it = m_streams.begin(), itEnd = m_streams.end(); it != itEnd; ++it) { | ||
355 | if (m_streamingEnabled) { | 338 | if (it->nodeId == nodeid) { | ||
356 | m_streamingEnabled = false; | 339 | m_streams.erase(it); | ||
357 | 340 | break; | |||
358 | // First unbound outputs and destroy remote access manager so we no longer receive buffers | 341 | } | ||
359 | if (m_remoteAccessManager) { | | |||
360 | m_remoteAccessManager->release(); | | |||
361 | m_remoteAccessManager->destroy(); | | |||
362 | } | | |||
363 | qDeleteAll(m_bindOutputs); | | |||
364 | m_bindOutputs.clear(); | | |||
365 | | ||||
366 | if (m_stream) { | | |||
367 | delete m_stream; | | |||
368 | m_stream = nullptr; | | |||
369 | } | 342 | } | ||
343 | | ||||
344 | if (m_streams.isEmpty()) { | ||||
345 | stopAllStreaming(); | ||||
370 | } | 346 | } | ||
371 | } | 347 | } | ||
372 | 348 | | |||
373 | void WaylandIntegration::WaylandIntegrationPrivate::requestPointerButtonPress(quint32 linuxButton) | 349 | void WaylandIntegration::WaylandIntegrationPrivate::requestPointerButtonPress(quint32 linuxButton) | ||
374 | { | 350 | { | ||
375 | if (m_streamInput && m_fakeInput) { | 351 | if (m_streamInput && m_fakeInput) { | ||
376 | m_fakeInput->requestPointerButtonPress(linuxButton); | 352 | m_fakeInput->requestPointerButtonPress(linuxButton); | ||
377 | } | 353 | } | ||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Line(s) | |||||
423 | 399 | | |||
424 | QMap<quint32, WaylandIntegration::WaylandOutput> WaylandIntegration::WaylandIntegrationPrivate::screens() | 400 | QMap<quint32, WaylandIntegration::WaylandOutput> WaylandIntegration::WaylandIntegrationPrivate::screens() | ||
425 | { | 401 | { | ||
426 | return m_outputMap; | 402 | return m_outputMap; | ||
427 | } | 403 | } | ||
428 | 404 | | |||
429 | QVariant WaylandIntegration::WaylandIntegrationPrivate::streams() | 405 | QVariant WaylandIntegration::WaylandIntegrationPrivate::streams() | ||
430 | { | 406 | { | ||
431 | Stream stream; | 407 | return QVariant::fromValue<WaylandIntegrationPrivate::Streams>(m_streams); | ||
432 | stream.nodeId = m_stream->nodeId(); | 408 | } | ||
433 | stream.map = QVariantMap({{QLatin1String("size"), m_outputMap.value(m_output).resolution()}}); | 409 | | ||
434 | return QVariant::fromValue<WaylandIntegrationPrivate::Streams>({stream}); | 410 | QVector<KWayland::Client::ScreencastingSource> WaylandIntegration::WaylandIntegrationPrivate::videoStreamingSources() | ||
411 | { | ||||
412 | return m_screencasting->sources(); | ||||
435 | } | 413 | } | ||
436 | 414 | | |||
437 | void WaylandIntegration::WaylandIntegrationPrivate::initDrm() | 415 | void WaylandIntegration::WaylandIntegrationPrivate::initDrm() | ||
438 | { | 416 | { | ||
439 | m_drmFd = open("/dev/dri/renderD128", O_RDWR); | 417 | m_drmFd = open("/dev/dri/renderD128", O_RDWR); | ||
440 | 418 | | |||
441 | if (m_drmFd == -1) { | 419 | if (m_drmFd == -1) { | ||
442 | qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Cannot open render node: " << strerror(errno); | 420 | qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Cannot open render node: " << strerror(errno); | ||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Line(s) | |||||
585 | void WaylandIntegration::WaylandIntegrationPrivate::removeOutput(quint32 name) | 563 | void WaylandIntegration::WaylandIntegrationPrivate::removeOutput(quint32 name) | ||
586 | { | 564 | { | ||
587 | WaylandOutput output = m_outputMap.take(name); | 565 | WaylandOutput output = m_outputMap.take(name); | ||
588 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << "Removing output:"; | 566 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << "Removing output:"; | ||
589 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << " manufacturer: " << output.manufacturer(); | 567 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << " manufacturer: " << output.manufacturer(); | ||
590 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << " model: " << output.model(); | 568 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << " model: " << output.model(); | ||
591 | } | 569 | } | ||
592 | 570 | | |||
593 | void WaylandIntegration::WaylandIntegrationPrivate::processBuffer(const KWayland::Client::RemoteBuffer* rbuf) | | |||
594 | { | | |||
595 | QScopedPointer<const KWayland::Client::RemoteBuffer> guard(rbuf); | | |||
596 | | ||||
597 | auto gbmHandle = rbuf->fd(); | | |||
598 | auto width = rbuf->width(); | | |||
599 | auto height = rbuf->height(); | | |||
600 | auto stride = rbuf->stride(); | | |||
601 | auto format = rbuf->format(); | | |||
602 | | ||||
603 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << QStringLiteral("Incoming GBM fd %1, %2x%3, stride %4, fourcc 0x%5").arg(gbmHandle).arg(width).arg(height).arg(stride).arg(QString::number(format, 16)); | | |||
604 | | ||||
605 | if (!m_streamingEnabled) { | | |||
606 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << "Streaming is disabled"; | | |||
607 | close(gbmHandle); | | |||
608 | return; | | |||
609 | } | | |||
610 | | ||||
611 | if (m_lastFrameTime.isValid() && | | |||
612 | m_lastFrameTime.msecsTo(QDateTime::currentDateTime()) < (1000 / m_stream->framerate())) { | | |||
613 | close(gbmHandle); | | |||
614 | return; | | |||
615 | } | | |||
616 | | ||||
617 | if (!gbm_device_is_format_supported(m_gbmDevice, format, GBM_BO_USE_SCANOUT)) { | | |||
618 | qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to process buffer: GBM format is not supported by device!"; | | |||
619 | close(gbmHandle); | | |||
620 | return; | | |||
621 | } | | |||
622 | | ||||
623 | // import GBM buffer that was passed from KWin | | |||
624 | gbm_import_fd_data importInfo = {gbmHandle, width, height, stride, format}; | | |||
625 | gbm_bo *imported = gbm_bo_import(m_gbmDevice, GBM_BO_IMPORT_FD, &importInfo, GBM_BO_USE_SCANOUT); | | |||
626 | if (!imported) { | | |||
627 | qCWarning(XdgDesktopPortalKdeWaylandIntegration) << "Failed to process buffer: Cannot import passed GBM fd - " << strerror(errno); | | |||
628 | close(gbmHandle); | | |||
629 | return; | | |||
630 | } | | |||
631 | | ||||
632 | if (m_stream->recordFrame(imported, width, height, stride)) { | | |||
633 | m_lastFrameTime = QDateTime::currentDateTime(); | | |||
634 | } | | |||
635 | | ||||
636 | gbm_bo_destroy(imported); | | |||
637 | close(gbmHandle); | | |||
638 | } | | |||
639 | #endif | 571 | #endif | ||
640 | 572 | | |||
641 | void WaylandIntegration::WaylandIntegrationPrivate::setupRegistry() | 573 | void WaylandIntegration::WaylandIntegrationPrivate::setupRegistry() | ||
642 | { | 574 | { | ||
643 | m_queue = new KWayland::Client::EventQueue(this); | 575 | m_queue = new KWayland::Client::EventQueue(this); | ||
644 | m_queue->setup(m_connection); | 576 | m_queue->setup(m_connection); | ||
645 | 577 | | |||
646 | m_registry = new KWayland::Client::Registry(this); | 578 | m_registry = new KWayland::Client::Registry(this); | ||
647 | 579 | | |||
648 | #if HAVE_PIPEWIRE_SUPPORT | 580 | #if HAVE_PIPEWIRE_SUPPORT | ||
649 | connect(m_registry, &KWayland::Client::Registry::fakeInputAnnounced, this, [this] (quint32 name, quint32 version) { | 581 | connect(m_registry, &KWayland::Client::Registry::fakeInputAnnounced, this, [this] (quint32 name, quint32 version) { | ||
650 | m_fakeInput = m_registry->createFakeInput(name, version, this); | 582 | m_fakeInput = m_registry->createFakeInput(name, version, this); | ||
651 | }); | 583 | }); | ||
652 | connect(m_registry, &KWayland::Client::Registry::outputAnnounced, this, &WaylandIntegrationPrivate::addOutput); | 584 | connect(m_registry, &KWayland::Client::Registry::outputAnnounced, this, &WaylandIntegrationPrivate::addOutput); | ||
653 | connect(m_registry, &KWayland::Client::Registry::outputRemoved, this, &WaylandIntegrationPrivate::removeOutput); | 585 | connect(m_registry, &KWayland::Client::Registry::outputRemoved, this, &WaylandIntegrationPrivate::removeOutput); | ||
654 | #endif | 586 | #endif | ||
655 | 587 | | |||
588 | connect(m_registry, &KWayland::Client::Registry::screencastingAnnounced, this, [this] (quint32 name, quint32 version) { | ||||
589 | qDebug() << "screen!"; | ||||
davidedmundson: leftover | |||||
590 | m_screencasting = m_registry->createScreencasting(name, version, this); | ||||
591 | }); | ||||
656 | connect(m_registry, &KWayland::Client::Registry::plasmaWindowManagementAnnounced, this, [this] (quint32 name, quint32 version) { | 592 | connect(m_registry, &KWayland::Client::Registry::plasmaWindowManagementAnnounced, this, [this] (quint32 name, quint32 version) { | ||
657 | m_windowManagement = m_registry->createPlasmaWindowManagement(name, version, this); | 593 | m_windowManagement = m_registry->createPlasmaWindowManagement(name, version, this); | ||
658 | Q_EMIT waylandIntegration()->plasmaWindowManagementInitialized(); | 594 | Q_EMIT waylandIntegration()->plasmaWindowManagementInitialized(); | ||
659 | }); | 595 | }); | ||
660 | 596 | | |||
661 | connect(m_registry, &KWayland::Client::Registry::interfacesAnnounced, this, [this] { | 597 | connect(m_registry, &KWayland::Client::Registry::interfacesAnnounced, this, [this] { | ||
662 | m_registryInitialized = true; | 598 | m_registryInitialized = true; | ||
663 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << "Registry initialized"; | 599 | qCDebug(XdgDesktopPortalKdeWaylandIntegration) << "Registry initialized"; | ||
664 | }); | 600 | }); | ||
665 | 601 | | |||
666 | m_registry->create(m_connection); | 602 | m_registry->create(m_connection); | ||
667 | m_registry->setEventQueue(m_queue); | 603 | m_registry->setEventQueue(m_queue); | ||
668 | m_registry->setup(); | 604 | m_registry->setup(); | ||
669 | } | 605 | } |
This has been removed, but I think it will still be needed.