Implement zkde_screencast_stream_unstable_v1
This commit is contained in:
parent
97219ec2d5
commit
e089092b54
7 changed files with 396 additions and 0 deletions
|
@ -68,6 +68,7 @@ set(SERVER_LIB_SRCS
|
|||
xdgforeign_v2_interface.cpp
|
||||
xdgoutput_interface.cpp
|
||||
xdgshell_interface.cpp
|
||||
screencast_interface.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(SERVER_LIB_SRCS
|
||||
|
@ -258,6 +259,11 @@ ecm_add_qtwayland_server_protocol(SERVER_LIB_SRCS
|
|||
BASENAME wp-primary-selection-unstable-v1
|
||||
)
|
||||
|
||||
ecm_add_qtwayland_server_protocol(SERVER_LIB_SRCS
|
||||
PROTOCOL PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/screencast.xml
|
||||
BASENAME zkde-screencast-unstable-v1
|
||||
)
|
||||
|
||||
set(SERVER_GENERATED_SRCS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-client-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-server-protocol.h
|
||||
|
@ -316,6 +322,8 @@ set(SERVER_GENERATED_SRCS
|
|||
${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-tablet-unstable-v2.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-tablet-unstable-v2.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-keyboard-shortcuts-inhibit-unstable-v1.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-screencast-unstable-v1.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-screencast-unstable-v1.cpp
|
||||
)
|
||||
|
||||
set_source_files_properties(${SERVER_GENERATED_SRCS} PROPERTIES SKIP_AUTOMOC ON)
|
||||
|
@ -397,6 +405,7 @@ set(SERVER_LIB_HEADERS
|
|||
relativepointer_interface.h
|
||||
remote_access_interface.h
|
||||
resource.h
|
||||
screencast_interface.h
|
||||
seat_interface.h
|
||||
server_decoration_interface.h
|
||||
server_decoration_palette_interface.h
|
||||
|
|
|
@ -75,3 +75,16 @@ add_executable(testViewporterInterface test_viewporter_interface.cpp ${VIEWPORTE
|
|||
target_link_libraries(testViewporterInterface Qt5::Test Plasma::KWaylandServer KF5::WaylandClient Wayland::Client)
|
||||
add_test(NAME kwayland-testViewporterInterface COMMAND testViewporterInterface)
|
||||
ecm_mark_as_test(testViewporterInterface)
|
||||
|
||||
|
||||
########################################################
|
||||
# Test ScreencastInterface
|
||||
########################################################
|
||||
ecm_add_qtwayland_client_protocol(SCREENCAST_SRCS
|
||||
PROTOCOL PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/screencast.xml
|
||||
BASENAME zkde-screencast-unstable-v1
|
||||
)
|
||||
add_executable(testScreencastInterface test_screencast.cpp ${SCREENCAST_SRCS})
|
||||
target_link_libraries(testScreencastInterface Qt5::Test Plasma::KWaylandServer Wayland::Client KF5::WaylandClient)
|
||||
add_test(NAME kwayland-testScreencastInterface COMMAND testScreencastInterface)
|
||||
ecm_mark_as_test(testScreencastInterface)
|
||||
|
|
176
src/wayland/autotests/server/test_screencast.cpp
Normal file
176
src/wayland/autotests/server/test_screencast.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
// Qt
|
||||
#include <QHash>
|
||||
#include <QThread>
|
||||
#include <QtTest>
|
||||
|
||||
#include <wayland-client.h>
|
||||
|
||||
// WaylandServer
|
||||
#include "../../src/server/compositor_interface.h"
|
||||
#include "../../src/server/display.h"
|
||||
#include "../../src/server/seat_interface.h"
|
||||
#include "../../src/server/screencast_interface.h"
|
||||
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/event_queue.h>
|
||||
#include <KWayland/Client/registry.h>
|
||||
#include <KWayland/Client/seat.h>
|
||||
#include <KWayland/Client/compositor.h>
|
||||
|
||||
#include "qwayland-zkde-screencast-unstable-v1.h"
|
||||
|
||||
class ScreencastStream : public QObject, public QtWayland::zkde_screencast_stream_unstable_v1
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScreencastStream(::zkde_screencast_stream_unstable_v1 *obj, QObject *parent)
|
||||
: QObject(parent)
|
||||
, zkde_screencast_stream_unstable_v1(obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void zkde_screencast_stream_unstable_v1_created(uint32_t node) override {
|
||||
Q_EMIT created(node);
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void created(quint32 node);
|
||||
};
|
||||
class Screencast : public QObject, public QtWayland::zkde_screencast_unstable_v1
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Screencast(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ScreencastStream* createWindowStream(const QString &uuid) {
|
||||
return new ScreencastStream(stream_window(uuid, 2), this);
|
||||
}
|
||||
};
|
||||
|
||||
class TestScreencastInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestScreencastInterface()
|
||||
{
|
||||
}
|
||||
|
||||
~TestScreencastInterface() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void testCreate();
|
||||
|
||||
private:
|
||||
KWayland::Client::ConnectionThread *m_connection;
|
||||
KWayland::Client::EventQueue *m_queue = nullptr;
|
||||
Screencast *m_screencast = nullptr;
|
||||
|
||||
KWaylandServer::ScreencastInterface *m_screencastInterface = nullptr;
|
||||
|
||||
QPointer<KWaylandServer::ScreencastStreamInterface> m_triggered = nullptr;
|
||||
QThread *m_thread;
|
||||
KWaylandServer::Display *m_display = nullptr;
|
||||
};
|
||||
|
||||
static const QString s_socketName = QStringLiteral("kwin-wayland-server-screencast-test-0");
|
||||
|
||||
void TestScreencastInterface::initTestCase()
|
||||
{
|
||||
delete m_display;
|
||||
m_display = new KWaylandServer::Display(this);
|
||||
m_display->setSocketName(s_socketName);
|
||||
m_display->start();
|
||||
QVERIFY(m_display->isRunning());
|
||||
|
||||
// setup connection
|
||||
m_connection = new KWayland::Client::ConnectionThread;
|
||||
QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
|
||||
QVERIFY(connectedSpy.isValid());
|
||||
m_connection->setSocketName(s_socketName);
|
||||
|
||||
m_thread = new QThread(this);
|
||||
m_connection->moveToThread(m_thread);
|
||||
m_thread->start();
|
||||
|
||||
m_connection->initConnection();
|
||||
QVERIFY(connectedSpy.wait());
|
||||
|
||||
m_queue = new KWayland::Client::EventQueue(this);
|
||||
QVERIFY(!m_queue->isValid());
|
||||
m_queue->setup(m_connection);
|
||||
QVERIFY(m_queue->isValid());
|
||||
|
||||
KWayland::Client::Registry registry;
|
||||
|
||||
QSignalSpy screencastSpy(®istry, &KWayland::Client::Registry::interfacesAnnounced);
|
||||
QVERIFY(screencastSpy.isValid());
|
||||
m_screencastInterface = m_display->createScreencastInterface(this);
|
||||
connect(m_screencastInterface, &KWaylandServer::ScreencastInterface::windowScreencastRequested, this, [this] (KWaylandServer::ScreencastStreamInterface* stream, const QString &winid) {
|
||||
Q_UNUSED(winid);
|
||||
stream->sendCreated(123);
|
||||
m_triggered = stream;
|
||||
});
|
||||
|
||||
connect(®istry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, ®istry] (const QByteArray &interfaceName, quint32 name, quint32 version) {
|
||||
if (interfaceName != "zkde_screencast_unstable_v1")
|
||||
return;
|
||||
Q_ASSERT(version == 1);
|
||||
m_screencast = new Screencast(this);
|
||||
m_screencast->init(&*registry, name, version);
|
||||
});
|
||||
registry.setEventQueue(m_queue);
|
||||
registry.create(m_connection->display());
|
||||
QVERIFY(registry.isValid());
|
||||
registry.setup();
|
||||
wl_display_flush(m_connection->display());
|
||||
|
||||
QVERIFY(m_screencastInterface);
|
||||
QVERIFY(m_screencast || screencastSpy.wait());
|
||||
QVERIFY(m_screencast);
|
||||
}
|
||||
|
||||
TestScreencastInterface::~TestScreencastInterface()
|
||||
{
|
||||
delete m_queue;
|
||||
m_queue = nullptr;
|
||||
|
||||
if (m_thread) {
|
||||
m_thread->quit();
|
||||
m_thread->wait();
|
||||
delete m_thread;
|
||||
m_thread = nullptr;
|
||||
}
|
||||
m_connection->deleteLater();
|
||||
m_connection = nullptr;
|
||||
|
||||
delete m_display;
|
||||
}
|
||||
|
||||
void TestScreencastInterface::testCreate()
|
||||
{
|
||||
auto stream = m_screencast->createWindowStream("3");
|
||||
QVERIFY(stream);
|
||||
|
||||
QSignalSpy spyWorking(stream, &ScreencastStream::created);
|
||||
QVERIFY(spyWorking.count() || spyWorking.wait());
|
||||
QVERIFY(m_triggered);
|
||||
|
||||
QSignalSpy spyStop(m_triggered, &KWaylandServer::ScreencastStreamInterface::finished);
|
||||
stream->close();
|
||||
QVERIFY(spyStop.count() || spyStop.wait());
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(TestScreencastInterface)
|
||||
|
||||
#include "test_screencast.moc"
|
|
@ -33,6 +33,7 @@
|
|||
#include "relativepointer_interface_p.h"
|
||||
#include "remote_access_interface.h"
|
||||
#include "seat_interface.h"
|
||||
#include "screencast_interface.h"
|
||||
#include "server_decoration_interface.h"
|
||||
#include "server_decoration_palette_interface.h"
|
||||
#include "shadow_interface.h"
|
||||
|
@ -341,6 +342,13 @@ ServerSideDecorationManagerInterface *Display::createServerSideDecorationManager
|
|||
return d;
|
||||
}
|
||||
|
||||
ScreencastInterface *Display::createScreencastInterface(QObject *parent)
|
||||
{
|
||||
auto s = new ScreencastInterface(this, parent);
|
||||
connect(this, &Display::aboutToTerminate, s, [s] { delete s; });
|
||||
return s;
|
||||
}
|
||||
|
||||
TextInputManagerInterface *Display::createTextInputManager(const TextInputInterfaceVersion &version, QObject *parent)
|
||||
{
|
||||
TextInputManagerInterface *t = nullptr;
|
||||
|
|
|
@ -81,6 +81,7 @@ class DataControlDeviceManagerV1Interface;
|
|||
class PrimarySelectionDeviceManagerV1Interface;
|
||||
class KeyboardShortcutsInhibitManagerV1Interface;
|
||||
class ViewporterInterface;
|
||||
class ScreencastInterface;
|
||||
|
||||
/**
|
||||
* @brief Class holding the Wayland server display loop.
|
||||
|
@ -333,6 +334,11 @@ public:
|
|||
*/
|
||||
PrimarySelectionDeviceManagerV1Interface *createPrimarySelectionDeviceManagerV1(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* Creates an interface to request video feeds of different compositor resources
|
||||
*/
|
||||
ScreencastInterface *createScreencastInterface(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* Gets the ClientConnection for the given @p client.
|
||||
* If there is no ClientConnection yet for the given @p client, it will be created.
|
||||
|
|
111
src/wayland/server/screencast_interface.cpp
Normal file
111
src/wayland/server/screencast_interface.cpp
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "screencast_interface.h"
|
||||
#include "display.h"
|
||||
#include <QDebug>
|
||||
|
||||
#include "qwayland-server-zkde-screencast-unstable-v1.h"
|
||||
|
||||
using namespace KWaylandServer;
|
||||
|
||||
static int s_version = 1;
|
||||
|
||||
class KWaylandServer::ScreencastStreamInterfacePrivate : public QtWaylandServer::zkde_screencast_stream_unstable_v1
|
||||
{
|
||||
public:
|
||||
ScreencastStreamInterfacePrivate(ScreencastStreamInterface *q)
|
||||
: q(q)
|
||||
{}
|
||||
|
||||
void zkde_screencast_stream_unstable_v1_destroy_resource(Resource *resource) override
|
||||
{
|
||||
Q_UNUSED(resource);
|
||||
if (!stopped) {
|
||||
Q_EMIT q->finished();
|
||||
}
|
||||
|
||||
q->deleteLater();
|
||||
}
|
||||
|
||||
void zkde_screencast_stream_unstable_v1_close(Resource * resource) override
|
||||
{
|
||||
Q_UNUSED(resource);
|
||||
Q_EMIT q->finished();
|
||||
stopped = true;
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
bool stopped = false;
|
||||
ScreencastStreamInterface *const q;
|
||||
};
|
||||
|
||||
ScreencastStreamInterface::ScreencastStreamInterface(QObject* parent)
|
||||
: QObject(parent)
|
||||
, d(new ScreencastStreamInterfacePrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
ScreencastStreamInterface::~ScreencastStreamInterface() = default;
|
||||
|
||||
void ScreencastStreamInterface::sendCreated(quint32 nodeid)
|
||||
{
|
||||
d->send_created(nodeid);
|
||||
}
|
||||
|
||||
void ScreencastStreamInterface::sendFailed(const QString& error)
|
||||
{
|
||||
d->send_failed(error);
|
||||
}
|
||||
|
||||
void ScreencastStreamInterface::sendClosed()
|
||||
{
|
||||
if (!d->stopped) {
|
||||
d->send_closed();
|
||||
}
|
||||
}
|
||||
|
||||
class KWaylandServer::ScreencastInterfacePrivate : public QtWaylandServer::zkde_screencast_unstable_v1
|
||||
{
|
||||
public:
|
||||
ScreencastInterfacePrivate(Display *display, ScreencastInterface* q)
|
||||
: QtWaylandServer::zkde_screencast_unstable_v1(*display, s_version)
|
||||
, q(q)
|
||||
{
|
||||
}
|
||||
|
||||
ScreencastStreamInterface *createStream(Resource *resource, quint32 streamid) const
|
||||
{
|
||||
auto stream = new ScreencastStreamInterface(q);
|
||||
stream->d->init(resource->client(), streamid, resource->version());
|
||||
return stream;
|
||||
}
|
||||
|
||||
void zkde_screencast_unstable_v1_stream_output(Resource *resource, uint32_t streamid, struct ::wl_resource *output, uint32_t pointer) override
|
||||
{
|
||||
Q_EMIT q->outputScreencastRequested(createStream(resource, streamid), output, ScreencastInterface::CursorMode(pointer));
|
||||
}
|
||||
|
||||
void zkde_screencast_unstable_v1_stream_window(Resource *resource, uint32_t streamid, const QString &uuid, uint32_t pointer) override
|
||||
{
|
||||
Q_EMIT q->windowScreencastRequested(createStream(resource, streamid), uuid, ScreencastInterface::CursorMode(pointer));
|
||||
}
|
||||
|
||||
void zkde_screencast_unstable_v1_destroy(Resource * resource) override
|
||||
{
|
||||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
ScreencastInterface *const q;
|
||||
};
|
||||
|
||||
ScreencastInterface::ScreencastInterface(Display *display, QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new ScreencastInterfacePrivate(display, this))
|
||||
{
|
||||
}
|
||||
|
||||
ScreencastInterface::~ScreencastInterface() = default;
|
73
src/wayland/server/screencast_interface.h
Normal file
73
src/wayland/server/screencast_interface.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QRect>
|
||||
#include <QScopedPointer>
|
||||
#include <QSharedPointer>
|
||||
#include <functional>
|
||||
#include <KWaylandServer/kwaylandserver_export.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
struct wl_resource;
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
class Display;
|
||||
class OutputInterface;
|
||||
class Screencast;
|
||||
class ScreencastSourcePrivate;
|
||||
class ScreencastInterfacePrivate;
|
||||
class ScreencastStreamInterfacePrivate;
|
||||
class ScreencastStreamInterface;
|
||||
|
||||
class KWAYLANDSERVER_EXPORT ScreencastStreamInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
~ScreencastStreamInterface() override;
|
||||
|
||||
void sendCreated(quint32 nodeid);
|
||||
void sendFailed(const QString &error);
|
||||
void sendClosed();
|
||||
|
||||
Q_SIGNALS:
|
||||
void finished();
|
||||
|
||||
private:
|
||||
friend class ScreencastInterfacePrivate;
|
||||
explicit ScreencastStreamInterface(QObject *parent);
|
||||
QScopedPointer<ScreencastStreamInterfacePrivate> d;
|
||||
};
|
||||
|
||||
class KWAYLANDSERVER_EXPORT ScreencastInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~ScreencastInterface();
|
||||
|
||||
enum CursorMode {
|
||||
Hidden = 1,
|
||||
Embedded = 2,
|
||||
Metadata = 4,
|
||||
};
|
||||
Q_ENUM(CursorMode);
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
void outputScreencastRequested(ScreencastStreamInterface* stream, ::wl_resource *output, CursorMode mode);
|
||||
void windowScreencastRequested(ScreencastStreamInterface* stream, const QString &winid, CursorMode mode);
|
||||
|
||||
private:
|
||||
explicit ScreencastInterface(Display *display, QObject *parent = nullptr);
|
||||
friend class Display;
|
||||
QScopedPointer<ScreencastInterfacePrivate> d;
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in a new issue