diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index bfb268b484..c444510b29 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -23,6 +23,8 @@ set(SERVER_LIB_SRCS plasmawindowmanagement_interface.cpp qtsurfaceextension_interface.cpp region_interface.cpp + relativepointer_interface.cpp + relativepointer_interface_v1.cpp resource.cpp seat_interface.cpp slide_interface.cpp @@ -95,6 +97,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS BASENAME contrast ) +ecm_add_wayland_server_protocol(SERVER_LIB_SRCS + PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/relative-pointer-unstable-v1.xml + BASENAME relativepointer-unstable-v1 +) + ecm_add_wayland_server_protocol(SERVER_LIB_SRCS PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/slide.xml BASENAME slide @@ -180,6 +187,7 @@ install(FILES plasmawindowmanagement_interface.h qtsurfaceextension_interface.h region_interface.h + relativepointer_interface.h resource.h seat_interface.h server_decoration_interface.h diff --git a/src/wayland/autotests/client/test_wayland_registry.cpp b/src/wayland/autotests/client/test_wayland_registry.cpp index 32acff300e..263c22317f 100644 --- a/src/wayland/autotests/client/test_wayland_registry.cpp +++ b/src/wayland/autotests/client/test_wayland_registry.cpp @@ -27,6 +27,7 @@ License along with this library. If not, see . #include "../../src/client/registry.h" #include "../../src/client/output.h" #include "../../src/client/seat.h" +#include "../../src/client/relativepointer.h" #include "../../src/client/server_decoration.h" #include "../../src/client/shell.h" #include "../../src/client/subcompositor.h" @@ -47,6 +48,7 @@ License along with this library. If not, see . #include "../../src/server/outputdevice_interface.h" #include "../../src/server/textinput_interface.h" #include "../../src/server/xdgshell_interface.h" +#include "../../src/server/relativepointer_interface.h" // Wayland #include #include @@ -54,6 +56,7 @@ License along with this library. If not, see . #include #include #include +#include class TestWaylandRegistry : public QObject { @@ -80,6 +83,7 @@ private Q_SLOTS: void testBindTextInputManagerUnstableV0(); void testBindTextInputManagerUnstableV2(); void testBindXdgShellUnstableV5(); + void testBindRelativePointerManagerUnstableV1(); void testGlobalSync(); void testGlobalSyncThreaded(); void testRemoval(); @@ -101,6 +105,7 @@ private: KWayland::Server::TextInputManagerInterface *m_textInputManagerV0; KWayland::Server::TextInputManagerInterface *m_textInputManagerV2; KWayland::Server::XdgShellInterface *m_xdgShellUnstableV5; + KWayland::Server::RelativePointerManagerInterface *m_relativePointerV1; }; static const QString s_socketName = QStringLiteral("kwin-test-wayland-registry-0"); @@ -120,6 +125,7 @@ TestWaylandRegistry::TestWaylandRegistry(QObject *parent) , m_textInputManagerV0(nullptr) , m_textInputManagerV2(nullptr) , m_xdgShellUnstableV5(nullptr) + , m_relativePointerV1(nullptr) { } @@ -161,6 +167,9 @@ void TestWaylandRegistry::init() m_xdgShellUnstableV5 = m_display->createXdgShell(KWayland::Server::XdgShellInterfaceVersion::UnstableV5); m_xdgShellUnstableV5->create(); QCOMPARE(m_xdgShellUnstableV5->interfaceVersion(), KWayland::Server::XdgShellInterfaceVersion::UnstableV5); + m_relativePointerV1 = m_display->createRelativePointerManager(KWayland::Server::RelativePointerInterfaceVersion::UnstableV1); + m_relativePointerV1->create(); + QCOMPARE(m_relativePointerV1->interfaceVersion(), KWayland::Server::RelativePointerInterfaceVersion::UnstableV1); } void TestWaylandRegistry::cleanup() @@ -303,6 +312,11 @@ void TestWaylandRegistry::testBindXdgShellUnstableV5() TEST_BIND(KWayland::Client::Registry::Interface::XdgShellUnstableV5, SIGNAL(xdgShellUnstableV5Announced(quint32,quint32)), bindXdgShellUnstableV5, xdg_shell_destroy) } +void TestWaylandRegistry::testBindRelativePointerManagerUnstableV1() +{ + TEST_BIND(KWayland::Client::Registry::Interface::RelativePointerManagerUnstableV1, SIGNAL(relativePointerManagerUnstableV1Announced(quint32,quint32)), bindRelativePointerManagerUnstableV1, zwp_relative_pointer_manager_v1_destroy) +} + #undef TEST_BIND void TestWaylandRegistry::testRemoval() diff --git a/src/wayland/autotests/client/test_wayland_seat.cpp b/src/wayland/autotests/client/test_wayland_seat.cpp index b414e667ca..390631e06c 100644 --- a/src/wayland/autotests/client/test_wayland_seat.cpp +++ b/src/wayland/autotests/client/test_wayland_seat.cpp @@ -30,6 +30,7 @@ License along with this library. If not, see . #include "../../src/client/pointer.h" #include "../../src/client/surface.h" #include "../../src/client/registry.h" +#include "../../src/client/relativepointer.h" #include "../../src/client/seat.h" #include "../../src/client/shm_pool.h" #include "../../src/client/subcompositor.h" @@ -41,6 +42,7 @@ License along with this library. If not, see . #include "../../src/server/display.h" #include "../../src/server/keyboard_interface.h" #include "../../src/server/pointer_interface.h" +#include "../../src/server/relativepointer_interface.h" #include "../../src/server/seat_interface.h" #include "../../src/server/subcompositor_interface.h" #include "../../src/server/surface_interface.h" @@ -87,11 +89,13 @@ private: KWayland::Server::CompositorInterface *m_compositorInterface; KWayland::Server::SeatInterface *m_seatInterface; KWayland::Server::SubCompositorInterface *m_subCompositorInterface; + KWayland::Server::RelativePointerManagerInterface *m_relativePointerManagerInterface; KWayland::Client::ConnectionThread *m_connection; KWayland::Client::Compositor *m_compositor; KWayland::Client::Seat *m_seat; KWayland::Client::ShmPool *m_shm; KWayland::Client::SubCompositor * m_subCompositor; + KWayland::Client::RelativePointerManager *m_relativePointerManager; KWayland::Client::EventQueue *m_queue; QThread *m_thread; }; @@ -104,11 +108,13 @@ TestWaylandSeat::TestWaylandSeat(QObject *parent) , m_compositorInterface(nullptr) , m_seatInterface(nullptr) , m_subCompositorInterface(nullptr) + , m_relativePointerManagerInterface(nullptr) , m_connection(nullptr) , m_compositor(nullptr) , m_seat(nullptr) , m_shm(nullptr) , m_subCompositor(nullptr) + , m_relativePointerManager(nullptr) , m_queue(nullptr) , m_thread(nullptr) { @@ -134,6 +140,11 @@ void TestWaylandSeat::init() m_subCompositorInterface->create(); QVERIFY(m_subCompositorInterface->isValid()); + m_relativePointerManagerInterface = m_display->createRelativePointerManager(RelativePointerInterfaceVersion::UnstableV1, m_display); + QVERIFY(m_relativePointerManagerInterface); + m_relativePointerManagerInterface->create(); + QVERIFY(m_relativePointerManagerInterface->isValid()); + // setup connection m_connection = new KWayland::Client::ConnectionThread; QSignalSpy connectedSpy(m_connection, SIGNAL(connected())); @@ -182,10 +193,19 @@ void TestWaylandSeat::init() registry.interface(KWayland::Client::Registry::Interface::SubCompositor).version, this); QVERIFY(m_subCompositor->isValid()); + + m_relativePointerManager = registry.createRelativePointerManager(registry.interface(KWayland::Client::Registry::Interface::RelativePointerManagerUnstableV1).name, + registry.interface(KWayland::Client::Registry::Interface::RelativePointerManagerUnstableV1).version, + this); + QVERIFY(m_relativePointerManager->isValid()); } void TestWaylandSeat::cleanup() { + if (m_relativePointerManager) { + delete m_relativePointerManager; + m_relativePointerManager = nullptr; + } if (m_subCompositor) { delete m_subCompositor; m_subCompositor = nullptr; @@ -226,6 +246,9 @@ void TestWaylandSeat::cleanup() delete m_subCompositorInterface; m_subCompositorInterface = nullptr; + delete m_relativePointerManagerInterface; + m_relativePointerManagerInterface = nullptr; + delete m_display; m_display = nullptr; } @@ -342,6 +365,8 @@ void TestWaylandSeat::testPointer() Pointer *p = m_seat->createPointer(m_seat); const Pointer &cp = *p; QVERIFY(p->isValid()); + QScopedPointer relativePointer(m_relativePointerManager->createRelativePointer(p)); + QVERIFY(relativePointer->isValid()); QSignalSpy pointerCreatedSpy(m_seatInterface, SIGNAL(pointerCreated(KWayland::Server::PointerInterface*))); QVERIFY(pointerCreatedSpy.isValid()); // once the pointer is created it should be set as the focused pointer @@ -372,6 +397,9 @@ void TestWaylandSeat::testPointer() QSignalSpy buttonSpy(p, SIGNAL(buttonStateChanged(quint32,quint32,quint32,KWayland::Client::Pointer::ButtonState))); QVERIFY(buttonSpy.isValid()); + QSignalSpy relativeMotionSpy(relativePointer.data(), &RelativePointer::relativeMotion); + QVERIFY(relativeMotionSpy.isValid()); + QVERIFY(!p->enteredSurface()); QVERIFY(!cp.enteredSurface()); m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(10, 15)); @@ -393,6 +421,14 @@ void TestWaylandSeat::testPointer() QCOMPARE(motionSpy.first().first().toPoint(), QPoint(0, 1)); QCOMPARE(motionSpy.first().last().value(), quint32(1)); + // test relative motion + m_seatInterface->relativePointerMotion(QSizeF(1, 2), QSizeF(3, 4), quint64(-1)); + QVERIFY(relativeMotionSpy.wait()); + QCOMPARE(relativeMotionSpy.count(), 1); + QCOMPARE(relativeMotionSpy.first().at(0).toSizeF(), QSizeF(1, 2)); + QCOMPARE(relativeMotionSpy.first().at(1).toSizeF(), QSizeF(3, 4)); + QCOMPARE(relativeMotionSpy.first().at(2).value(), quint64(-1)); + // test axis m_seatInterface->setTimestamp(2); m_seatInterface->pointerAxis(Qt::Horizontal, 10); @@ -460,6 +496,10 @@ void TestWaylandSeat::testPointer() QVERIFY(!p->enteredSurface()); QVERIFY(!cp.enteredSurface()); + // now a relative motion should not be sent to the relative pointer + m_seatInterface->relativePointerMotion(QSizeF(1, 2), QSizeF(3, 4), quint64(-1)); + QVERIFY(!relativeMotionSpy.wait()); + // enter it again m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(0, 0)); QCOMPARE(focusedPointerChangedSpy.count(), 6); @@ -467,6 +507,14 @@ void TestWaylandSeat::testPointer() QCOMPARE(p->enteredSurface(), s); QCOMPARE(cp.enteredSurface(), s); + // send another relative motion event + m_seatInterface->relativePointerMotion(QSizeF(4, 5), QSizeF(6, 7), quint64(1)); + QVERIFY(relativeMotionSpy.wait()); + QCOMPARE(relativeMotionSpy.count(), 2); + QCOMPARE(relativeMotionSpy.last().at(0).toSizeF(), QSizeF(4, 5)); + QCOMPARE(relativeMotionSpy.last().at(1).toSizeF(), QSizeF(6, 7)); + QCOMPARE(relativeMotionSpy.last().at(2).value(), quint64(1)); + // destroy the focused pointer QSignalSpy unboundSpy(serverPointer, &Resource::unbound); QVERIFY(unboundSpy.isValid()); @@ -1368,6 +1416,7 @@ void TestWaylandSeat::testDestroy() connect(m_connection, &ConnectionThread::connectionDied, m_seat, &Seat::destroy); connect(m_connection, &ConnectionThread::connectionDied, m_shm, &ShmPool::destroy); connect(m_connection, &ConnectionThread::connectionDied, m_subCompositor, &SubCompositor::destroy); + connect(m_connection, &ConnectionThread::connectionDied, m_relativePointerManager, &RelativePointerManager::destroy); connect(m_connection, &ConnectionThread::connectionDied, m_queue, &EventQueue::destroy); QVERIFY(m_seat->isValid()); @@ -1378,6 +1427,7 @@ void TestWaylandSeat::testDestroy() m_compositorInterface = nullptr; m_seatInterface = nullptr; m_subCompositorInterface = nullptr; + m_relativePointerManagerInterface = nullptr; QVERIFY(connectionDiedSpy.wait()); // now the seat should be destroyed; diff --git a/src/wayland/display.cpp b/src/wayland/display.cpp index 3a6dc17e7f..5848b933fe 100644 --- a/src/wayland/display.cpp +++ b/src/wayland/display.cpp @@ -35,6 +35,7 @@ License along with this library. If not, see . #include "shadow_interface.h" #include "blur_interface.h" #include "contrast_interface.h" +#include "relativepointer_interface_p.h" #include "server_decoration_interface.h" #include "slide_interface.h" #include "shell_interface.h" @@ -369,6 +370,18 @@ XdgShellInterface *Display::createXdgShell(const XdgShellInterfaceVersion &versi return x; } +RelativePointerManagerInterface *Display::createRelativePointerManager(const RelativePointerInterfaceVersion &version, QObject *parent) +{ + RelativePointerManagerInterface *r = nullptr; + switch (version) { + case RelativePointerInterfaceVersion::UnstableV1: + r = new RelativePointerManagerUnstableV1Interface(this, parent); + break; + } + connect(this, &Display::aboutToTerminate, r, [r] { delete r; }); + return r; +} + void Display::createShm() { Q_ASSERT(d->display); diff --git a/src/wayland/display.h b/src/wayland/display.h index e56aa19794..48ee6c7940 100644 --- a/src/wayland/display.h +++ b/src/wayland/display.h @@ -74,6 +74,8 @@ class TextInputManagerInterface; class XdgShellV5Interface; enum class XdgShellInterfaceVersion; class XdgShellInterface; +enum class RelativePointerInterfaceVersion; +class RelativePointerManagerInterface; /** * @brief Class holding the Wayland server display loop. @@ -189,6 +191,14 @@ public: **/ XdgShellInterface *createXdgShell(const XdgShellInterfaceVersion &version, QObject *parent = nullptr); + /** + * Creates the RelativePointerManagerInterface in interface @p version + * + * @returns The created manager object + * @since 5.28 + **/ + RelativePointerManagerInterface *createRelativePointerManager(const RelativePointerInterfaceVersion &version, 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. diff --git a/src/wayland/pointer_interface.cpp b/src/wayland/pointer_interface.cpp index 8a7472b26b..1e5c6621da 100644 --- a/src/wayland/pointer_interface.cpp +++ b/src/wayland/pointer_interface.cpp @@ -20,6 +20,7 @@ License along with this library. If not, see . #include "pointer_interface.h" #include "pointer_interface_p.h" #include "resource_p.h" +#include "relativepointer_interface_p.h" #include "seat_interface.h" #include "display.h" #include "subcompositor_interface.h" @@ -77,6 +78,16 @@ void PointerInterface::Private::sendLeave(SurfaceInterface *surface, quint32 ser } } +void PointerInterface::Private::registerRelativePointer(RelativePointerInterface *relativePointer) +{ + relativePointers << relativePointer; + QObject::connect(relativePointer, &QObject::destroyed, q, + [this, relativePointer] { + relativePointers.removeOne(relativePointer); + } + ); +} + namespace { static QPointF surfacePosition(SurfaceInterface *surface) { if (surface && surface->subSurface()) { @@ -211,11 +222,28 @@ Cursor *PointerInterface::cursor() const return d->cursor; } +void PointerInterface::relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds) +{ + Q_D(); + if (d->relativePointers.isEmpty()) { + return; + } + for (auto it = d->relativePointers.constBegin(), end = d->relativePointers.constEnd(); it != end; it++) { + (*it)->relativeMotion(delta, deltaNonAccelerated, microseconds); + } + client()->flush(); +} + PointerInterface::Private *PointerInterface::d_func() const { return reinterpret_cast(d.data()); } +PointerInterface *PointerInterface::get(wl_resource *native) +{ + return Private::get(native); +} + Cursor::Private::Private(Cursor *q, PointerInterface *pointer) : pointer(pointer) , q(q) diff --git a/src/wayland/pointer_interface.h b/src/wayland/pointer_interface.h index eb18a0101b..37a98037b0 100644 --- a/src/wayland/pointer_interface.h +++ b/src/wayland/pointer_interface.h @@ -30,6 +30,7 @@ namespace Server { class Cursor; +class RelativePointerManagerUnstableV1Interface; class SeatInterface; class SurfaceInterface; @@ -55,6 +56,12 @@ public: **/ Cursor *cursor() const; + /** + * @returns The PointerInterface for the @p native resource. + * @since 5.28 + **/ + static PointerInterface *get(wl_resource *native); + Q_SIGNALS: /** * Signal emitted whenever the Cursor changes. @@ -66,7 +73,9 @@ private: void buttonPressed(quint32 button, quint32 serial); void buttonReleased(quint32 button, quint32 serial); void axis(Qt::Orientation orientation, quint32 delta); + void relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds); friend class SeatInterface; + friend class RelativePointerManagerUnstableV1Interface; explicit PointerInterface(SeatInterface *parent, wl_resource *parentResource); class Private; Private *d_func() const; diff --git a/src/wayland/pointer_interface_p.h b/src/wayland/pointer_interface_p.h index bbfd7828be..2c29ef1b47 100644 --- a/src/wayland/pointer_interface_p.h +++ b/src/wayland/pointer_interface_p.h @@ -28,6 +28,7 @@ namespace KWayland { namespace Server { +class RelativePointerInterface; class PointerInterface::Private : public Resource::Private { @@ -39,10 +40,13 @@ public: QPointer focusedChildSurface; QMetaObject::Connection destroyConnection; Cursor *cursor = nullptr; + QVector relativePointers; void sendLeave(SurfaceInterface *surface, quint32 serial); void sendEnter(SurfaceInterface *surface, const QPointF &parentSurfacePosition, quint32 serial); + void registerRelativePointer(RelativePointerInterface *relativePointer); + private: PointerInterface *q_func() { return reinterpret_cast(q); diff --git a/src/wayland/seat_interface.cpp b/src/wayland/seat_interface.cpp index 976877ae93..0076d065a7 100644 --- a/src/wayland/seat_interface.cpp +++ b/src/wayland/seat_interface.cpp @@ -846,6 +846,14 @@ quint32 SeatInterface::pointerButtonSerial(quint32 button) const return it.value(); } +void SeatInterface::relativePointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds) +{ + Q_D(); + if (d->globalPointer.focus.pointer && d->globalPointer.focus.surface) { + d->globalPointer.focus.pointer->relativeMotion(delta, deltaNonAccelerated, microseconds); + } +} + void SeatInterface::keyPressed(quint32 key) { Q_D(); diff --git a/src/wayland/seat_interface.h b/src/wayland/seat_interface.h index b5808f4d69..d51678ac6a 100644 --- a/src/wayland/seat_interface.h +++ b/src/wayland/seat_interface.h @@ -367,6 +367,42 @@ public: * @since 5.6 **/ bool hasImplicitPointerGrab(quint32 serial) const; + + /** + * A relative motion is in the same dimension as regular motion events, + * except they do not represent an absolute position. For example, + * moving a pointer from (x, y) to (x', y') would have the equivalent + * relative motion (x' - x, y' - y). If a pointer motion caused the + * absolute pointer position to be clipped by for example the edge of the + * monitor, the relative motion is unaffected by the clipping and will + * represent the unclipped motion. + * + * This method also contains non-accelerated motion deltas (@p deltaNonAccelerated). + * The non-accelerated delta is, when applicable, the regular pointer motion + * delta as it was before having applied motion acceleration and other + * transformations such as normalization. + * + * Note that the non-accelerated delta does not represent 'raw' events as + * they were read from some device. Pointer motion acceleration is device- + * and configuration-specific and non-accelerated deltas and accelerated + * deltas may have the same value on some devices. + * + * Relative motions are not coupled to wl_pointer.motion events (see @link{setPointerPos}, + * and can be sent in combination with such events, but also independently. There may + * also be scenarios where wl_pointer.motion is sent, but there is no + * relative motion. The order of an absolute and relative motion event + * originating from the same physical motion is not guaranteed. + * + * Sending relative pointer events only makes sense if the RelativePointerManagerInterface + * is created on the Display. + * + * @param delta Motion vector + * @param deltaNonAccelerated non-accelerated motion vector + * @param microseconds timestamp with microseconds granularity + * @see setPointerPos + * @since 5.28 + **/ + void relativePointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds); ///@} /** diff --git a/src/wayland/server/relativepointer_interface.cpp b/src/wayland/server/relativepointer_interface.cpp new file mode 100644 index 0000000000..69af3ad99e --- /dev/null +++ b/src/wayland/server/relativepointer_interface.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +Copyright 2016 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 "relativepointer_interface_p.h" + +namespace KWayland +{ +namespace Server +{ + +RelativePointerManagerInterface::Private::Private(RelativePointerInterfaceVersion interfaceVersion, RelativePointerManagerInterface *q, Display *d, const wl_interface *interface, quint32 version) + : Global::Private(d, interface, version) + , interfaceVersion(interfaceVersion) + , q(q) +{ +} + +RelativePointerManagerInterface::RelativePointerManagerInterface(Private *d, QObject *parent) + : Global(d, parent) +{ +} + +RelativePointerManagerInterface::~RelativePointerManagerInterface() = default; + +RelativePointerInterfaceVersion RelativePointerManagerInterface::interfaceVersion() const +{ + Q_D(); + return d->interfaceVersion; +} + +RelativePointerManagerInterface::Private *RelativePointerManagerInterface::d_func() const +{ + return reinterpret_cast(d.data()); +} + +RelativePointerInterface::Private::Private(RelativePointerInterface *q, Global *c, wl_resource *parentResource, const wl_interface *interface, const void *implementation) + : Resource::Private(q, c, parentResource, interface, implementation) +{ +} + +RelativePointerInterface::Private::~Private() +{ + if (resource) { + wl_resource_destroy(resource); + resource = nullptr; + } +} + +RelativePointerInterface::RelativePointerInterface(Private *p, QObject *parent) + : Resource(p, parent) +{ +} + +RelativePointerInterface::~RelativePointerInterface() = default; + +void RelativePointerInterface::relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds) +{ + Q_D(); + d->relativeMotion(delta, deltaNonAccelerated, microseconds); +} + +RelativePointerInterface::Private *RelativePointerInterface::d_func() const +{ + return reinterpret_cast(d.data()); +} + +} +} diff --git a/src/wayland/server/relativepointer_interface.h b/src/wayland/server/relativepointer_interface.h new file mode 100644 index 0000000000..aa8507c814 --- /dev/null +++ b/src/wayland/server/relativepointer_interface.h @@ -0,0 +1,73 @@ +/**************************************************************************** +Copyright 2016 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_RELATIVE_POINTER_H +#define KWAYLAND_SERVER_RELATIVE_POINTER_H + +#include "global.h" + +#include + +namespace KWayland +{ +namespace Server +{ + +class Display; + +enum class RelativePointerInterfaceVersion { + /** + * zwp_relative_pointer_manager_v1 and zwp_relative_pointer_v1 + **/ + UnstableV1 +}; + +/** + * Manager object to create relative pointer interfaces. + * + * Once created the interaction happens through the SeatInterface class + * which automatically delegates relative motion events to the created relative pointer + * interfaces. + * + * @see SeatInterface::relativePointerMotion + * @since 5.28 + **/ +class KWAYLANDSERVER_EXPORT RelativePointerManagerInterface : public Global +{ + Q_OBJECT +public: + virtual ~RelativePointerManagerInterface(); + + /** + * @returns The interface version used by this RelativePointerManagerInterface + **/ + RelativePointerInterfaceVersion interfaceVersion() const; + +protected: + class Private; + explicit RelativePointerManagerInterface(Private *d, QObject *parent = nullptr); + +private: + Private *d_func() const; +}; + +} +} + +#endif diff --git a/src/wayland/server/relativepointer_interface_p.h b/src/wayland/server/relativepointer_interface_p.h new file mode 100644 index 0000000000..a7220a070f --- /dev/null +++ b/src/wayland/server/relativepointer_interface_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +Copyright 2016 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_RELATIVEPOINTER_INTERFACE_P_H +#define KWAYLAND_SERVER_RELATIVEPOINTER_INTERFACE_P_H +#include "relativepointer_interface.h" +#include "resource_p.h" +#include "global_p.h" + + +namespace KWayland +{ +namespace Server +{ + +class RelativePointerManagerInterface::Private : public Global::Private +{ +public: + RelativePointerInterfaceVersion interfaceVersion; + +protected: + Private(RelativePointerInterfaceVersion interfaceVersion, RelativePointerManagerInterface *q, Display *d, const wl_interface *interface, quint32 version); + RelativePointerManagerInterface *q; +}; + +class RelativePointerManagerUnstableV1Interface : public RelativePointerManagerInterface +{ + Q_OBJECT +public: + explicit RelativePointerManagerUnstableV1Interface(Display *display, QObject *parent = nullptr); + virtual ~RelativePointerManagerUnstableV1Interface(); + +private: + class Private; +}; + +class RelativePointerInterface : public Resource +{ + Q_OBJECT +public: + virtual ~RelativePointerInterface(); + void relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds); + +protected: + class Private; + explicit RelativePointerInterface(Private *p, QObject *parent = nullptr); + +private: + Private *d_func() const; +}; + +class RelativePointerInterface::Private : public Resource::Private +{ +public: + ~Private(); + virtual void relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds) = 0; + +protected: + Private(RelativePointerInterface *q, Global *c, wl_resource *parentResource, const wl_interface *interface, const void *implementation); + +private: + RelativePointerInterface *q_func() { + return reinterpret_cast(q); + } +}; + +class RelativePointerUnstableV1Interface : public RelativePointerInterface +{ + Q_OBJECT +public: + virtual ~RelativePointerUnstableV1Interface(); + +private: + explicit RelativePointerUnstableV1Interface(RelativePointerManagerUnstableV1Interface *parent, wl_resource *parentResource); + friend class RelativePointerManagerUnstableV1Interface; + + class Private; + Private *d_func() const; +}; + +} +} + +#endif diff --git a/src/wayland/server/relativepointer_interface_v1.cpp b/src/wayland/server/relativepointer_interface_v1.cpp new file mode 100644 index 0000000000..0358aa24f0 --- /dev/null +++ b/src/wayland/server/relativepointer_interface_v1.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +Copyright 2016 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 "relativepointer_interface_p.h" +#include "display.h" +#include "pointer_interface_p.h" +#include +#include + +namespace KWayland +{ +namespace Server +{ + +class RelativePointerManagerUnstableV1Interface::Private : public RelativePointerManagerInterface::Private +{ +public: + Private(RelativePointerManagerUnstableV1Interface *q, Display *d); + +private: + void bind(wl_client *client, uint32_t version, uint32_t id) override; + + static void unbind(wl_resource *resource); + static Private *cast(wl_resource *r) { + return reinterpret_cast(wl_resource_get_user_data(r)); + } + + static void destroyCallback(wl_client *client, wl_resource *resource); + static void getRelativePointerCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * pointer); + + RelativePointerManagerUnstableV1Interface *q; + + static const struct zwp_relative_pointer_manager_v1_interface s_interface; + static const quint32 s_version; +}; + +const quint32 RelativePointerManagerUnstableV1Interface::Private::s_version = 1; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +const struct zwp_relative_pointer_manager_v1_interface RelativePointerManagerUnstableV1Interface::Private::s_interface = { + destroyCallback, + getRelativePointerCallback +}; +#endif + +void RelativePointerManagerUnstableV1Interface::Private::destroyCallback(wl_client *client, wl_resource *resource) +{ + Q_UNUSED(client) + wl_resource_destroy(resource); +} + +void RelativePointerManagerUnstableV1Interface::Private::getRelativePointerCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *pointer) +{ + PointerInterface *p = PointerInterface::get(pointer); + if (!p) { + // TODO: raise error? + return; + } + auto m = cast(resource); + auto *r = new RelativePointerUnstableV1Interface(m->q, resource); + r->d->create(m->display->getConnection(client), version, id); + p->d_func()->registerRelativePointer(r); +} + +RelativePointerManagerUnstableV1Interface::Private::Private(RelativePointerManagerUnstableV1Interface *q, Display *d) + : RelativePointerManagerInterface::Private(RelativePointerInterfaceVersion::UnstableV1, q, d, &zwp_relative_pointer_manager_v1_interface, s_version) + , q(q) +{ +} + +void RelativePointerManagerUnstableV1Interface::Private::bind(wl_client *client, uint32_t version, uint32_t id) +{ + auto c = display->getConnection(client); + wl_resource *resource = c->createResource(&zwp_relative_pointer_manager_v1_interface, qMin(version, s_version), id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &s_interface, this, unbind); + // TODO: should we track? +} + +void RelativePointerManagerUnstableV1Interface::Private::unbind(wl_resource *resource) +{ + Q_UNUSED(resource) + // TODO: implement? +} + +RelativePointerManagerUnstableV1Interface::RelativePointerManagerUnstableV1Interface(Display *display, QObject *parent) + : RelativePointerManagerInterface(new Private(this, display), parent) +{ +} + +RelativePointerManagerUnstableV1Interface::~RelativePointerManagerUnstableV1Interface() = default; + +class RelativePointerUnstableV1Interface::Private : public RelativePointerInterface::Private +{ +public: + Private(RelativePointerUnstableV1Interface *q, RelativePointerManagerUnstableV1Interface *c, wl_resource *parentResource); + ~Private(); + void relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds) override; + +private: + RelativePointerUnstableV1Interface *q_func() { + return reinterpret_cast(q); + } + + static const struct zwp_relative_pointer_v1_interface s_interface; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +const struct zwp_relative_pointer_v1_interface RelativePointerUnstableV1Interface::Private::s_interface = { + resourceDestroyedCallback +}; +#endif + +RelativePointerUnstableV1Interface::Private::Private(RelativePointerUnstableV1Interface *q, RelativePointerManagerUnstableV1Interface *c, wl_resource *parentResource) + : RelativePointerInterface::Private(q, c, parentResource, &zwp_relative_pointer_v1_interface, &s_interface) +{ +} + +RelativePointerUnstableV1Interface::Private::~Private() = default; + +void RelativePointerUnstableV1Interface::Private::relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds) +{ + if (!resource) { + return; + } + zwp_relative_pointer_v1_send_relative_motion(resource, (microseconds >> 32), microseconds, + wl_fixed_from_double(delta.width()), + wl_fixed_from_double(delta.height()), + wl_fixed_from_double(deltaNonAccelerated.width()), + wl_fixed_from_double(deltaNonAccelerated.height())); +} + +RelativePointerUnstableV1Interface::RelativePointerUnstableV1Interface(RelativePointerManagerUnstableV1Interface *parent, wl_resource *parentResource) + : RelativePointerInterface(new Private(this, parent, parentResource)) +{ +} + +RelativePointerUnstableV1Interface::~RelativePointerUnstableV1Interface() = default; + +} +} diff --git a/src/wayland/tools/mapping.txt b/src/wayland/tools/mapping.txt index 3706952bff..dc71b142e6 100644 --- a/src/wayland/tools/mapping.txt +++ b/src/wayland/tools/mapping.txt @@ -47,3 +47,5 @@ zwp_text_input_manager_v2;TextInputManagerUnstableV2 xdg_shell;XdgShellV5 xdg_surface;XdgSurfaceV5 xdg_popup;XdgPopupV5 +zwp_relative_pointer_manager_v1;RelativePointerManagerUnstableV1 +zwp_relative_pointer_v1;RelativePointerUnstableV1