File indexing completed on 2024-04-28 05:27:35

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 "logging.h"
0009 #include "qwayland-zkde-screencast-unstable-v1.h"
0010 #include <QGuiApplication>
0011 #include <QPointer>
0012 #include <QRect>
0013 #include <QtWaylandClient/QWaylandClientExtensionTemplate>
0014 #include <qpa/qplatformnativeinterface.h>
0015 #include <qscreen.h>
0016 #include <qtwaylandclientversion.h>
0017 
0018 using namespace KWayland::Client;
0019 
0020 class ScreencastingStreamPrivate : public QtWayland::zkde_screencast_stream_unstable_v1
0021 {
0022 public:
0023     ScreencastingStreamPrivate(ScreencastingStream *q)
0024         : q(q)
0025     {
0026     }
0027     ~ScreencastingStreamPrivate()
0028     {
0029         if (isInitialized()) {
0030             close();
0031         }
0032         q->deleteLater();
0033     }
0034 
0035     void zkde_screencast_stream_unstable_v1_created(uint32_t node) override
0036     {
0037         m_nodeId = node;
0038         Q_EMIT q->created(node);
0039     }
0040 
0041     void zkde_screencast_stream_unstable_v1_closed() override
0042     {
0043         Q_EMIT q->closed();
0044     }
0045 
0046     void zkde_screencast_stream_unstable_v1_failed(const QString &error) override
0047     {
0048         Q_EMIT q->failed(error);
0049     }
0050 
0051     std::optional<uint> m_nodeId;
0052     QPointer<ScreencastingStream> q;
0053 };
0054 
0055 ScreencastingStream::ScreencastingStream(QObject *parent)
0056     : QObject(parent)
0057     , d(new ScreencastingStreamPrivate(this))
0058 {
0059 }
0060 
0061 ScreencastingStream::~ScreencastingStream() = default;
0062 
0063 quint32 ScreencastingStream::nodeId() const
0064 {
0065     Q_ASSERT(d->m_nodeId.has_value());
0066     return *d->m_nodeId;
0067 }
0068 
0069 class ScreencastingPrivate : public QWaylandClientExtensionTemplate<ScreencastingPrivate>, public QtWayland::zkde_screencast_unstable_v1
0070 {
0071 public:
0072     ScreencastingPrivate(Screencasting *q)
0073         : QWaylandClientExtensionTemplate<ScreencastingPrivate>(ZKDE_SCREENCAST_UNSTABLE_V1_STREAM_REGION_SINCE_VERSION)
0074         , q(q)
0075     {
0076         initialize();
0077 
0078         if (!isInitialized()) {
0079             qWarning() << "Remember requesting the interface on your desktop file: X-KDE-Wayland-Interfaces=zkde_screencast_unstable_v1";
0080         }
0081         Q_ASSERT(isInitialized());
0082     }
0083 
0084     ~ScreencastingPrivate()
0085     {
0086         destroy();
0087     }
0088 
0089     Screencasting *const q;
0090 };
0091 
0092 Screencasting::Screencasting(QObject *parent)
0093     : QObject(parent)
0094     , d(new ScreencastingPrivate(this))
0095 {
0096 }
0097 
0098 Screencasting::~Screencasting() = default;
0099 
0100 ScreencastingStream *Screencasting::createOutputStream(const QString &outputName, Screencasting::CursorMode mode)
0101 {
0102     for (auto screen : qGuiApp->screens()) {
0103         if (screen->name() == outputName) {
0104             return createOutputStream(screen, mode);
0105         }
0106     }
0107     return nullptr;
0108 }
0109 
0110 ScreencastingStream *Screencasting::createOutputStream(QScreen *screen, CursorMode mode)
0111 {
0112     wl_output *output = (wl_output *)QGuiApplication::platformNativeInterface()->nativeResourceForScreen("output", screen);
0113     auto stream = new ScreencastingStream(this);
0114     stream->setObjectName(screen->name());
0115     stream->d->init(d->stream_output(output, mode));
0116     return stream;
0117 }
0118 
0119 ScreencastingStream *Screencasting::createRegionStream(const QRect &geometry, qreal scaling, CursorMode mode)
0120 {
0121     Q_ASSERT(d->QWaylandClientExtension::version() >= ZKDE_SCREENCAST_UNSTABLE_V1_STREAM_REGION_SINCE_VERSION);
0122     auto stream = new ScreencastingStream(this);
0123     stream->setObjectName(QStringLiteral("region-%1,%2 (%3x%4)").arg(geometry.x()).arg(geometry.y()).arg(geometry.width()).arg(geometry.height()));
0124     stream->d->init(d->stream_region(geometry.x(), geometry.y(), geometry.width(), geometry.height(), wl_fixed_from_double(scaling), mode));
0125     return stream;
0126 }
0127 
0128 ScreencastingStream *Screencasting::createWindowStream(const QString &uuid, CursorMode mode)
0129 {
0130     auto stream = new ScreencastingStream(this);
0131     stream->d->init(d->stream_window(uuid, mode));
0132     return stream;
0133 }
0134 
0135 ScreencastingStream *Screencasting::createVirtualMonitorStream(const QString &name, const QSize &size, qreal scale, CursorMode mode)
0136 {
0137     auto stream = new ScreencastingStream(this);
0138     stream->d->init(d->stream_virtual_output(name, size.width(), size.height(), wl_fixed_from_double(scale), mode));
0139     return stream;
0140 }
0141 
0142 void Screencasting::destroy()
0143 {
0144     d.reset(nullptr);
0145 }
0146 
0147 #include "moc_screencasting.cpp"