Provide an implementation for the tablet interface
Summary: Implements the necessary classes to have proper support for the tablet and pen. Doesn't implement yet the ring/slider/totem bits. Test Plan: Used it with Plasma and GTK clients, together with the kwin patch I'll submit soon. https://youtu.be/GGx0TlNJlzs Also I added a test. Reviewers: #kwin, #frameworks, zzag, davidedmundson Reviewed By: #kwin, zzag, davidedmundson Subscribers: davidedmundson, zzag, kde-frameworks-devel Tags: #frameworks Differential Revision: https://phabricator.kde.org/D26858
This commit is contained in:
parent
74edaa85df
commit
d4dad00b52
7 changed files with 1052 additions and 23 deletions
|
@ -50,6 +50,7 @@ set(SERVER_LIB_SRCS
|
|||
subcompositor_interface.cpp
|
||||
surface_interface.cpp
|
||||
surfacerole.cpp
|
||||
tablet_interface.cpp
|
||||
textinput_interface.cpp
|
||||
textinput_interface_v0.cpp
|
||||
textinput_interface_v2.cpp
|
||||
|
@ -228,6 +229,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
|
|||
BASENAME linux-dmabuf-unstable-v1
|
||||
)
|
||||
|
||||
ecm_add_qtwayland_server_protocol(SERVER_LIB_SRCS
|
||||
PROTOCOL ${WaylandProtocols_DATADIR}/unstable/tablet/tablet-unstable-v2.xml
|
||||
BASENAME tablet-unstable-v2
|
||||
)
|
||||
|
||||
set(SERVER_GENERATED_SRCS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-client-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-server-protocol.h
|
||||
|
@ -285,6 +291,8 @@ set(SERVER_GENERATED_SRCS
|
|||
${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-shell-server-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-shell-v6-client-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-shell-v6-server-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-tablet-unstable-v2.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-tablet-unstable-v2.cpp
|
||||
)
|
||||
|
||||
set_source_files_properties(${SERVER_GENERATED_SRCS} PROPERTIES SKIP_AUTOMOC ON)
|
||||
|
@ -369,6 +377,7 @@ set(SERVER_LIB_HEADERS
|
|||
slide_interface.h
|
||||
subcompositor_interface.h
|
||||
surface_interface.h
|
||||
tablet_interface.h
|
||||
textinput_interface.h
|
||||
touch_interface.h
|
||||
xdgdecoration_interface.h
|
||||
|
|
|
@ -45,3 +45,15 @@ add_executable(testNoXdgRuntimeDir test_no_xdg_runtime_dir.cpp)
|
|||
target_link_libraries( testNoXdgRuntimeDir Qt5::Test KF5::WaylandServer)
|
||||
add_test(NAME kwayland-testNoXdgRuntimeDir COMMAND testNoXdgRuntimeDir)
|
||||
ecm_mark_as_test(testNoXdgRuntimeDir)
|
||||
|
||||
########################################################
|
||||
# Test Tablet Interface
|
||||
########################################################
|
||||
ecm_add_qtwayland_client_protocol(TABLET_SRCS
|
||||
PROTOCOL ${WaylandProtocols_DATADIR}/unstable/tablet/tablet-unstable-v2.xml
|
||||
BASENAME tablet-unstable-v2
|
||||
)
|
||||
add_executable(testTabletInterface test_tablet_interface.cpp ${TABLET_SRCS})
|
||||
target_link_libraries( testTabletInterface Qt5::Test KF5::WaylandServer KF5::WaylandClient Wayland::Client)
|
||||
add_test(NAME kwayland-testTabletInterface COMMAND testTabletInterface)
|
||||
ecm_mark_as_test(testTabletInterface)
|
||||
|
|
296
src/wayland/autotests/server/test_tablet_interface.cpp
Normal file
296
src/wayland/autotests/server/test_tablet_interface.cpp
Normal file
|
@ -0,0 +1,296 @@
|
|||
/********************************************************************
|
||||
Copyright 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
// Qt
|
||||
#include <QHash>
|
||||
#include <QThread>
|
||||
#include <QtTest>
|
||||
// WaylandServer
|
||||
#include "../../src/server/compositor_interface.h"
|
||||
#include "../../src/server/display.h"
|
||||
#include "../../src/server/seat_interface.h"
|
||||
#include "../../src/server/tablet_interface.h"
|
||||
|
||||
#include "../../src/client/compositor.h"
|
||||
#include "../../src/client/connection_thread.h"
|
||||
#include "../../src/client/event_queue.h"
|
||||
#include "../../src/client/registry.h"
|
||||
#include "../../src/client/seat.h"
|
||||
|
||||
#include "qwayland-tablet-unstable-v2.h"
|
||||
|
||||
using namespace KWayland::Server;
|
||||
|
||||
class Tablet : public QtWayland::zwp_tablet_v2
|
||||
{
|
||||
public:
|
||||
Tablet(::zwp_tablet_v2 *t)
|
||||
: QtWayland::zwp_tablet_v2(t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Tool : public QObject, public QtWayland::zwp_tablet_tool_v2
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Tool(::zwp_tablet_tool_v2 *t)
|
||||
: QtWayland::zwp_tablet_tool_v2(t)
|
||||
{
|
||||
}
|
||||
|
||||
void zwp_tablet_tool_v2_proximity_in(uint32_t /*serial*/, struct ::zwp_tablet_v2 * /*tablet*/, struct ::wl_surface *surface) override
|
||||
{
|
||||
surfaceApproximated[surface]++;
|
||||
}
|
||||
|
||||
void zwp_tablet_tool_v2_frame(uint32_t time) override
|
||||
{
|
||||
Q_EMIT frame(time);
|
||||
}
|
||||
|
||||
QHash<struct ::wl_surface *, int> surfaceApproximated;
|
||||
Q_SIGNALS:
|
||||
void frame(quint32 time);
|
||||
};
|
||||
|
||||
class TabletSeat : public QObject, public QtWayland::zwp_tablet_seat_v2
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TabletSeat(::zwp_tablet_seat_v2 *seat)
|
||||
: QtWayland::zwp_tablet_seat_v2(seat)
|
||||
{
|
||||
}
|
||||
|
||||
void zwp_tablet_seat_v2_tablet_added(struct ::zwp_tablet_v2 *id) override
|
||||
{
|
||||
m_tablets << new Tablet(id);
|
||||
Q_EMIT tabletAdded();
|
||||
}
|
||||
void zwp_tablet_seat_v2_tool_added(struct ::zwp_tablet_tool_v2 *id) override
|
||||
{
|
||||
m_tools << new Tool(id);
|
||||
Q_EMIT toolAdded();
|
||||
}
|
||||
|
||||
QVector<Tablet *> m_tablets;
|
||||
QVector<Tool *> m_tools;
|
||||
|
||||
Q_SIGNALS:
|
||||
void toolAdded();
|
||||
void tabletAdded();
|
||||
};
|
||||
|
||||
class TestTabletInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestTabletInterface()
|
||||
{
|
||||
}
|
||||
~TestTabletInterface() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void testAdd();
|
||||
void testInteractSimple();
|
||||
void testInteractSurfaceChange();
|
||||
|
||||
private:
|
||||
KWayland::Client::ConnectionThread *m_connection;
|
||||
KWayland::Client::EventQueue *m_queue;
|
||||
KWayland::Client::Compositor *m_clientCompositor;
|
||||
KWayland::Client::Seat *m_clientSeat = nullptr;
|
||||
|
||||
QThread *m_thread;
|
||||
Display m_display;
|
||||
SeatInterface *m_seat;
|
||||
CompositorInterface *m_serverCompositor;
|
||||
|
||||
TabletSeat *m_tabletSeatClient = nullptr;
|
||||
TabletManagerInterface *m_tabletManager;
|
||||
|
||||
TabletInterface *m_tablet;
|
||||
TabletToolInterface *m_tool;
|
||||
|
||||
QVector<SurfaceInterface *> m_surfaces;
|
||||
};
|
||||
|
||||
static const QString s_socketName = QStringLiteral("kwin-wayland-server-tablet-test-0");
|
||||
|
||||
void TestTabletInterface::initTestCase()
|
||||
{
|
||||
m_display.setSocketName(s_socketName);
|
||||
m_display.start();
|
||||
QVERIFY(m_display.isRunning());
|
||||
|
||||
m_seat = m_display.createSeat(this);
|
||||
m_seat->create();
|
||||
m_serverCompositor = m_display.createCompositor(this);
|
||||
m_serverCompositor->create();
|
||||
m_tabletManager = m_display.createTabletManagerInterface(this);
|
||||
QVERIFY(m_serverCompositor->isValid());
|
||||
connect(m_serverCompositor, &CompositorInterface::surfaceCreated, this, [this](SurfaceInterface *surface) {
|
||||
m_surfaces += surface;
|
||||
});
|
||||
|
||||
// setup connection
|
||||
m_connection = new KWayland::Client::ConnectionThread;
|
||||
QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
|
||||
m_connection->setSocketName(s_socketName);
|
||||
|
||||
m_thread = new QThread(this);
|
||||
m_connection->moveToThread(m_thread);
|
||||
m_thread->start();
|
||||
|
||||
m_connection->initConnection();
|
||||
QVERIFY(connectedSpy.wait());
|
||||
QVERIFY(!m_connection->connections().isEmpty());
|
||||
|
||||
m_queue = new KWayland::Client::EventQueue(this);
|
||||
QVERIFY(!m_queue->isValid());
|
||||
m_queue->setup(m_connection);
|
||||
QVERIFY(m_queue->isValid());
|
||||
|
||||
auto registry = new KWayland::Client::Registry(this);
|
||||
connect(registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, registry](const QByteArray &interface, quint32 name, quint32 version) {
|
||||
if (interface == "zwp_tablet_manager_v2") {
|
||||
auto tabletClient = new QtWayland::zwp_tablet_manager_v2(registry->registry(), name, version);
|
||||
auto _seat = tabletClient->get_tablet_seat(*m_clientSeat);
|
||||
m_tabletSeatClient = new TabletSeat(_seat);
|
||||
}
|
||||
});
|
||||
connect(registry, &KWayland::Client::Registry::seatAnnounced, this, [this, registry](quint32 name, quint32 version) {
|
||||
m_clientSeat = registry->createSeat(name, version);
|
||||
});
|
||||
registry->setEventQueue(m_queue);
|
||||
QSignalSpy compositorSpy(registry, &KWayland::Client::Registry::compositorAnnounced);
|
||||
registry->create(m_connection->display());
|
||||
QVERIFY(registry->isValid());
|
||||
registry->setup();
|
||||
wl_display_flush(m_connection->display());
|
||||
|
||||
QVERIFY(compositorSpy.wait());
|
||||
m_clientCompositor = registry->createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
|
||||
QVERIFY(m_clientCompositor->isValid());
|
||||
|
||||
QSignalSpy surfaceSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
m_clientCompositor->createSurface(this);
|
||||
}
|
||||
QVERIFY(surfaceSpy.count() < 3 && surfaceSpy.wait(200));
|
||||
QVERIFY(m_surfaces.count() == 3);
|
||||
QVERIFY(m_tabletSeatClient);
|
||||
}
|
||||
|
||||
TestTabletInterface::~TestTabletInterface()
|
||||
{
|
||||
if (m_queue) {
|
||||
delete m_queue;
|
||||
m_queue = nullptr;
|
||||
}
|
||||
if (m_thread) {
|
||||
m_thread->quit();
|
||||
m_thread->wait();
|
||||
delete m_thread;
|
||||
m_thread = nullptr;
|
||||
}
|
||||
delete m_tabletSeatClient;
|
||||
m_connection->deleteLater();
|
||||
m_connection = nullptr;
|
||||
}
|
||||
|
||||
void TestTabletInterface::testAdd()
|
||||
{
|
||||
TabletSeatInterface *seatInterface = m_tabletManager->seat(m_seat);
|
||||
QVERIFY(seatInterface);
|
||||
|
||||
QSignalSpy tabletSpy(m_tabletSeatClient, &TabletSeat::tabletAdded);
|
||||
m_tablet = seatInterface->addTablet(1, 2, QStringLiteral("event33"), QStringLiteral("my tablet"), {QStringLiteral("/test/event33")});
|
||||
QVERIFY(m_tablet);
|
||||
QVERIFY(tabletSpy.wait() || tabletSpy.count() == 1);
|
||||
QCOMPARE(m_tabletSeatClient->m_tablets.count(), 1);
|
||||
|
||||
QSignalSpy toolSpy(m_tabletSeatClient, &TabletSeat::toolAdded);
|
||||
m_tool = seatInterface->addTool(KWayland::Server::TabletToolInterface::Pen, 0, 0, {TabletToolInterface::Tilt, TabletToolInterface::Pressure});
|
||||
QVERIFY(m_tool);
|
||||
QVERIFY(toolSpy.wait() || toolSpy.count() == 1);
|
||||
QCOMPARE(m_tabletSeatClient->m_tools.count(), 1);
|
||||
|
||||
QVERIFY(!m_tool->isClientSupported()); //There's no surface in it yet
|
||||
m_tool->setCurrentSurface(nullptr);
|
||||
QVERIFY(!m_tool->isClientSupported()); //There's no surface in it
|
||||
|
||||
QCOMPARE(m_surfaces.count(), 3);
|
||||
for (SurfaceInterface *surface : m_surfaces) {
|
||||
m_tool->setCurrentSurface(surface);
|
||||
}
|
||||
m_tool->setCurrentSurface(nullptr);
|
||||
}
|
||||
|
||||
static uint s_serial = 0;
|
||||
void TestTabletInterface::testInteractSimple()
|
||||
{
|
||||
QSignalSpy frameSpy(m_tabletSeatClient->m_tools[0], &Tool::frame);
|
||||
|
||||
QVERIFY(!m_tool->isClientSupported());
|
||||
m_tool->setCurrentSurface(m_surfaces[0]);
|
||||
QVERIFY(m_tool->isClientSupported() && m_tablet->isSurfaceSupported(m_surfaces[0]));
|
||||
m_tool->sendProximityIn(m_tablet);
|
||||
m_tool->sendPressure(0);
|
||||
m_tool->sendFrame(s_serial++);
|
||||
m_tool->sendMotion({3, 3});
|
||||
m_tool->sendFrame(s_serial++);
|
||||
m_tool->sendProximityOut();
|
||||
QVERIFY(m_tool->isClientSupported());
|
||||
m_tool->sendFrame(s_serial++);
|
||||
QVERIFY(!m_tool->isClientSupported());
|
||||
|
||||
QVERIFY(frameSpy.wait(500));
|
||||
QCOMPARE(m_tabletSeatClient->m_tools[0]->surfaceApproximated.count(), 1);
|
||||
}
|
||||
|
||||
void TestTabletInterface::testInteractSurfaceChange()
|
||||
{
|
||||
m_tabletSeatClient->m_tools[0]->surfaceApproximated.clear();
|
||||
QSignalSpy frameSpy(m_tabletSeatClient->m_tools[0], &Tool::frame);
|
||||
QVERIFY(!m_tool->isClientSupported());
|
||||
m_tool->setCurrentSurface(m_surfaces[0]);
|
||||
QVERIFY(m_tool->isClientSupported() && m_tablet->isSurfaceSupported(m_surfaces[0]));
|
||||
m_tool->sendProximityIn(m_tablet);
|
||||
m_tool->sendPressure(0);
|
||||
m_tool->sendFrame(s_serial++);
|
||||
|
||||
m_tool->setCurrentSurface(m_surfaces[1]);
|
||||
QVERIFY(m_tool->isClientSupported());
|
||||
|
||||
m_tool->sendMotion({3, 3});
|
||||
m_tool->sendFrame(s_serial++);
|
||||
m_tool->sendProximityOut();
|
||||
QVERIFY(m_tool->isClientSupported());
|
||||
m_tool->sendFrame(s_serial++);
|
||||
QVERIFY(!m_tool->isClientSupported());
|
||||
|
||||
QVERIFY(frameSpy.wait(500));
|
||||
QCOMPARE(m_tabletSeatClient->m_tools[0]->surfaceApproximated.count(), 2);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(TestTabletInterface)
|
||||
#include "test_tablet_interface.moc"
|
|
@ -5,45 +5,46 @@
|
|||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
#include "display.h"
|
||||
#include "appmenu_interface.h"
|
||||
#include "blur_interface.h"
|
||||
#include "compositor_interface.h"
|
||||
#include "contrast_interface.h"
|
||||
#include "datadevicemanager_interface.h"
|
||||
#include "dpms_interface.h"
|
||||
#include "outputconfiguration_interface.h"
|
||||
#include "outputmanagement_interface.h"
|
||||
#include "outputdevice_interface.h"
|
||||
#include "eglstream_controller_interface.h"
|
||||
#include "fakeinput_interface.h"
|
||||
#include "idle_interface.h"
|
||||
#include "idleinhibit_interface_p.h"
|
||||
#include "remote_access_interface.h"
|
||||
#include "fakeinput_interface.h"
|
||||
#include "keystate_interface.h"
|
||||
#include "linuxdmabuf_v1_interface.h"
|
||||
#include "logging.h"
|
||||
#include "output_interface.h"
|
||||
#include "outputconfiguration_interface.h"
|
||||
#include "outputdevice_interface.h"
|
||||
#include "outputmanagement_interface.h"
|
||||
#include "plasmashell_interface.h"
|
||||
#include "plasmavirtualdesktop_interface.h"
|
||||
#include "plasmawindowmanagement_interface.h"
|
||||
#include "pointerconstraints_interface_p.h"
|
||||
#include "pointergestures_interface_p.h"
|
||||
#include "qtsurfaceextension_interface.h"
|
||||
#include "seat_interface.h"
|
||||
#include "shadow_interface.h"
|
||||
#include "blur_interface.h"
|
||||
#include "contrast_interface.h"
|
||||
#include "relativepointer_interface_p.h"
|
||||
#include "remote_access_interface.h"
|
||||
#include "seat_interface.h"
|
||||
#include "server_decoration_interface.h"
|
||||
#include "slide_interface.h"
|
||||
#include "shell_interface.h"
|
||||
#include "subcompositor_interface.h"
|
||||
#include "textinput_interface_p.h"
|
||||
#include "xdgshell_v5_interface_p.h"
|
||||
#include "xdgforeign_interface.h"
|
||||
#include "xdgshell_v6_interface_p.h"
|
||||
#include "xdgshell_stable_interface_p.h"
|
||||
#include "appmenu_interface.h"
|
||||
#include "server_decoration_palette_interface.h"
|
||||
#include "plasmavirtualdesktop_interface.h"
|
||||
#include "xdgoutput_interface.h"
|
||||
#include "shadow_interface.h"
|
||||
#include "shell_interface.h"
|
||||
#include "slide_interface.h"
|
||||
#include "subcompositor_interface.h"
|
||||
#include "tablet_interface.h"
|
||||
#include "textinput_interface_p.h"
|
||||
#include "xdgdecoration_interface.h"
|
||||
#include "eglstream_controller_interface.h"
|
||||
#include "keystate_interface.h"
|
||||
#include "linuxdmabuf_v1_interface.h"
|
||||
#include "xdgforeign_interface.h"
|
||||
#include "xdgoutput_interface.h"
|
||||
#include "xdgshell_stable_interface_p.h"
|
||||
#include "xdgshell_v5_interface_p.h"
|
||||
#include "xdgshell_v6_interface_p.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
@ -523,6 +524,13 @@ KeyStateInterface *Display::createKeyStateInterface(QObject *parent)
|
|||
return d;
|
||||
}
|
||||
|
||||
TabletManagerInterface *Display::createTabletManagerInterface(QObject *parent)
|
||||
{
|
||||
auto d = new TabletManagerInterface(this, parent);
|
||||
connect(this, &Display::aboutToTerminate, d, [d] { delete d; });
|
||||
return d;
|
||||
}
|
||||
|
||||
void Display::createShm()
|
||||
{
|
||||
Q_ASSERT(d->display);
|
||||
|
|
|
@ -79,6 +79,7 @@ class XdgDecorationManagerInterface;
|
|||
class EglStreamControllerInterface;
|
||||
class KeyStateInterface;
|
||||
class LinuxDmabufUnstableV1Interface;
|
||||
class TabletManagerInterface;
|
||||
|
||||
/**
|
||||
* @brief Class holding the Wayland server display loop.
|
||||
|
@ -310,6 +311,13 @@ public:
|
|||
*/
|
||||
EglStreamControllerInterface *createEglStreamControllerInterface(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* Creates the entry point to support wacom-like tablets and pens.
|
||||
*
|
||||
* @since 5.67
|
||||
*/
|
||||
TabletManagerInterface *createTabletManagerInterface(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.
|
||||
|
|
502
src/wayland/server/tablet_interface.cpp
Normal file
502
src/wayland/server/tablet_interface.cpp
Normal file
|
@ -0,0 +1,502 @@
|
|||
/********************************************************************
|
||||
Copyright 2019 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#include "tablet_interface.h"
|
||||
#include "display.h"
|
||||
#include "resource_p.h"
|
||||
#include "seat_interface.h"
|
||||
#include "surface_interface.h"
|
||||
|
||||
#include "qwayland-server-tablet-unstable-v2.h"
|
||||
#include <QHash>
|
||||
|
||||
using namespace KWayland;
|
||||
using namespace Server;
|
||||
|
||||
static int s_version = 1;
|
||||
|
||||
class TabletInterface::Private : public QtWaylandServer::zwp_tablet_v2
|
||||
{
|
||||
public:
|
||||
Private(TabletInterface* q, uint32_t vendorId, uint32_t productId, const QString name, const QStringList &paths)
|
||||
: zwp_tablet_v2()
|
||||
, q(q)
|
||||
, m_vendorId(vendorId)
|
||||
, m_productId(productId)
|
||||
, m_name(name)
|
||||
, m_paths(paths)
|
||||
{
|
||||
}
|
||||
|
||||
wl_resource *resourceForSurface(SurfaceInterface *surface) const
|
||||
{
|
||||
ClientConnection *client = surface->client();
|
||||
QtWaylandServer::zwp_tablet_v2::Resource *r = resourceMap().value(*client);
|
||||
return r ? r->handle : nullptr;
|
||||
}
|
||||
|
||||
void zwp_tablet_v2_destroy_resource(QtWaylandServer::zwp_tablet_v2::Resource * resource) override
|
||||
{
|
||||
Q_UNUSED(resource);
|
||||
if (removed && resourceMap().isEmpty()) {
|
||||
delete q;
|
||||
}
|
||||
}
|
||||
|
||||
TabletInterface *const q;
|
||||
const uint32_t m_vendorId;
|
||||
const uint32_t m_productId;
|
||||
const QString m_name;
|
||||
const QStringList m_paths;
|
||||
bool removed = false;
|
||||
};
|
||||
|
||||
TabletInterface::TabletInterface(uint32_t vendorId, uint32_t productId,
|
||||
const QString &name, const QStringList &paths,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new Private(this, vendorId, productId, name, paths))
|
||||
{
|
||||
}
|
||||
|
||||
TabletInterface::~TabletInterface() = default;
|
||||
|
||||
bool TabletInterface::isSurfaceSupported(SurfaceInterface *surface) const
|
||||
{
|
||||
return d->resourceForSurface(surface);
|
||||
}
|
||||
|
||||
void TabletInterface::sendRemoved()
|
||||
{
|
||||
d->removed = true;
|
||||
for (QtWaylandServer::zwp_tablet_v2::Resource *resource : d->resourceMap()) {
|
||||
d->send_removed(resource->handle);
|
||||
}
|
||||
}
|
||||
|
||||
class TabletCursor::Private
|
||||
{
|
||||
public:
|
||||
Private(TabletCursor* q) : q(q) {}
|
||||
|
||||
void update(quint32 serial, SurfaceInterface *surface, const QPoint &hotspot)
|
||||
{
|
||||
const bool diff = m_serial != serial && m_surface != surface && m_hotspot != hotspot;
|
||||
m_serial = serial;
|
||||
m_surface = surface;
|
||||
m_hotspot = hotspot;
|
||||
if (diff)
|
||||
Q_EMIT q->changed();
|
||||
}
|
||||
|
||||
TabletCursor* const q;
|
||||
|
||||
quint32 m_serial = 0;
|
||||
SurfaceInterface* m_surface = nullptr;
|
||||
QPoint m_hotspot;
|
||||
};
|
||||
|
||||
TabletCursor::TabletCursor()
|
||||
: QObject()
|
||||
, d(new Private(this))
|
||||
{
|
||||
}
|
||||
|
||||
TabletCursor::~TabletCursor() = default;
|
||||
|
||||
QPoint TabletCursor::hotspot() const
|
||||
{
|
||||
return d->m_hotspot;
|
||||
}
|
||||
|
||||
quint32 TabletCursor::enteredSerial() const
|
||||
{
|
||||
return d->m_serial;
|
||||
}
|
||||
|
||||
SurfaceInterface* TabletCursor::surface() const
|
||||
{
|
||||
return d->m_surface;
|
||||
}
|
||||
|
||||
class TabletToolInterface::Private : public QtWaylandServer::zwp_tablet_tool_v2
|
||||
{
|
||||
public:
|
||||
Private(TabletToolInterface* q, Display *display, Type type, uint32_t hsh, uint32_t hsl, uint32_t hih,
|
||||
uint32_t hil, const QVector<Capability>& capabilities)
|
||||
: zwp_tablet_tool_v2()
|
||||
, m_display(display)
|
||||
, m_type(type)
|
||||
, m_hardwareSerialHigh(hsh)
|
||||
, m_hardwareSerialLow(hsl)
|
||||
, m_hardwareIdHigh(hih)
|
||||
, m_hardwareIdLow(hil)
|
||||
, m_capabilities(capabilities)
|
||||
, q(q)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wl_resource *targetResource()
|
||||
{
|
||||
ClientConnection *client = m_surface->client();
|
||||
const Resource *r = resourceMap().value(*client);
|
||||
return r ? r->handle : nullptr;
|
||||
}
|
||||
|
||||
quint64 hardwareId() const
|
||||
{
|
||||
return quint64(quint64(m_hardwareIdHigh) << 32) + m_hardwareIdLow;
|
||||
}
|
||||
quint64 hardwareSerial() const
|
||||
{
|
||||
return quint64(quint64(m_hardwareSerialHigh) << 32) + m_hardwareSerialLow;
|
||||
}
|
||||
|
||||
void zwp_tablet_tool_v2_bind_resource(QtWaylandServer::zwp_tablet_tool_v2::Resource * resource) override
|
||||
{
|
||||
TabletCursor *&c = m_cursors[resource->handle];
|
||||
if (!c)
|
||||
c = new TabletCursor;
|
||||
}
|
||||
|
||||
void zwp_tablet_tool_v2_set_cursor(Resource * resource, uint32_t serial, struct ::wl_resource * _surface, int32_t hotspot_x, int32_t hotspot_y) override
|
||||
{
|
||||
TabletCursor *c = m_cursors[resource->handle];
|
||||
c->d->update(serial, SurfaceInterface::get(_surface), {hotspot_x, hotspot_y});
|
||||
if (resource->handle == targetResource())
|
||||
q->cursorChanged(c);
|
||||
}
|
||||
|
||||
void zwp_tablet_tool_v2_destroy_resource(Resource * resource) override {
|
||||
delete m_cursors.take(resource->handle);
|
||||
}
|
||||
|
||||
Display *const m_display;
|
||||
bool m_cleanup = false;
|
||||
QPointer<SurfaceInterface> m_surface;
|
||||
QPointer<TabletInterface> m_lastTablet;
|
||||
const uint32_t m_type;
|
||||
const uint32_t m_hardwareSerialHigh, m_hardwareSerialLow;
|
||||
const uint32_t m_hardwareIdHigh, m_hardwareIdLow;
|
||||
const QVector<Capability> m_capabilities;
|
||||
QHash<wl_resource *, TabletCursor *> m_cursors;
|
||||
TabletToolInterface *const q;
|
||||
};
|
||||
|
||||
TabletToolInterface::TabletToolInterface(Display *display, Type type, uint32_t hsh,
|
||||
uint32_t hsl, uint32_t hih, uint32_t hil,
|
||||
const QVector<Capability>& capabilities,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new Private(this, display, type, hsh, hsl, hih, hil, capabilities))
|
||||
{
|
||||
}
|
||||
|
||||
TabletToolInterface::~TabletToolInterface() = default;
|
||||
|
||||
void TabletToolInterface::setCurrentSurface(SurfaceInterface *surface)
|
||||
{
|
||||
if (d->m_surface == surface)
|
||||
return;
|
||||
|
||||
TabletInterface *const lastTablet = d->m_lastTablet;
|
||||
if (d->m_surface && d->resourceMap().contains(*d->m_surface->client())) {
|
||||
sendProximityOut();
|
||||
sendFrame(0);
|
||||
}
|
||||
|
||||
d->m_surface = surface;
|
||||
|
||||
if (lastTablet && lastTablet->d->resourceForSurface(surface)) {
|
||||
sendProximityIn(lastTablet);
|
||||
} else {
|
||||
d->m_lastTablet = lastTablet;
|
||||
}
|
||||
|
||||
Q_EMIT cursorChanged(d->m_cursors.value(d->targetResource()));
|
||||
}
|
||||
|
||||
bool TabletToolInterface::isClientSupported() const
|
||||
{
|
||||
return d->m_surface && d->targetResource();
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendButton(uint32_t button, bool pressed)
|
||||
{
|
||||
d->send_button(d->targetResource(), d->m_display->nextSerial(), button,
|
||||
pressed ? QtWaylandServer::zwp_tablet_tool_v2::button_state_pressed
|
||||
: QtWaylandServer::zwp_tablet_tool_v2::button_state_released);
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendMotion(const QPointF &pos)
|
||||
{
|
||||
d->send_motion(d->targetResource(), wl_fixed_from_double(pos.x()),
|
||||
wl_fixed_from_double(pos.y()));
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendDistance(uint32_t distance)
|
||||
{
|
||||
d->send_distance(d->targetResource(), distance);
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendFrame(uint32_t time)
|
||||
{
|
||||
d->send_frame(d->targetResource(), time);
|
||||
|
||||
if (d->m_cleanup) {
|
||||
d->m_surface = nullptr;
|
||||
d->m_lastTablet = nullptr;
|
||||
d->m_cleanup = false;
|
||||
}
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendPressure(uint32_t pressure)
|
||||
{
|
||||
d->send_pressure(d->targetResource(), pressure);
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendRotation(qreal rotation)
|
||||
{
|
||||
d->send_rotation(d->targetResource(), wl_fixed_from_double(rotation));
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendSlider(int32_t position)
|
||||
{
|
||||
d->send_slider(d->targetResource(), position);
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendTilt(qreal degreesX, qreal degreesY)
|
||||
{
|
||||
d->send_tilt(d->targetResource(), wl_fixed_from_double(degreesX),
|
||||
wl_fixed_from_double(degreesY));
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendWheel(int32_t degrees, int32_t clicks)
|
||||
{
|
||||
d->send_wheel(d->targetResource(), degrees, clicks);
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendProximityIn(TabletInterface *tablet)
|
||||
{
|
||||
wl_resource* tabletResource = tablet->d->resourceForSurface(d->m_surface);
|
||||
d->send_proximity_in(d->targetResource(), d->m_display->nextSerial(),
|
||||
tabletResource, d->m_surface->resource());
|
||||
d->m_lastTablet = tablet;
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendProximityOut()
|
||||
{
|
||||
d->send_proximity_out(d->targetResource());
|
||||
d->m_cleanup = true;
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendDown()
|
||||
{
|
||||
d->send_down(d->targetResource(), d->m_display->nextSerial());
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendUp()
|
||||
{
|
||||
d->send_up(d->targetResource());
|
||||
}
|
||||
|
||||
void TabletToolInterface::sendRemoved()
|
||||
{
|
||||
for (QtWaylandServer::zwp_tablet_tool_v2::Resource *resource : d->resourceMap()) {
|
||||
d->send_removed(resource->handle);
|
||||
}
|
||||
}
|
||||
|
||||
class TabletSeatInterface::Private : public QtWaylandServer::zwp_tablet_seat_v2
|
||||
{
|
||||
public:
|
||||
Private(Display *display, TabletSeatInterface *q)
|
||||
: zwp_tablet_seat_v2()
|
||||
, q(q)
|
||||
, m_display(display)
|
||||
{
|
||||
}
|
||||
|
||||
void zwp_tablet_seat_v2_bind_resource(Resource *resource) override
|
||||
{
|
||||
for (auto iface : qAsConst(m_tablets)) {
|
||||
sendTabletAdded(resource, iface);
|
||||
}
|
||||
|
||||
for (auto *tool : qAsConst(m_tools)) {
|
||||
sendToolAdded(resource, tool);
|
||||
}
|
||||
}
|
||||
|
||||
void sendToolAdded(Resource *resource, TabletToolInterface *tool)
|
||||
{
|
||||
wl_resource *toolResource = tool->d->add(resource->client(), resource->version())->handle;
|
||||
send_tool_added(resource->handle, toolResource);
|
||||
|
||||
tool->d->send_type(toolResource, tool->d->m_type);
|
||||
tool->d->send_hardware_serial(toolResource, tool->d->m_hardwareSerialHigh,
|
||||
tool->d->m_hardwareSerialLow);
|
||||
tool->d->send_hardware_id_wacom(toolResource, tool->d->m_hardwareIdHigh,
|
||||
tool->d->m_hardwareIdLow);
|
||||
for (uint32_t cap : qAsConst(tool->d->m_capabilities)) {
|
||||
tool->d->send_capability(toolResource, cap);
|
||||
}
|
||||
tool->d->send_done(toolResource);
|
||||
}
|
||||
void sendTabletAdded(Resource *resource, TabletInterface *tablet)
|
||||
{
|
||||
wl_resource *tabletResource = tablet->d->add(resource->client(), resource->version())->handle;
|
||||
send_tablet_added(resource->handle, tabletResource);
|
||||
|
||||
tablet->d->send_name(tabletResource, tablet->d->m_name);
|
||||
if (tablet->d->m_vendorId && tablet->d->m_productId) {
|
||||
tablet->d->send_id(tabletResource, tablet->d->m_vendorId, tablet->d->m_productId);
|
||||
}
|
||||
for (const QString &path : qAsConst(tablet->d->m_paths)) {
|
||||
tablet->d->send_path(tabletResource, path);
|
||||
}
|
||||
tablet->d->send_done(tabletResource);
|
||||
}
|
||||
|
||||
TabletSeatInterface *const q;
|
||||
QVector<TabletToolInterface *> m_tools;
|
||||
QHash<QString, TabletInterface *> m_tablets;
|
||||
Display *const m_display;
|
||||
};
|
||||
|
||||
TabletSeatInterface::TabletSeatInterface(Display *display, QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new Private(display, this))
|
||||
{
|
||||
}
|
||||
|
||||
TabletSeatInterface::~TabletSeatInterface() = default;
|
||||
|
||||
TabletToolInterface *TabletSeatInterface::addTool(TabletToolInterface::Type type,
|
||||
quint64 hardwareSerial,
|
||||
quint64 hardwareId,
|
||||
const QVector<TabletToolInterface::Capability> &capabilities)
|
||||
{
|
||||
constexpr auto MAX_UINT_32 = std::numeric_limits<quint32>::max();
|
||||
auto tool = new TabletToolInterface(d->m_display,
|
||||
type, hardwareSerial >> 32, hardwareSerial & MAX_UINT_32,
|
||||
hardwareId >> 32, hardwareId & MAX_UINT_32, capabilities, this);
|
||||
for (QtWaylandServer::zwp_tablet_seat_v2::Resource *resource : d->resourceMap()) {
|
||||
d->sendToolAdded(resource, tool);
|
||||
}
|
||||
|
||||
d->m_tools.append(tool);
|
||||
QObject::connect(tool, &QObject::destroyed, this, [this](QObject *object) {
|
||||
auto tti = static_cast<TabletToolInterface *>(object);
|
||||
tti->d->send_removed();
|
||||
d->m_tools.removeAll(tti);
|
||||
});
|
||||
return tool;
|
||||
}
|
||||
|
||||
TabletInterface *TabletSeatInterface::addTablet(uint32_t vendorId, uint32_t productId,
|
||||
const QString &sysname,
|
||||
const QString &name,
|
||||
const QStringList &paths)
|
||||
{
|
||||
auto iface = new TabletInterface(vendorId, productId, name, paths, this);
|
||||
|
||||
for (QtWaylandServer::zwp_tablet_seat_v2::Resource *r : d->resourceMap()) {
|
||||
d->sendTabletAdded(r, iface);
|
||||
}
|
||||
|
||||
d->m_tablets[sysname] = iface;
|
||||
return iface;
|
||||
}
|
||||
|
||||
void TabletSeatInterface::removeTablet(const QString &sysname)
|
||||
{
|
||||
auto tablet = d->m_tablets.take(sysname);
|
||||
if (tablet) {
|
||||
tablet->sendRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
TabletToolInterface *TabletSeatInterface::toolByHardwareId(quint64 hardwareId) const
|
||||
{
|
||||
for (TabletToolInterface *tool : d->m_tools) {
|
||||
if (tool->d->hardwareId() == hardwareId)
|
||||
return tool;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TabletToolInterface *TabletSeatInterface::toolByHardwareSerial(quint64 hardwareSerial) const
|
||||
{
|
||||
for (TabletToolInterface *tool : d->m_tools) {
|
||||
if (tool->d->hardwareSerial() == hardwareSerial)
|
||||
return tool;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TabletInterface *TabletSeatInterface::tabletByName(const QString &name) const
|
||||
{
|
||||
return d->m_tablets.value(name);
|
||||
}
|
||||
|
||||
class TabletManagerInterface::Private : public QtWaylandServer::zwp_tablet_manager_v2
|
||||
{
|
||||
public:
|
||||
Private(Display *display, TabletManagerInterface *q)
|
||||
: zwp_tablet_manager_v2(*display, s_version)
|
||||
, q(q)
|
||||
, m_display(display)
|
||||
{
|
||||
}
|
||||
|
||||
void zwp_tablet_manager_v2_get_tablet_seat(Resource *resource, uint32_t tablet_seat,
|
||||
struct ::wl_resource *seat_resource) override {
|
||||
SeatInterface* seat = SeatInterface::get(seat_resource);
|
||||
TabletSeatInterface *tsi = get(seat);
|
||||
tsi->d->add(resource->client(), tablet_seat, s_version);
|
||||
}
|
||||
|
||||
TabletSeatInterface *get(SeatInterface *seat)
|
||||
{
|
||||
TabletSeatInterface *&tabletSeat = m_seats[seat];
|
||||
if (!tabletSeat) {
|
||||
tabletSeat = new TabletSeatInterface(m_display, q);
|
||||
}
|
||||
return tabletSeat;
|
||||
}
|
||||
|
||||
TabletManagerInterface *const q;
|
||||
Display *const m_display;
|
||||
QHash<SeatInterface *, TabletSeatInterface *> m_seats;
|
||||
};
|
||||
|
||||
TabletManagerInterface::TabletManagerInterface(Display *display, QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new Private(display, this))
|
||||
{
|
||||
}
|
||||
|
||||
TabletSeatInterface *TabletManagerInterface::seat(SeatInterface *seat) const
|
||||
{
|
||||
return d->get(seat);
|
||||
}
|
||||
|
||||
TabletManagerInterface::~TabletManagerInterface() = default;
|
194
src/wayland/server/tablet_interface.h
Normal file
194
src/wayland/server/tablet_interface.h
Normal file
|
@ -0,0 +1,194 @@
|
|||
/********************************************************************
|
||||
Copyright 2019 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#ifndef WAYLAND_SERVER_TABLET_INTERFACE_H
|
||||
#define WAYLAND_SERVER_TABLET_INTERFACE_H
|
||||
|
||||
#include <KWayland/Server/kwaylandserver_export.h>
|
||||
#include <QVector>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Server
|
||||
{
|
||||
class TabletSeatInterface;
|
||||
class Display;
|
||||
class SeatInterface;
|
||||
class SurfaceInterface;
|
||||
class TabletInterface;
|
||||
class TabletCursor;
|
||||
|
||||
/**
|
||||
* This is an implementation of wayland-protocols/unstable/tablet/tablet-unstable-v2.xml
|
||||
*
|
||||
* This class is just the means to get a @class TabletSeatInterface, which is
|
||||
* the class that will have all of the information we need.
|
||||
*
|
||||
* @since 5.69
|
||||
*/
|
||||
|
||||
class KWAYLANDSERVER_EXPORT TabletManagerInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~TabletManagerInterface();
|
||||
|
||||
TabletSeatInterface *seat(SeatInterface *seat) const;
|
||||
|
||||
private:
|
||||
friend class Display;
|
||||
explicit TabletManagerInterface(Display *d, QObject *parent);
|
||||
class Private;
|
||||
QScopedPointer<Private> d;
|
||||
};
|
||||
|
||||
class KWAYLANDSERVER_EXPORT TabletToolInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~TabletToolInterface();
|
||||
|
||||
enum Type {
|
||||
Pen = 0x140, ///< Pen
|
||||
Eraser = 0x141, ///< Eraser
|
||||
Brush = 0x142, ///< Brush
|
||||
Pencil = 0x143, ///< Pencil
|
||||
Airbrush = 0x144, ///< Airbrush
|
||||
Finger = 0x145, ///< Finger
|
||||
Mouse = 0x146, ///< Mouse
|
||||
Lens = 0x147, ///< Lens
|
||||
Totem
|
||||
};
|
||||
Q_ENUM(Type)
|
||||
|
||||
enum Capability {
|
||||
Tilt = 1, ///< Tilt axeis
|
||||
Pressure = 2, ///< Pressure axis
|
||||
Distance = 3, ///< Distance axis
|
||||
Rotation = 4, ///< Z-rotation axis
|
||||
Slider = 5, ///< Slider axis
|
||||
Wheel = 6 ///< Wheel axis
|
||||
};
|
||||
Q_ENUM(Capability)
|
||||
|
||||
/**
|
||||
* Sets the surface the events will be sent to.
|
||||
*
|
||||
* Make sure the surface supports being sent events to.
|
||||
*
|
||||
* @see TabletInterface::isSurfaceSupported
|
||||
*/
|
||||
void setCurrentSurface(SurfaceInterface *surface);
|
||||
bool isClientSupported() const;
|
||||
|
||||
void sendRemoved();
|
||||
void sendProximityIn(TabletInterface *tablet);
|
||||
void sendProximityOut();
|
||||
void sendUp();
|
||||
void sendDown();
|
||||
void sendPressure(quint32 pressure);
|
||||
void sendDistance(quint32 distance);
|
||||
void sendTilt(qreal degreesX, qreal degreesY);
|
||||
void sendRotation(qreal degrees);
|
||||
void sendSlider(qint32 position);
|
||||
void sendWheel(qint32 degrees, qint32 clicks);
|
||||
void sendButton(quint32 button, bool pressed);
|
||||
void sendFrame(quint32 time);
|
||||
void sendMotion(const QPointF &pos);
|
||||
|
||||
Q_SIGNALS:
|
||||
void cursorChanged(TabletCursor* cursor) const;
|
||||
|
||||
private:
|
||||
friend class TabletSeatInterface;
|
||||
explicit TabletToolInterface(Display *display, Type type, quint32 hsh, quint32 hsl, quint32 hih, quint32 hil, const QVector<Capability> &capability, QObject *parent);
|
||||
class Private;
|
||||
QScopedPointer<Private> d;
|
||||
};
|
||||
|
||||
class KWAYLANDSERVER_EXPORT TabletCursor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
~TabletCursor() override;
|
||||
QPoint hotspot() const;
|
||||
quint32 enteredSerial() const;
|
||||
SurfaceInterface* surface() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void changed();
|
||||
|
||||
private:
|
||||
friend class TabletToolInterface;
|
||||
TabletCursor();
|
||||
class Private;
|
||||
const QScopedPointer<Private> d;
|
||||
};
|
||||
|
||||
class KWAYLANDSERVER_EXPORT TabletInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~TabletInterface();
|
||||
|
||||
/**
|
||||
* @returns true if the surface has been bound to the tablet.
|
||||
*/
|
||||
bool isSurfaceSupported(SurfaceInterface *surface) const;
|
||||
|
||||
void sendRemoved();
|
||||
|
||||
private:
|
||||
friend class TabletSeatInterface;
|
||||
friend class TabletToolInterface;
|
||||
explicit TabletInterface(quint32 vendorId, quint32 productId, const QString &name, const QStringList &paths, QObject *parent);
|
||||
class Private;
|
||||
QScopedPointer<Private> d;
|
||||
};
|
||||
|
||||
class KWAYLANDSERVER_EXPORT TabletSeatInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~TabletSeatInterface();
|
||||
|
||||
TabletInterface *addTablet(quint32 vendorId, quint32 productId, const QString &sysname, const QString &name, const QStringList &paths);
|
||||
TabletToolInterface *addTool(TabletToolInterface::Type type, quint64 hardwareSerial, quint64 hardwareId, const QVector<TabletToolInterface::Capability> &capabilities);
|
||||
|
||||
TabletToolInterface *toolByHardwareId(quint64 hardwareId) const;
|
||||
TabletToolInterface *toolByHardwareSerial(quint64 hardwareSerial) const;
|
||||
TabletInterface *tabletByName(const QString &sysname) const;
|
||||
|
||||
void removeTablet(const QString &sysname);
|
||||
|
||||
private:
|
||||
friend class TabletManagerInterface;
|
||||
explicit TabletSeatInterface(Display *display, QObject *parent);
|
||||
class Private;
|
||||
QScopedPointer<Private> d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(KWayland::Server::TabletSeatInterface *)
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue