File indexing completed on 2024-04-21 05:44:59

0001 /*
0002     SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "screencasting.h"
0008 #include "qwayland-zkde-screencast-unstable-v1.h"
0009 #include <QGuiApplication>
0010 #include <QLoggingCategory>
0011 #include <QPointer>
0012 #include <QRect>
0013 #include <QtWaylandClient/QWaylandClientExtensionTemplate>
0014 #include <QtWaylandClientVersion>
0015 #include <qpa/qplatformnativeinterface.h>
0016 #include <qscreen.h>
0017 
0018 using namespace KWayland::Client;
0019 
0020 class ScreencastingStreamPrivate : public QtWayland::zkde_screencast_stream_unstable_v1
0021 {
0022 public:
0023     explicit ScreencastingStreamPrivate(ScreencastingStream *q)
0024         : q(q)
0025     {
0026     }
0027     ~ScreencastingStreamPrivate() override
0028     {
0029         if (isInitialized()) {
0030             close();
0031         }
0032         q->deleteLater();
0033     }
0034     Q_DISABLE_COPY_MOVE(ScreencastingStreamPrivate)
0035 
0036     void zkde_screencast_stream_unstable_v1_created(uint32_t node) override
0037     {
0038         m_nodeId = node;
0039         Q_EMIT q->created(node);
0040     }
0041 
0042     void zkde_screencast_stream_unstable_v1_closed() override
0043     {
0044         Q_EMIT q->closed();
0045     }
0046 
0047     void zkde_screencast_stream_unstable_v1_failed(const QString &error) override
0048     {
0049         Q_EMIT q->failed(error);
0050     }
0051 
0052     std::optional<uint> m_nodeId;
0053     QPointer<ScreencastingStream> q;
0054 };
0055 
0056 ScreencastingStream::ScreencastingStream(QObject *parent)
0057     : QObject(parent)
0058     , d(new ScreencastingStreamPrivate(this))
0059 {
0060 }
0061 
0062 ScreencastingStream::~ScreencastingStream() = default;
0063 
0064 quint32 ScreencastingStream::nodeId() const
0065 {
0066     Q_ASSERT(d->m_nodeId.has_value());
0067     return d->m_nodeId.value_or(0);
0068 }
0069 
0070 class ScreencastingPrivate : public QWaylandClientExtensionTemplate<ScreencastingPrivate>, public QtWayland::zkde_screencast_unstable_v1
0071 {
0072 public:
0073     explicit ScreencastingPrivate(Screencasting *q)
0074         : QWaylandClientExtensionTemplate<ScreencastingPrivate>(ZKDE_SCREENCAST_UNSTABLE_V1_STREAM_REGION_SINCE_VERSION)
0075         , q(q)
0076     {
0077 #if QTWAYLANDCLIENT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
0078         initialize();
0079 #else
0080         // QWaylandClientExtensionTemplate invokes this with a QueuedConnection but
0081         // we want it called immediately
0082         QMetaObject::invokeMethod(this, "addRegistryListener", Qt::DirectConnection);
0083 #endif
0084 
0085         if (!isInitialized()) {
0086             qWarning() << "Remember requesting the interface on your desktop file: "
0087                           "X-KDE-Wayland-Interfaces=zkde_screencast_unstable_v1";
0088         }
0089         Q_ASSERT(isInitialized());
0090     }
0091 
0092     ~ScreencastingPrivate() override
0093     {
0094         destroy();
0095     }
0096     Q_DISABLE_COPY_MOVE(ScreencastingPrivate)
0097 
0098     Screencasting *const q;
0099 };
0100 
0101 Screencasting::Screencasting(QObject *parent)
0102     : QObject(parent)
0103     , d(new ScreencastingPrivate(this))
0104 {
0105 }
0106 
0107 Screencasting::~Screencasting() = default;
0108 
0109 ScreencastingStream *Screencasting::createRegionStream(const QRect &geometry, qreal scaling, CursorMode mode)
0110 {
0111     Q_ASSERT(d->QWaylandClientExtension::version() >= ZKDE_SCREENCAST_UNSTABLE_V1_STREAM_REGION_SINCE_VERSION);
0112     auto stream = new ScreencastingStream(this);
0113     stream->setObjectName(QStringLiteral("region-%1,%2 (%3x%4)").arg(geometry.x()).arg(geometry.y()).arg(geometry.width()).arg(geometry.height()));
0114     stream->d->init(d->stream_region(geometry.x(), geometry.y(), geometry.width(), geometry.height(), wl_fixed_from_double(scaling), mode));
0115     return stream;
0116 }
0117 
0118 void Screencasting::destroy()
0119 {
0120     d.reset(nullptr);
0121 }