diff options
Diffstat (limited to 'tests/auto/client/cursor/tst_cursor.cpp')
-rw-r--r-- | tests/auto/client/cursor/tst_cursor.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/tests/auto/client/cursor/tst_cursor.cpp b/tests/auto/client/cursor/tst_cursor.cpp new file mode 100644 index 000000000..070e062f6 --- /dev/null +++ b/tests/auto/client/cursor/tst_cursor.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mockcompositor.h" +#include <QtGui/QRasterWindow> +#include <QtGui/qpa/qplatformnativeinterface.h> +#include <QtWaylandClient/private/wayland-wayland-client-protocol.h> +#include <QtWaylandClient/private/qwaylandwindow_p.h> + +#include "cursorshapev1.h" + +using namespace MockCompositor; + +class tst_cursor : public QObject, private DefaultCompositor +{ + Q_OBJECT +public: + tst_cursor(); + CursorShapeDevice* cursorShape(); +private slots: + void init(); + void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); } + void setCursor(); +}; + +tst_cursor::tst_cursor() +{ + exec([this] { + m_config.autoConfigure = true; + add<CursorShapeManager>(1); + }); +} + +CursorShapeDevice* tst_cursor::cursorShape() +{ + auto manager = get<CursorShapeManager>(); + if (!manager->m_cursorDevices.count()) + return nullptr; + return manager->m_cursorDevices[0]; +} + +void tst_cursor::init() +{ + setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1); +} + +void tst_cursor::setCursor() +{ + QCOMPOSITOR_TRY_VERIFY(cursorShape()); + QSignalSpy setCursorSpy(exec([&] { return pointer(); }), &Pointer::setCursor); + QSignalSpy setCursorShapeSpy(exec([&] { return cursorShape(); }), &CursorShapeDevice::setCursor); + + QRasterWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + uint enterSerial = exec([&] { + return pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); + }); + setCursorShapeSpy.wait(); + // verify we got given a cursor on enter + QCOMPOSITOR_COMPARE(cursorShape()->m_currentShape, CursorShapeDevice::shape_default); + QVERIFY(setCursorSpy.isEmpty()); + QCOMPARE(setCursorShapeSpy.takeFirst().at(0).toUInt(), enterSerial); + + // client sets a different shape + window.setCursor(QCursor(Qt::WaitCursor)); + QVERIFY(setCursorShapeSpy.wait()); + QCOMPOSITOR_COMPARE(cursorShape()->m_currentShape, CursorShapeDevice::shape_wait); + + setCursorShapeSpy.clear(); + + // client hides the cursor + // CursorShape will not be used, instead, it uses the old path + window.setCursor(QCursor(Qt::BlankCursor)); + QVERIFY(setCursorSpy.wait()); + QVERIFY(setCursorShapeSpy.isEmpty()); + QCOMPOSITOR_VERIFY(!pointer()->cursorSurface()); + + // same for bitmaps + QPixmap myCustomPixmap(10, 10); + myCustomPixmap.fill(Qt::red); + window.setCursor(QCursor(myCustomPixmap)); + QVERIFY(setCursorSpy.wait()); + QVERIFY(setCursorShapeSpy.isEmpty()); + + // set a shape again + window.setCursor(QCursor(Qt::BusyCursor)); + QVERIFY(setCursorShapeSpy.wait()); + QCOMPOSITOR_COMPARE(cursorShape()->m_currentShape, CursorShapeDevice::shape_progress); + + setCursorShapeSpy.clear(); + + // set the same bitmap again, make sure switching from new to old path works + // even if the bitmap cursor's properties haven't changed + window.setCursor(QCursor(myCustomPixmap)); + QVERIFY(setCursorSpy.wait()); + QVERIFY(setCursorShapeSpy.isEmpty()); +} + +QCOMPOSITOR_TEST_MAIN(tst_cursor) +#include "tst_cursor.moc" |