File indexing completed on 2024-04-28 05:36:52

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 "screencast_debug.h"
0010 
0011 #include <KWayland/Client/output.h>
0012 #include <KWayland/Client/plasmawindowmanagement.h>
0013 #include <KWayland/Client/registry.h>
0014 #include <QDebug>
0015 #include <QRect>
0016 
0017 #include <QGuiApplication>
0018 #include <qpa/qplatformnativeinterface.h>
0019 
0020 using namespace KWayland::Client;
0021 
0022 class ScreencastingStreamPrivate : public QtWayland::zkde_screencast_stream_unstable_v1
0023 {
0024 public:
0025     ScreencastingStreamPrivate(ScreencastingStream *q)
0026         : q(q)
0027     {
0028     }
0029     ~ScreencastingStreamPrivate() override
0030     {
0031         close();
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     uint m_nodeid = 0;
0052     QRect m_geometry;
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     return d->m_nodeid;
0067 }
0068 
0069 QRect ScreencastingStream::geometry() const
0070 {
0071     return d->m_geometry;
0072 }
0073 
0074 class ScreencastingPrivate : public QtWayland::zkde_screencast_unstable_v1
0075 {
0076 public:
0077     ScreencastingPrivate(Registry *registry, int id, int version, Screencasting *q)
0078         : QtWayland::zkde_screencast_unstable_v1(*registry, id, version)
0079         , q(q)
0080     {
0081     }
0082 
0083     ScreencastingPrivate(::zkde_screencast_unstable_v1 *screencasting, Screencasting *q)
0084         : QtWayland::zkde_screencast_unstable_v1(screencasting)
0085         , q(q)
0086     {
0087     }
0088 
0089     ~ScreencastingPrivate() override
0090     {
0091         destroy();
0092     }
0093 
0094     Screencasting *const q;
0095 };
0096 
0097 Screencasting::Screencasting(QObject *parent)
0098     : QObject(parent)
0099 {
0100 }
0101 
0102 Screencasting::Screencasting(Registry *registry, int id, int version, QObject *parent)
0103     : QObject(parent)
0104     , d(new ScreencastingPrivate(registry, id, version, this))
0105 {
0106 }
0107 
0108 Screencasting::~Screencasting() = default;
0109 
0110 ScreencastingStream *Screencasting::createOutputStream(QScreen *screen, CursorMode mode)
0111 {
0112     auto stream = new ScreencastingStream(this);
0113     stream->setObjectName(screen->name());
0114 
0115     auto native = qGuiApp->platformNativeInterface();
0116     auto *output = reinterpret_cast<wl_output *>(native->nativeResourceForScreen(QByteArrayLiteral("output"), screen));
0117     if (!output) {
0118         qCWarning(XdgDesktopPortalKdeScreenCast) << "Could not find a matching Wayland output for screen" << screen->name();
0119         return nullptr;
0120     }
0121 
0122     stream->d->init(d->stream_output(output, mode));
0123     stream->d->m_geometry = screen->geometry();
0124     return stream;
0125 }
0126 
0127 ScreencastingStream *Screencasting::createWindowStream(const QString &uuid, CursorMode mode)
0128 {
0129     auto stream = new ScreencastingStream(this);
0130     stream->d->init(d->stream_window(uuid, mode));
0131     return stream;
0132 }
0133 
0134 ScreencastingStream *Screencasting::createRegionStream(const QRect &g, qreal scale, CursorMode mode)
0135 {
0136     auto stream = new ScreencastingStream(this);
0137     stream->d->init(d->stream_region(g.x(), g.y(), g.width(), g.height(), wl_fixed_from_double(scale), mode));
0138     stream->d->m_geometry = g;
0139     return stream;
0140 }
0141 
0142 ScreencastingStream *Screencasting::createVirtualOutputStream(const QString &name, const QSize &s, qreal scale, Screencasting::CursorMode mode)
0143 {
0144     auto stream = new ScreencastingStream(this);
0145     stream->d->init(d->stream_virtual_output(name, s.width(), s.height(), wl_fixed_from_double(scale), mode));
0146     stream->d->m_geometry = QRect(QPoint(0, 0), s);
0147     return stream;
0148 }
0149 
0150 void Screencasting::setup(::zkde_screencast_unstable_v1 *screencasting)
0151 {
0152     d.reset(new ScreencastingPrivate(screencasting, this));
0153 }
0154 
0155 void Screencasting::destroy()
0156 {
0157     d.reset(nullptr);
0158 }