From bb7065be3db7b9e2e02b5e8804b022d0ef3831df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 24 Mar 2015 14:48:53 +0100 Subject: [PATCH] [client] Add Touch Basic support for handling touch events on Client side. --- src/wayland/tests/CMakeLists.txt | 3 + src/wayland/tests/touchclienttest.cpp | 258 ++++++++++++++++++++++++++ src/wayland/tests/touchclienttest.h | 67 +++++++ 3 files changed, 328 insertions(+) create mode 100644 src/wayland/tests/touchclienttest.cpp create mode 100644 src/wayland/tests/touchclienttest.h diff --git a/src/wayland/tests/CMakeLists.txt b/src/wayland/tests/CMakeLists.txt index 9dc0ec7e36..c41b7a3a5a 100644 --- a/src/wayland/tests/CMakeLists.txt +++ b/src/wayland/tests/CMakeLists.txt @@ -29,3 +29,6 @@ if (Qt5Concurrent_FOUND) target_link_libraries(pasteClient Qt5::Concurrent KF5::WaylandClient) ecm_mark_as_test(pasteClient) endif() + +add_executable(touchClientTest touchclienttest.cpp) +target_link_libraries(touchClientTest KF5::WaylandClient) diff --git a/src/wayland/tests/touchclienttest.cpp b/src/wayland/tests/touchclienttest.cpp new file mode 100644 index 0000000000..fb9e4a096f --- /dev/null +++ b/src/wayland/tests/touchclienttest.cpp @@ -0,0 +1,258 @@ +/******************************************************************** +Copyright 2014, 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 "touchclienttest.h" +// KWin::Wayland +#include <../src/client/buffer.h> +#include <../src/client/compositor.h> +#include <../src/client/connection_thread.h> +#include <../src/client/event_queue.h> +#include <../src/client/keyboard.h> +#include <../src/client/output.h> +#include <../src/client/pointer.h> +#include <../src/client/registry.h> +#include <../src/client/seat.h> +#include <../src/client/shell.h> +#include <../src/client/shm_pool.h> +#include <../src/client/surface.h> +#include <../src/client/touch.h> +// Qt +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace KWayland::Client; + +static Qt::GlobalColor s_colors[] = { + Qt::white, + Qt::red, + Qt::green, + Qt::blue, + Qt::black +}; +static int s_colorIndex = 0; + +WaylandClientTest::WaylandClientTest(QObject *parent) + : QObject(parent) + , m_connectionThread(new QThread(this)) + , m_connectionThreadObject(new ConnectionThread(nullptr)) + , m_eventQueue(nullptr) + , m_compositor(nullptr) + , m_output(nullptr) + , m_surface(nullptr) + , m_shm(nullptr) + , m_timer(new QTimer(this)) +{ + init(); +} + +WaylandClientTest::~WaylandClientTest() +{ + m_connectionThread->quit(); + m_connectionThread->wait(); + m_connectionThreadObject->deleteLater(); +} + +void WaylandClientTest::init() +{ + connect(m_connectionThreadObject, &ConnectionThread::connected, this, + [this]() { + // create the event queue for the main gui thread + m_eventQueue = new EventQueue(this); + m_eventQueue->setup(m_connectionThreadObject); + // setup registry + Registry *registry = new Registry(this); + setupRegistry(registry); + }, + Qt::QueuedConnection); + + m_connectionThreadObject->moveToThread(m_connectionThread); + m_connectionThread->start(); + + m_connectionThreadObject->initConnection(); + + connect(m_timer, &QTimer::timeout, this, + [this]() { + s_colorIndex = (s_colorIndex + 1) % 5; + render(); + } + ); + m_timer->setInterval(1000); + m_timer->start(); +} + +void WaylandClientTest::setupRegistry(Registry *registry) +{ + connect(registry, &Registry::compositorAnnounced, this, + [this, registry](quint32 name) { + m_compositor = registry->createCompositor(name, 1, this); + m_surface = m_compositor->createSurface(this); + } + ); + connect(registry, &Registry::shellAnnounced, this, + [this, registry](quint32 name) { + Shell *shell = registry->createShell(name, 1, this); + ShellSurface *shellSurface = shell->createSurface(m_surface, m_surface); + shellSurface->setToplevel(); + render(QSize(400, 200)); + } + ); + connect(registry, &Registry::outputAnnounced, this, + [this, registry](quint32 name) { + if (m_output) { + return; + } + m_output = registry->createOutput(name, 2, this); + } + ); + connect(registry, &Registry::shmAnnounced, this, + [this, registry](quint32 name) { + m_shm = registry->createShmPool(name, 1, this); + } + ); + connect(registry, &Registry::seatAnnounced, this, + [this, registry](quint32 name) { + Seat *s = registry->createSeat(name, 2, this); + connect(s, &Seat::hasKeyboardChanged, this, + [this, s](bool has) { + if (!has) { + return; + } + Keyboard *k = s->createKeyboard(this); + connect(k, &Keyboard::keyChanged, this, + [this](quint32 key, Keyboard::KeyState state) { + if (key == KEY_Q && state == Keyboard::KeyState::Released) { + QCoreApplication::instance()->quit(); + } + } + ); + } + ); + connect(s, &Seat::hasPointerChanged, this, + [this, s](bool has) { + if (!has) { + return; + } + Pointer *p = s->createPointer(this); + connect(p, &Pointer::buttonStateChanged, this, + [this](quint32 serial, quint32 time, quint32 button, Pointer::ButtonState state) { + Q_UNUSED(serial) + Q_UNUSED(time) + if (state == Pointer::ButtonState::Released) { + if (button == BTN_LEFT) { + if (m_timer->isActive()) { + m_timer->stop(); + } else { + m_timer->start(); + } + } + if (button == BTN_RIGHT) { + QCoreApplication::instance()->quit(); + } + } + } + ); + } + ); + connect(s, &Seat::hasTouchChanged, this, + [this, s](bool has) { + if (!has) { + return; + } + Touch *t = s->createTouch(this); + connect(t, &Touch::sequenceStarted, this, + [] (KWayland::Client::TouchPoint *startPoint) { + qDebug() << "Touch sequence started at" << startPoint->position() << "with id" << startPoint->id(); + } + ); + connect(t, &Touch::sequenceCanceled, this, + [] () { + qDebug() << "Touch sequence canceled"; + } + ); + connect(t, &Touch::sequenceEnded, this, + [] () { + qDebug() << "Touch sequence finished"; + } + ); + connect(t, &Touch::frameEnded, this, + [] () { + qDebug() << "End of touch contact point list"; + } + ); + connect(t, &Touch::pointAdded, this, + [] (KWayland::Client::TouchPoint *point) { + qDebug() << "Touch point added at" << point->position() << "with id" << point->id(); + } + ); + connect(t, &Touch::pointRemoved, this, + [] (KWayland::Client::TouchPoint *point) { + qDebug() << "Touch point " << point->id() << " removed at" << point->position(); + } + ); + connect(t, &Touch::pointMoved, this, + [] (KWayland::Client::TouchPoint *point) { + qDebug() << "Touch point " << point->id() << " moved to" << point->position(); + } + ); + } + ); + } + ); + registry->create(m_connectionThreadObject->display()); + registry->setEventQueue(m_eventQueue); + registry->setup(); +} + +void WaylandClientTest::render(const QSize &size) +{ + m_currentSize = size; + render(); +} + +void WaylandClientTest::render() +{ + if (!m_shm || !m_surface || !m_surface->isValid() || !m_currentSize.isValid()) { + return; + } + auto buffer = m_shm->getBuffer(m_currentSize, m_currentSize.width() * 4).toStrongRef(); + buffer->setUsed(true); + QImage image(buffer->address(), m_currentSize.width(), m_currentSize.height(), QImage::Format_ARGB32_Premultiplied); + image.fill(s_colors[s_colorIndex]); + + m_surface->attachBuffer(*buffer); + m_surface->damage(QRect(QPoint(0, 0), m_currentSize)); + m_surface->commit(Surface::CommitFlag::None); + buffer->setUsed(false); +} + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + new WaylandClientTest(&app); + + return app.exec(); +} diff --git a/src/wayland/tests/touchclienttest.h b/src/wayland/tests/touchclienttest.h new file mode 100644 index 0000000000..963089de7b --- /dev/null +++ b/src/wayland/tests/touchclienttest.h @@ -0,0 +1,67 @@ +/******************************************************************** +Copyright 2014, 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 WAYLANDCLIENTTEST_H +#define WAYLANDCLIENTTEST_H + +#include +#include + +namespace KWayland +{ +namespace Client +{ +class Compositor; +class ConnectionThread; +class EventQueue; +class Output; +class Registry; +class ShmPool; +class Surface; +} +} + +class QThread; +class QTimer; + +class WaylandClientTest : public QObject +{ + Q_OBJECT +public: + explicit WaylandClientTest(QObject *parent = nullptr); + virtual ~WaylandClientTest(); + +private: + void init(); + void render(const QSize &size); + void render(); + void setupRegistry(KWayland::Client::Registry *registry); + void toggleTimer(); + QThread *m_connectionThread; + KWayland::Client::ConnectionThread *m_connectionThreadObject; + KWayland::Client::EventQueue *m_eventQueue; + KWayland::Client::Compositor *m_compositor; + KWayland::Client::Output *m_output; + KWayland::Client::Surface *m_surface; + KWayland::Client::ShmPool *m_shm; + QSize m_currentSize; + QTimer *m_timer; +}; + +#endif