diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index 18f683fece..1dbf8d286d 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -9,6 +9,7 @@ set(SERVER_LIB_SRCS display.cpp global.cpp idle_interface.cpp + fakeinput_interface.cpp keyboard_interface.cpp logging.cpp output_interface.cpp @@ -45,6 +46,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS BASENAME idle ) +ecm_add_wayland_server_protocol(SERVER_LIB_SRCS + PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/fake-input.xml + BASENAME fake-input +) + add_library(KF5WaylandServer ${SERVER_LIB_SRCS}) generate_export_header(KF5WaylandServer BASE_NAME @@ -88,6 +94,7 @@ install(FILES dataoffer_interface.h datasource_interface.h display.h + fakeinput_interface.h global.h idle_interface.h keyboard_interface.h diff --git a/src/wayland/display.cpp b/src/wayland/display.cpp index 4476673f7a..77632d8a68 100644 --- a/src/wayland/display.cpp +++ b/src/wayland/display.cpp @@ -21,6 +21,7 @@ License along with this library. If not, see . #include "compositor_interface.h" #include "datadevicemanager_interface.h" #include "idle_interface.h" +#include "fakeinput_interface.h" #include "logging_p.h" #include "output_interface.h" #include "plasmashell_interface.h" @@ -255,6 +256,13 @@ IdleInterface *Display::createIdle(QObject *parent) return i; } +FakeInputInterface *Display::createFakeInput(QObject *parent) +{ + auto i = new FakeInputInterface(this, parent); + connect(this, &Display::aboutToTerminate, i, [this, i] { delete i; }); + return i; +} + void Display::createShm() { Q_ASSERT(d->display); diff --git a/src/wayland/display.h b/src/wayland/display.h index 63fb4e9ffe..56dcb6363b 100644 --- a/src/wayland/display.h +++ b/src/wayland/display.h @@ -39,6 +39,7 @@ namespace Server class CompositorInterface; class DataDeviceManagerInterface; class IdleInterface; +class FakeInputInterface; class OutputInterface; class PlasmaShellInterface; class PlasmaWindowManagementInterface; @@ -122,6 +123,7 @@ public: PlasmaWindowManagementInterface *createPlasmaWindowManagement(QObject *parent = nullptr); QtSurfaceExtensionInterface *createQtSurfaceExtension(QObject *parent = nullptr); IdleInterface *createIdle(QObject *parent = nullptr); + FakeInputInterface *createFakeInput(QObject *parent = nullptr); /** * Gets the ClientConnection for the given @p client. diff --git a/src/wayland/fakeinput_interface.cpp b/src/wayland/fakeinput_interface.cpp new file mode 100644 index 0000000000..da95cca5f9 --- /dev/null +++ b/src/wayland/fakeinput_interface.cpp @@ -0,0 +1,215 @@ +/******************************************************************** +Copyright 2015 Martin Gräßlin + +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 "fakeinput_interface.h" +#include "display.h" +#include "global_p.h" + +#include + +#include + +namespace KWayland +{ +namespace Server +{ + +static const quint32 s_version = 1; + +class FakeInputInterface::Private : public Global::Private +{ +public: + Private(FakeInputInterface *q, Display *d); + QList devices; + +private: + void bind(wl_client *client, uint32_t version, uint32_t id) override; + static void authenticateCallback(wl_client *client, wl_resource *resource, const char *application, const char *reason); + static void pointerMotionCallback(wl_client *client, wl_resource *resource, wl_fixed_t delta_x, wl_fixed_t delta_y); + static void buttonCallback(wl_client *client, wl_resource *resource, uint32_t button, uint32_t state); + static void axisCallback(wl_client *client, wl_resource *resource, uint32_t axis, wl_fixed_t value); + + static void unbind(wl_resource *resource); + static Private *cast(wl_resource *r) { + return reinterpret_cast(wl_resource_get_user_data(r)); + } + static FakeInputDevice *device(wl_resource *r); + + FakeInputInterface *q; + static const struct org_kde_kwin_fake_input_interface s_interface; +}; + +class FakeInputDevice::Private +{ +public: + Private(wl_resource *resource, FakeInputInterface *interface, FakeInputDevice *q); + wl_resource *resource; + FakeInputInterface *interface; + bool authenticated = false; + +private: + FakeInputDevice *q; +}; + +const struct org_kde_kwin_fake_input_interface FakeInputInterface::Private::s_interface = { + authenticateCallback, + pointerMotionCallback, + buttonCallback, + axisCallback +}; + +FakeInputInterface::Private::Private(FakeInputInterface *q, Display *d) + : Global::Private(d, &org_kde_kwin_fake_input_interface, s_version) + , q(q) +{ +} + +void FakeInputInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) +{ + auto c = display->getConnection(client); + wl_resource *resource = c->createResource(&org_kde_kwin_fake_input_interface, qMin(version, s_version), id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &s_interface, this, unbind); + FakeInputDevice *device = new FakeInputDevice(resource, q); + devices << device; + QObject::connect(device, &FakeInputDevice::destroyed, q, [device, this] { devices.removeAll(device); }); + emit q->deviceCreated(device); +} + +void FakeInputInterface::Private::unbind(wl_resource *resource) +{ + if (FakeInputDevice *d = device(resource)) { + d->deleteLater(); + } +} + +FakeInputDevice *FakeInputInterface::Private::device(wl_resource *r) +{ + Private *p = cast(r); + auto it = std::find_if(p->devices.constBegin(), p->devices.constEnd(), [r] (FakeInputDevice *device) { return device->resource() == r; } ); + if (it != p->devices.constEnd()) { + return *it; + } + return nullptr; +} + +void FakeInputInterface::Private::authenticateCallback(wl_client *client, wl_resource *resource, const char *application, const char *reason) +{ + Q_UNUSED(client) + FakeInputDevice *d = device(resource); + if (!d) { + return; + } + emit d->authenticationRequested(QString::fromUtf8(application), QString::fromUtf8(reason)); +} + +void FakeInputInterface::Private::pointerMotionCallback(wl_client *client, wl_resource *resource, wl_fixed_t delta_x, wl_fixed_t delta_y) +{ + Q_UNUSED(client) + FakeInputDevice *d = device(resource); + if (!d || !d->isAuthenticated()) { + return; + } + emit d->pointerMotionRequested(QSizeF(wl_fixed_to_double(delta_x), wl_fixed_to_double(delta_y))); +} + +void FakeInputInterface::Private::axisCallback(wl_client *client, wl_resource *resource, uint32_t axis, wl_fixed_t value) +{ + Q_UNUSED(client) + FakeInputDevice *d = device(resource); + if (!d || !d->isAuthenticated()) { + return; + } + Qt::Orientation orientation; + switch (axis) { + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: + orientation = Qt::Horizontal; + break; + case WL_POINTER_AXIS_VERTICAL_SCROLL: + orientation = Qt::Vertical; + break; + default: + // invalid + return; + } + emit d->pointerAxisRequested(orientation, wl_fixed_to_double(value)); +} + +void FakeInputInterface::Private::buttonCallback(wl_client *client, wl_resource *resource, uint32_t button, uint32_t state) +{ + Q_UNUSED(client) + FakeInputDevice *d = device(resource); + if (!d || !d->isAuthenticated()) { + return; + } + switch (state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + emit d->pointerButtonPressRequested(button); + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + emit d->pointerButtonReleaseRequested(button); + break; + default: + // nothing + break; + } +} + +FakeInputInterface::FakeInputInterface(Display *display, QObject *parent) + : Global(new Private(this, display), parent) +{ +} + +FakeInputInterface::~FakeInputInterface() = default; + +FakeInputDevice::Private::Private(wl_resource *resource, FakeInputInterface *interface, FakeInputDevice *q) + : resource(resource) + , interface(interface) + , q(q) +{ +} + +FakeInputDevice::FakeInputDevice(wl_resource *resource, FakeInputInterface *parent) + : QObject(parent) + , d(new Private(resource, parent, this)) +{ +} + +FakeInputDevice::~FakeInputDevice() = default; + +void FakeInputDevice::setAuthentication(bool authenticated) +{ + d->authenticated = authenticated; +} + +wl_resource *FakeInputDevice::resource() +{ + return d->resource; +} + +bool FakeInputDevice::isAuthenticated() const +{ + return d->authenticated; +} + +} +} diff --git a/src/wayland/fakeinput_interface.h b/src/wayland/fakeinput_interface.h new file mode 100644 index 0000000000..670ed8590b --- /dev/null +++ b/src/wayland/fakeinput_interface.h @@ -0,0 +1,80 @@ +/******************************************************************** +Copyright 2015 Martin Gräßlin + +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_FAKEINPUT_INTERFACE_H +#define KWAYLAND_SERVER_FAKEINPUT_INTERFACE_H + +#include +#include "global.h" + +struct wl_resource; + +namespace KWayland +{ +namespace Server +{ + +class Display; +class FakeInputDevice; + +class KWAYLANDSERVER_EXPORT FakeInputInterface : public Global +{ + Q_OBJECT +public: + virtual ~FakeInputInterface(); + +Q_SIGNALS: + void deviceCreated(KWayland::Server::FakeInputDevice *device); + +private: + explicit FakeInputInterface(Display *display, QObject *parent = nullptr); + friend class Display; + class Private; +}; + +class KWAYLANDSERVER_EXPORT FakeInputDevice : public QObject +{ + Q_OBJECT +public: + virtual ~FakeInputDevice(); + wl_resource *resource(); + + void setAuthentication(bool authenticated); + bool isAuthenticated() const; + +Q_SIGNALS: + void authenticationRequested(const QString &application, const QString &reason); + void pointerMotionRequested(const QSizeF &delta); + void pointerButtonPressRequested(quint32 button); + void pointerButtonReleaseRequested(quint32 button); + void pointerAxisRequested(Qt::Orientation orientation, qreal delta); + +private: + friend class FakeInputInterface; + FakeInputDevice(wl_resource *resource, FakeInputInterface *parent); + class Private; + QScopedPointer d; +}; + +} +} + +Q_DECLARE_METATYPE(KWayland::Server::FakeInputDevice*) + +#endif