diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -22,6 +22,7 @@ fullscreen_shell.cpp idle.cpp keyboard.cpp + remoteaccess.cpp outputconfiguration.cpp outputmanagement.cpp outputdevice.cpp @@ -106,6 +107,10 @@ PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/server-decoration.xml BASENAME server-decoration ) +ecm_add_wayland_client_protocol(CLIENT_LIB_SRCS + PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/remoteaccess.xml + BASENAME remoteaccess +) add_library(KF5WaylandClient ${CLIENT_LIB_SRCS}) generate_export_header(KF5WaylandClient @@ -153,6 +158,7 @@ fullscreen_shell.h idle.h keyboard.h + remoteaccess.h outputconfiguration.h outputmanagement.h outputdevice.h diff --git a/src/client/protocols/remoteaccess.xml b/src/client/protocols/remoteaccess.xml new file mode 100644 --- /dev/null +++ b/src/client/protocols/remoteaccess.xml @@ -0,0 +1,34 @@ + + + . + ]]> + + + + + + + + + + + + + + + + diff --git a/src/client/registry.h b/src/client/registry.h --- a/src/client/registry.h +++ b/src/client/registry.h @@ -39,6 +39,7 @@ struct org_kde_kwin_outputdevice; struct org_kde_kwin_fake_input; struct org_kde_kwin_idle; +struct org_kde_kwin_remoteaccess; struct org_kde_kwin_dpms_manager; struct org_kde_kwin_shadow_manager; struct org_kde_kwin_blur_manager; @@ -63,6 +64,7 @@ class OutputManagement; class OutputDevice; class Idle; +class RemoteAccess; class Output; class PlasmaShell; class PlasmaWindowManagement; @@ -123,6 +125,7 @@ PlasmaShell, ///< Refers to org_kde_plasma_shell interface PlasmaWindowManagement, ///< Refers to org_kde_plasma_window_management interface Idle, ///< Refers to org_kde_kwin_idle_interface interface + RemoteAccess, ///< Refers to org_kde_kwin_remoteaccess_interface interface FakeInput, ///< Refers to org_kde_kwin_fake_input interface Shadow, ///< Refers to org_kde_kwin_shadow_manager interface Blur, ///< refers to org_kde_kwin_blur_manager interface @@ -367,6 +370,16 @@ **/ org_kde_kwin_idle *bindIdle(uint32_t name, uint32_t version) const; /** + * Binds the org_kde_kwin_remoteaccess with @p name and @p version. + * If the @p name does not exist or is not for the idle interface, + * @c null will be returned. + * + * Prefer using createIdle instead. + * @see createIdle + * @since 5.7 + **/ + org_kde_kwin_remoteaccess *bindRemoteAccess(uint32_t name, uint32_t version) const; + /** * Binds the org_kde_kwin_fake_input with @p name and @p version. * If the @p name does not exist or is not for the fake input interface, * @c null will be returned. @@ -644,6 +657,22 @@ **/ Idle *createIdle(quint32 name, quint32 version, QObject *parent = nullptr); /** + * Creates a RemoteAccess and sets it up to manage the interface identified by + * @p name and @p version. + * + * Note: in case @p name is invalid or isn't for the org_kde_kwin_remoteaccess interface, + * the returned RemoteAccess will not be valid. Therefore it's recommended to call + * isValid on the created instance. + * + * @param name The name of the org_kde_kwin_remoteaccess interface to bind + * @param version The version or the org_kde_kwin_remoteaccess interface to use + * @param parent The parent for RemoteAccess + * + * @returns The created RemoteAccess. + * @since 5.7 + **/ + RemoteAccess *createRemoteAccess(quint32 name, quint32 version, QObject *parent = nullptr); + /** * Creates a FakeInput and sets it up to manage the interface identified by * @p name and @p version. * @@ -854,6 +883,13 @@ **/ void idleAnnounced(quint32 name, quint32 version); /** + * Emitted whenever a org_kde_kwin_remoteaccess interface gets announced. + * @param name The name for the announced interface + * @param version The maximum supported version of the announced interface + * @since 5.7 + **/ + void remoteAccessAnnounced(quint32 name, quint32 version); + /** * Emitted whenever a org_kde_kwin_fake_input interface gets announced. * @param name The name for the announced interface * @param version The maximum supported version of the announced interface @@ -978,6 +1014,12 @@ **/ void idleRemoved(quint32 name); /** + * Emitted whenever a org_kde_kwin_remoteaccess interface gets removed. + * @param name The name for the removed interface + * @since 5.7 + **/ + void remoteAccessRemoved(quint32 name); + /** * Emitted whenever a org_kde_kwin_fake_input interface gets removed. * @param name The name for the removed interface * @since 5.4 diff --git a/src/client/registry.cpp b/src/client/registry.cpp --- a/src/client/registry.cpp +++ b/src/client/registry.cpp @@ -26,6 +26,7 @@ #include "fakeinput.h" #include "fullscreen_shell.h" #include "idle.h" +#include "remoteaccess.h" #include "logging_p.h" #include "outputconfiguration.h" #include "outputmanagement.h" @@ -51,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -158,6 +160,13 @@ &Registry::idleAnnounced, &Registry::idleRemoved }}, + {Registry::Interface::RemoteAccess, { + 1, + QByteArrayLiteral("org_kde_kwin_remoteaccess"), + &org_kde_kwin_remoteaccess_interface, + &Registry::remoteAccessAnnounced, + &Registry::remoteAccessRemoved + }}, {Registry::Interface::FakeInput, { 1, QByteArrayLiteral("org_kde_kwin_fake_input"), @@ -502,6 +511,7 @@ BIND(PlasmaShell, org_kde_plasma_shell) BIND(PlasmaWindowManagement, org_kde_plasma_window_management) BIND(Idle, org_kde_kwin_idle) +BIND(RemoteAccess, org_kde_kwin_remoteaccess) BIND(FakeInput, org_kde_kwin_fake_input) BIND(OutputManagement, org_kde_kwin_outputmanagement) BIND(OutputDevice, org_kde_kwin_outputdevice) @@ -549,6 +559,7 @@ CREATE(PlasmaShell) CREATE(PlasmaWindowManagement) CREATE(Idle) +CREATE(RemoteAccess) CREATE(FakeInput) CREATE(OutputManagement) CREATE(OutputDevice) diff --git a/src/client/remoteaccess.h b/src/client/remoteaccess.h new file mode 100644 --- /dev/null +++ b/src/client/remoteaccess.h @@ -0,0 +1,139 @@ +/**************************************************************************** +Copyright 2016 Oleg Chernovskiy + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#ifndef KWAYLAND_CLIENT_KRFB_H +#define KWAYLAND_CLIENT_KRFB_H + +#include + +#include + +struct org_kde_kwin_remoteaccess; + +namespace KWayland +{ +namespace Client +{ + +class EventQueue; + +/** + * @short Wrapper for the org_kde_kwin_remoteaccess interface. + * + * This class provides a convenient wrapper for the org_kde_kwin_remoteaccess interface. + * + * To use this class one needs to interact with the Registry. There are two + * possible ways to create the RemoteAccess interface: + * @code + * RemoteAccess *c = registry->createRemoteAccess(name, version); + * @endcode + * + * This creates the RemoteAccess and sets it up directly. As an alternative this + * can also be done in a more low level way: + * @code + * RemoteAccess *c = new RemoteAccess; + * c->setup(registry->bindRemoteAccess(name, version)); + * @endcode + * + * The RemoteAccess can be used as a drop-in replacement for any org_kde_kwin_remoteaccess + * pointer as it provides matching cast operators. + * + * @see Registry + **/ +class KWAYLANDCLIENT_EXPORT RemoteAccess : public QObject +{ + Q_OBJECT +public: + /** + * Creates a new RemoteAccess. + * Note: after constructing the RemoteAccess it is not yet valid and one needs + * to call setup. In order to get a ready to use RemoteAccess prefer using + * Registry::createRemoteAccess. + **/ + explicit RemoteAccess(QObject *parent = nullptr); + virtual ~RemoteAccess(); + + /** + * Setup this RemoteAccess to manage the @p remoteaccess. + * When using Registry::createRemoteAccess there is no need to call this + * method. + **/ + void setup(org_kde_kwin_remoteaccess *remoteAccess); + /** + * @returns @c true if managing a org_kde_kwin_remoteaccess. + **/ + bool isValid() const; + /** + * Releases the org_kde_kwin_remoteaccess interface. + * After the interface has been released the RemoteAccess instance is no + * longer valid and can be setup with another org_kde_kwin_remoteaccess interface. + **/ + void release(); + /** + * Destroys the data held by this RemoteAccess. + * This method is supposed to be used when the connection to the Wayland + * server goes away. If the connection is not valid anymore, it's not + * possible to call release anymore as that calls into the Wayland + * connection and the call would fail. This method cleans up the data, so + * that the instance can be deleted or set up to a new org_kde_kwin_remoteaccess interface + * once there is a new connection available. + * + * It is suggested to connect this method to ConnectionThread::connectionDied: + * @code + * connect(connection, &ConnectionThread::connectionDied, remoteaccess, &RemoteAccess::destroy); + * @endcode + * + * @see release + **/ + void destroy(); + + /** + * Sets the @p queue to use for creating objects with this RemoteAccess. + **/ + void setEventQueue(EventQueue *queue); + /** + * @returns The event queue to use for creating objects with this RemoteAccess. + **/ + EventQueue *eventQueue(); + + void bufferNoLongerNeeded(); + + operator org_kde_kwin_remoteaccess*(); + operator org_kde_kwin_remoteaccess*() const; + +Q_SIGNALS: + /** + * The corresponding global for this interface on the Registry got removed. + * + * This signal gets only emitted if the RemoteAccess got created by + * Registry::createRemoteAccess + **/ + void removed(); + void bufferReady(qint32 gbmHandle, quint32 width, quint32 height, quint32 stride, quint32 format); + +private: + class Private; + QScopedPointer d; +}; + + +} +} + +#endif diff --git a/src/client/remoteaccess.cpp b/src/client/remoteaccess.cpp new file mode 100644 --- /dev/null +++ b/src/client/remoteaccess.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +Copyright 2016 Oleg Chernovskiy + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#include "remoteaccess.h" +#include "event_queue.h" +#include "wayland_pointer_p.h" + +#include + +namespace KWayland +{ +namespace Client +{ + +class RemoteAccess::Private +{ +public: + explicit Private(RemoteAccess *q); + void setup(org_kde_kwin_remoteaccess *k); + + WaylandPointer remoteAccess; + EventQueue *queue = nullptr; + +private: + static const struct org_kde_kwin_remoteaccess_listener s_listener; + static void bufferReadyCallback(void *data, org_kde_kwin_remoteaccess *org_kde_kwin_remoteaccess, qint32 gbmHandle, quint32 width, quint32 height, quint32 stride, quint32 format); + + RemoteAccess *q; +}; + +RemoteAccess::RemoteAccess(QObject *parent) + : QObject(parent) + , d(new Private(this)) +{ +} + +RemoteAccess::~RemoteAccess() +{ + release(); +} + +void RemoteAccess::setup(org_kde_kwin_remoteaccess *remoteAccess) +{ + d->setup(remoteAccess); +} + +void RemoteAccess::release() +{ + d->remoteAccess.release(); +} + +void RemoteAccess::destroy() +{ + d->remoteAccess.destroy(); +} + +void RemoteAccess::setEventQueue(EventQueue *queue) +{ + d->queue = queue; +} + +EventQueue *RemoteAccess::eventQueue() +{ + return d->queue; +} + +RemoteAccess::operator org_kde_kwin_remoteaccess*() { + return d->remoteAccess; +} + +RemoteAccess::operator org_kde_kwin_remoteaccess*() const { + return d->remoteAccess; +} + +bool RemoteAccess::isValid() const +{ + return d->remoteAccess.isValid(); +} + +const org_kde_kwin_remoteaccess_listener RemoteAccess::Private::s_listener = { + bufferReadyCallback +}; + +void RemoteAccess::Private::bufferReadyCallback(void *data, org_kde_kwin_remoteaccess *org_kde_kwin_remoteaccess, qint32 gbmHandle, quint32 width, quint32 height, quint32 stride, quint32 format) +{ + Q_UNUSED(org_kde_kwin_remoteaccess) + emit reinterpret_cast(data)->q->bufferReady(gbmHandle, width, height, stride, format); +} + +RemoteAccess::Private::Private(RemoteAccess *q) + : q(q) +{ +} + +void RemoteAccess::Private::setup(org_kde_kwin_remoteaccess *k) +{ + Q_ASSERT(k); + Q_ASSERT(!remoteAccess); + remoteAccess.setup(k); + org_kde_kwin_remoteaccess_add_listener(k, &s_listener, this); +} + +void RemoteAccess::bufferNoLongerNeeded() +{ + org_kde_kwin_remoteaccess_bufferNoLongerNeeded(d->remoteAccess); +} + + +} +} diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -12,6 +12,7 @@ idle_interface.cpp fakeinput_interface.cpp keyboard_interface.cpp + remoteaccess_interface.cpp outputconfiguration_interface.cpp outputchangeset.cpp outputmanagement_interface.cpp @@ -100,6 +101,11 @@ BASENAME server_decoration ) +ecm_add_wayland_server_protocol(SERVER_LIB_SRCS + PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/remoteaccess.xml + BASENAME remoteaccess +) + add_library(KF5WaylandServer ${SERVER_LIB_SRCS}) generate_export_header(KF5WaylandServer BASE_NAME @@ -150,6 +156,7 @@ global.h idle_interface.h keyboard_interface.h + remoteaccess_interface.h outputdevice_interface.h outputchangeset.h outputconfiguration_interface.h diff --git a/src/server/display.h b/src/server/display.h --- a/src/server/display.h +++ b/src/server/display.h @@ -53,6 +53,7 @@ class DataDeviceManagerInterface; class DpmsManagerInterface; class IdleInterface; +class RemoteAccessInterface; class FakeInputInterface; class OutputInterface; class OutputDeviceInterface; @@ -160,6 +161,7 @@ PlasmaWindowManagementInterface *createPlasmaWindowManagement(QObject *parent = nullptr); QtSurfaceExtensionInterface *createQtSurfaceExtension(QObject *parent = nullptr); IdleInterface *createIdle(QObject *parent = nullptr); + RemoteAccessInterface *createRemoteAccess(QObject *parent = nullptr); FakeInputInterface *createFakeInput(QObject *parent = nullptr); ShadowManagerInterface *createShadowManager(QObject *parent = nullptr); BlurManagerInterface *createBlurManager(QObject *parent = nullptr); diff --git a/src/server/display.cpp b/src/server/display.cpp --- a/src/server/display.cpp +++ b/src/server/display.cpp @@ -25,6 +25,7 @@ #include "outputmanagement_interface.h" #include "outputdevice_interface.h" #include "idle_interface.h" +#include "remoteaccess_interface.h" #include "fakeinput_interface.h" #include "logging_p.h" #include "output_interface.h" @@ -278,6 +279,13 @@ return s; } +RemoteAccessInterface *Display::createRemoteAccess(QObject *parent) +{ + auto i = new RemoteAccessInterface(this, parent); + connect(this, &Display::aboutToTerminate, i, [this, i] { delete i; }); + return i; +} + IdleInterface *Display::createIdle(QObject *parent) { auto i = new IdleInterface(this, parent); diff --git a/src/server/remoteaccess_interface.h b/src/server/remoteaccess_interface.h new file mode 100644 --- /dev/null +++ b/src/server/remoteaccess_interface.h @@ -0,0 +1,56 @@ +/**************************************************************************** +Copyright 2016 Oleg Chernovskiy + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#ifndef KWAYLAND_SERVER_KRFB_H +#define KWAYLAND_SERVER_KRFB_H + +#include "global.h" +#include "resource.h" + +#include + +namespace KWayland +{ +namespace Server +{ + +class Display; + +class KWAYLANDSERVER_EXPORT RemoteAccessInterface : public Global +{ + Q_OBJECT +public: + virtual ~RemoteAccessInterface(); + void passBuffer(qint32 gbmHandle, quint32 width, quint32 height, quint32 stride, quint32 format); + bool isBound(); + +Q_SIGNALS: + void bufferNoLongerNeeded(); + +private: + explicit RemoteAccessInterface(Display *display, QObject *parent = nullptr); + friend class Display; + class Private; +}; + + +} +} + +#endif diff --git a/src/server/remoteaccess_interface.cpp b/src/server/remoteaccess_interface.cpp new file mode 100644 --- /dev/null +++ b/src/server/remoteaccess_interface.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +Copyright 2016 Oleg Chernovskiy + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#include "remoteaccess_interface.h" +#include "display.h" +#include "global_p.h" +#include "resource_p.h" + +#include + +namespace KWayland +{ +namespace Server +{ + +class RemoteAccessInterface::Private : public Global::Private +{ +public: + Private(RemoteAccessInterface *q, Display *d); + void passBuffer(qint32 gbmHandle, quint32 width, quint32 height, quint32 stride, quint32 format); + bool bound = false; + +private: + static void bufferNoLongerNeededCallback(wl_client *client, wl_resource *resource); + static void unbind(wl_resource *resource); + static Private *cast(wl_resource *r) { + return reinterpret_cast(wl_resource_get_user_data(r)); + } + void bind(wl_client *client, uint32_t version, uint32_t id) override; + + static const struct org_kde_kwin_remoteaccess_interface s_interface; + static const quint32 s_version; + RemoteAccessInterface *q; + wl_resource *m_resource = nullptr; +}; + +const quint32 RemoteAccessInterface::Private::s_version = 1; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +const struct org_kde_kwin_remoteaccess_interface RemoteAccessInterface::Private::s_interface = { + bufferNoLongerNeededCallback +}; +#endif + +void RemoteAccessInterface::Private::bufferNoLongerNeededCallback(wl_client *client, wl_resource *resource) +{ + Private *p = cast(resource); + emit p->q->bufferNoLongerNeeded(); +} + +RemoteAccessInterface::Private::Private(RemoteAccessInterface *q, Display *d) + : Global::Private(d, &org_kde_kwin_remoteaccess_interface, s_version) + , q(q) +{ +} + +void RemoteAccessInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) +{ + auto c = display->getConnection(client); + wl_resource *resource = c->createResource(&org_kde_kwin_remoteaccess_interface, qMin(version, s_version), id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &s_interface, this, unbind); + m_resource = resource; + bound = true; +} + +void RemoteAccessInterface::Private::unbind(wl_resource *resource) +{ + Private *p = cast(resource); + p->bound = false; +} + +void RemoteAccessInterface::Private::passBuffer(qint32 gbmHandle, quint32 width, quint32 height, quint32 stride, quint32 format) +{ + org_kde_kwin_remoteaccess_send_bufferReady(m_resource, gbmHandle, width, height, stride, format); +} + + +RemoteAccessInterface::RemoteAccessInterface(Display *display, QObject *parent) + : Global(new Private(this, display), parent) +{ +} + +RemoteAccessInterface::~RemoteAccessInterface() = default; + +void RemoteAccessInterface::passBuffer(qint32 gbmHandle, quint32 width, quint32 height, quint32 stride, quint32 format) +{ + Private *priv = reinterpret_cast(d.data()); + priv->passBuffer(gbmHandle, width, height, stride, format); +} + +bool RemoteAccessInterface::isBound() { + Private *priv = reinterpret_cast(d.data()); + return priv->bound; +} + +} +} + diff --git a/src/tools/mapping.txt b/src/tools/mapping.txt --- a/src/tools/mapping.txt +++ b/src/tools/mapping.txt @@ -40,3 +40,4 @@ org_kde_plasma_window;PlasmaWindow org_kde_kwin_server_decoration_manager;ServerSideDecorationManager org_kde_kwin_server_decoration;ServerSideDecoration +org_kde_kwin_remoteaccess;RemoteAccess