17#include "KWayland/Client/compositor.h"
18#include "KWayland/Client/connection_thread.h"
19#include "KWayland/Client/event_queue.h"
20#include "KWayland/Client/registry.h"
21#include "KWayland/Client/seat.h"
22#include "KWayland/Client/surface.h"
24#include "qwayland-tablet-unstable-v2.h"
27using namespace std::literals;
29class Tablet :
public QtWayland::zwp_tablet_v2
38class TabletPad :
public QObject,
public QtWayland::zwp_tablet_pad_v2
55 Q_ASSERT(buttons == 1);
78class Tool :
public QObject,
public QtWayland::zwp_tablet_tool_v2
82 Tool(::zwp_tablet_tool_v2 *t)
102class TabletSeat :
public QObject,
public QtWayland::zwp_tablet_seat_v2
151 void testInteractSimple_data();
152 void testInteractSimple();
153 void testInteractSurfaceChange_data();
154 void testInteractSurfaceChange();
157 KWayland::Client::ConnectionThread *m_connection;
158 KWayland::Client::EventQueue *m_queue;
159 KWayland::Client::Compositor *m_clientCompositor;
160 KWayland::Client::Seat *m_clientSeat =
nullptr;
171 QList<KWayland::Client::Surface *> m_surfacesClient;
177 QList<SurfaceInterface *> m_surfaces;
180static const QString s_socketName = QStringLiteral(
"kwin-wayland-server-tablet-test-0");
182void TestTabletInterface::initTestCase()
193 m_surfaces += surface;
197 m_connection =
new KWayland::Client::ConnectionThread;
198 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
199 m_connection->setSocketName(s_socketName);
201 m_thread =
new QThread(
this);
202 m_connection->moveToThread(m_thread);
205 m_connection->initConnection();
206 QVERIFY(connectedSpy.wait());
207 QVERIFY(!m_connection->connections().isEmpty());
209 m_queue =
new KWayland::Client::EventQueue(
this);
210 QVERIFY(!m_queue->isValid());
211 m_queue->setup(m_connection);
212 QVERIFY(m_queue->isValid());
214 auto registry =
new KWayland::Client::Registry(
this);
215 connect(registry, &KWayland::Client::Registry::interfaceAnnounced,
this, [
this, registry](
const QByteArray &interface, quint32 name, quint32
version) {
216 if (interface ==
"zwp_tablet_manager_v2") {
217 auto tabletClient =
new QtWayland::zwp_tablet_manager_v2(
registry->registry(), name,
version);
218 auto _seat = tabletClient->get_tablet_seat(*m_clientSeat);
220 auto _seat2 = tabletClient->get_tablet_seat(*m_clientSeat);
224 connect(registry, &KWayland::Client::Registry::seatAnnounced,
this, [
this, registry](quint32 name, quint32
version) {
228 QSignalSpy compositorSpy(registry, &KWayland::Client::Registry::compositorAnnounced);
229 registry->create(m_connection->display());
232 wl_display_flush(m_connection->display());
234 QVERIFY(compositorSpy.wait());
235 m_clientCompositor =
registry->createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(),
this);
236 QVERIFY(m_clientCompositor->isValid());
239 for (
int i = 0; i < 3; ++i) {
240 m_surfacesClient += m_clientCompositor->createSurface(
this);
242 QVERIFY(surfaceSpy.count() < 3 && surfaceSpy.wait(200));
243 QVERIFY(m_surfaces.count() == 3);
244 QVERIFY(m_tabletSeatClient);
259 delete m_tabletSeatClient;
260 delete m_tabletSeatClient2;
261 m_connection->deleteLater();
262 m_connection =
nullptr;
265void TestTabletInterface::testAdd()
268 QVERIFY(seatInterface);
271 m_tablet = seatInterface->
addTablet(1, 2, QStringLiteral(
"event33"), QStringLiteral(
"my tablet"), {QStringLiteral(
"/test/event33")});
273 QVERIFY(tabletSpy.wait() || tabletSpy.count() == 1);
274 QCOMPARE(m_tabletSeatClient->
m_tablets.count(), 1);
279 QVERIFY(toolSpy.wait() || toolSpy.count() == 1);
280 QCOMPARE(m_tabletSeatClient->
m_tools.count(), 1);
286 QCOMPARE(m_surfaces.count(), 3);
293void TestTabletInterface::testAddPad()
296 QVERIFY(seatInterface);
300 seatInterface->
addTabletPad(QStringLiteral(
"my tablet pad"), QStringLiteral(
"tabletpad"), {QStringLiteral(
"/test/event33")}, 1, 1, 1, 1, 0, m_tablet);
301 QVERIFY(m_tabletPad);
302 QVERIFY(tabletPadSpy.wait() || tabletPadSpy.count() == 1);
303 QCOMPARE(m_tabletSeatClient->
m_pads.count(), 1);
304 QVERIFY(m_tabletSeatClient->
m_pads[0]);
306 QVERIFY(m_tabletPad->
ring(0));
307 QVERIFY(m_tabletPad->
strip(0));
309 QCOMPARE(m_surfaces.count(), 3);
310 QVERIFY(m_tabletSeatClient->
m_pads[0]->buttonStates.isEmpty());
313 m_tabletPad->
sendButton(123ms, 0, QtWayland::zwp_tablet_pad_v2::button_state_pressed);
314 QVERIFY(buttonSpy.count() || buttonSpy.wait(100));
315 QCOMPARE(m_tabletSeatClient->
m_pads[0]->doneCalled,
true);
316 QCOMPARE(m_tabletSeatClient->
m_pads[0]->buttonStates.count(), 1);
317 QCOMPARE(m_tabletSeatClient->
m_pads[0]->buttonStates[*m_surfacesClient[0]][0], QtWayland::zwp_tablet_pad_v2::button_state_pressed);
320static uint s_serial = 0;
322void TestTabletInterface::testInteractSimple_data()
324 QTest::addColumn<TabletSeat *>(
"tabletSeatClient");
325 QTest::newRow(
"first client") << m_tabletSeatClient;
326 QTest::newRow(
"second client") << m_tabletSeatClient2;
329void TestTabletInterface::testInteractSimple()
332 tabletSeatClient->m_tools[0]->surfaceApproximated.clear();
333 QSignalSpy frameSpy(tabletSeatClient->m_tools[0], &
Tool::frame);
348 QVERIFY(frameSpy.wait(500));
349 QCOMPARE(tabletSeatClient->m_tools[0]->surfaceApproximated.count(), 1);
352void TestTabletInterface::testInteractSurfaceChange_data()
354 QTest::addColumn<TabletSeat *>(
"tabletSeatClient");
355 QTest::newRow(
"first client") << m_tabletSeatClient;
356 QTest::newRow(
"second client") << m_tabletSeatClient2;
359void TestTabletInterface::testInteractSurfaceChange()
362 tabletSeatClient->m_tools[0]->surfaceApproximated.clear();
363 QSignalSpy frameSpy(tabletSeatClient->m_tools[0], &
Tool::frame);
382 QVERIFY(frameSpy.wait(500));
383 QCOMPARE(tabletSeatClient->m_tools[0]->surfaceApproximated.count(), 2);
387#include "test_tablet_interface.moc"
void surfaceCreated(KWin::SurfaceInterface *surface)
Class holding the Wayland server display loop.
bool addSocketName(const QString &name=QString())
Represents a Seat on the Wayland Display.
Resource representing a wl_surface.
TabletSeatV2Interface * seat(SeatInterface *seat) const
TabletPadRingV2Interface * ring(uint at) const
void sendButton(std::chrono::microseconds time, quint32 button, bool pressed)
TabletPadStripV2Interface * strip(uint at) const
void setCurrentSurface(SurfaceInterface *surface, TabletV2Interface *tablet)
TabletPadV2Interface * addTabletPad(const QString &sysname, const QString &name, const QStringList &paths, quint32 buttons, quint32 rings, quint32 strips, quint32 modes, quint32 currentMode, TabletV2Interface *tablet)
TabletToolV2Interface * addTool(TabletToolV2Interface::Type type, quint64 hardwareSerial, quint64 hardwareId, const QList< TabletToolV2Interface::Capability > &capabilities, const QString &deviceSysName)
TabletV2Interface * addTablet(quint32 vendorId, quint32 productId, const QString &sysname, const QString &name, const QStringList &paths)
bool isSurfaceSupported(SurfaceInterface *surface) const
Tablet(::zwp_tablet_v2 *t)
void zwp_tablet_pad_v2_buttons(uint32_t buttons) override
void zwp_tablet_pad_v2_done() override
QHash<::wl_surface *, QHash< uint32_t, uint32_t > > buttonStates
void zwp_tablet_pad_v2_button(uint32_t, uint32_t button, uint32_t state) override
TabletPad(::zwp_tablet_pad_v2 *t)
::wl_surface * m_currentSurface
void zwp_tablet_pad_v2_enter(uint32_t, struct ::zwp_tablet_v2 *, struct ::wl_surface *surface) override
void zwp_tablet_seat_v2_tool_added(struct ::zwp_tablet_tool_v2 *id) override
void zwp_tablet_seat_v2_pad_added(struct ::zwp_tablet_pad_v2 *id) override
TabletSeat(::zwp_tablet_seat_v2 *seat)
QList< TabletPad * > m_pads
void zwp_tablet_seat_v2_tablet_added(struct ::zwp_tablet_v2 *id) override
QList< Tablet * > m_tablets
~TestTabletInterface() override
KWayland::Client::Registry * registry