2020-03-15 15:19:28 +00:00
|
|
|
/*
|
|
|
|
SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org>
|
2018-12-21 13:07:52 +00:00
|
|
|
|
2020-03-15 15:19:28 +00:00
|
|
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
|
|
|
*/
|
2018-12-21 13:07:52 +00:00
|
|
|
// Qt
|
2023-07-03 19:28:19 +00:00
|
|
|
#include <QSignalSpy>
|
|
|
|
#include <QTest>
|
2018-12-21 13:07:52 +00:00
|
|
|
// KWin
|
2023-09-13 05:52:59 +00:00
|
|
|
#include "wayland/compositor.h"
|
2022-04-22 09:27:33 +00:00
|
|
|
#include "wayland/display.h"
|
2023-09-13 05:52:59 +00:00
|
|
|
#include "wayland/xdgdecoration_v1.h"
|
|
|
|
#include "wayland/xdgshell.h"
|
2022-04-22 09:27:33 +00:00
|
|
|
|
2020-04-29 13:59:23 +00:00
|
|
|
#include "KWayland/Client/compositor.h"
|
|
|
|
#include "KWayland/Client/connection_thread.h"
|
|
|
|
#include "KWayland/Client/event_queue.h"
|
|
|
|
#include "KWayland/Client/registry.h"
|
|
|
|
#include "KWayland/Client/surface.h"
|
2021-08-29 05:11:06 +00:00
|
|
|
#include "KWayland/Client/xdgdecoration.h"
|
|
|
|
#include "KWayland/Client/xdgshell.h"
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
class TestXdgDecoration : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
explicit TestXdgDecoration(QObject *parent = nullptr);
|
|
|
|
private Q_SLOTS:
|
|
|
|
void init();
|
|
|
|
void cleanup();
|
|
|
|
|
|
|
|
void testDecoration_data();
|
|
|
|
void testDecoration();
|
|
|
|
|
|
|
|
private:
|
2023-09-13 17:59:29 +00:00
|
|
|
KWin::Display *m_display = nullptr;
|
|
|
|
KWin::CompositorInterface *m_compositorInterface = nullptr;
|
|
|
|
KWin::XdgShellInterface *m_xdgShellInterface = nullptr;
|
|
|
|
KWin::XdgDecorationManagerV1Interface *m_xdgDecorationManagerInterface = nullptr;
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
KWayland::Client::ConnectionThread *m_connection = nullptr;
|
|
|
|
KWayland::Client::Compositor *m_compositor = nullptr;
|
|
|
|
KWayland::Client::EventQueue *m_queue = nullptr;
|
|
|
|
KWayland::Client::XdgShell *m_xdgShell = nullptr;
|
|
|
|
KWayland::Client::XdgDecorationManager *m_xdgDecorationManager = nullptr;
|
|
|
|
|
|
|
|
QThread *m_thread = nullptr;
|
|
|
|
KWayland::Client::Registry *m_registry = nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const QString s_socketName = QStringLiteral("kwayland-test-wayland-server-side-decoration-0");
|
|
|
|
|
|
|
|
TestXdgDecoration::TestXdgDecoration(QObject *parent)
|
|
|
|
: QObject(parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestXdgDecoration::init()
|
|
|
|
{
|
2023-09-13 17:59:29 +00:00
|
|
|
using namespace KWin;
|
2018-12-21 13:07:52 +00:00
|
|
|
|
2022-11-08 21:15:17 +00:00
|
|
|
qRegisterMetaType<KWayland::Client::XdgDecoration::Mode>();
|
2020-05-04 13:32:23 +00:00
|
|
|
qRegisterMetaType<XdgToplevelDecorationV1Interface::Mode>();
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
delete m_display;
|
2023-09-13 17:59:29 +00:00
|
|
|
m_display = new KWin::Display(this);
|
2020-10-19 15:52:56 +00:00
|
|
|
m_display->addSocketName(s_socketName);
|
2018-12-21 13:07:52 +00:00
|
|
|
m_display->start();
|
|
|
|
QVERIFY(m_display->isRunning());
|
|
|
|
|
|
|
|
// setup connection
|
|
|
|
m_connection = new KWayland::Client::ConnectionThread;
|
2022-11-08 21:15:17 +00:00
|
|
|
QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
|
2018-12-21 13:07:52 +00:00
|
|
|
m_connection->setSocketName(s_socketName);
|
|
|
|
|
|
|
|
m_thread = new QThread(this);
|
|
|
|
m_connection->moveToThread(m_thread);
|
|
|
|
m_thread->start();
|
|
|
|
|
|
|
|
m_connection->initConnection();
|
|
|
|
QVERIFY(connectedSpy.wait());
|
|
|
|
|
2022-11-08 21:15:17 +00:00
|
|
|
m_queue = new KWayland::Client::EventQueue(this);
|
2018-12-21 13:07:52 +00:00
|
|
|
QVERIFY(!m_queue->isValid());
|
|
|
|
m_queue->setup(m_connection);
|
|
|
|
QVERIFY(m_queue->isValid());
|
|
|
|
|
2022-11-08 21:15:17 +00:00
|
|
|
m_registry = new KWayland::Client::Registry();
|
|
|
|
QSignalSpy compositorSpy(m_registry, &KWayland::Client::Registry::compositorAnnounced);
|
|
|
|
QSignalSpy xdgShellSpy(m_registry, &KWayland::Client::Registry::xdgShellStableAnnounced);
|
|
|
|
QSignalSpy xdgDecorationManagerSpy(m_registry, &KWayland::Client::Registry::xdgDecorationAnnounced);
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
QVERIFY(!m_registry->eventQueue());
|
|
|
|
m_registry->setEventQueue(m_queue);
|
|
|
|
QCOMPARE(m_registry->eventQueue(), m_queue);
|
|
|
|
m_registry->create(m_connection);
|
|
|
|
QVERIFY(m_registry->isValid());
|
|
|
|
m_registry->setup();
|
|
|
|
|
2020-12-09 20:13:19 +00:00
|
|
|
m_compositorInterface = new CompositorInterface(m_display, m_display);
|
2018-12-21 13:07:52 +00:00
|
|
|
QVERIFY(compositorSpy.wait());
|
|
|
|
m_compositor = m_registry->createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
|
|
|
|
|
2020-12-09 20:13:19 +00:00
|
|
|
m_xdgShellInterface = new XdgShellInterface(m_display, m_display);
|
2018-12-21 13:07:52 +00:00
|
|
|
QVERIFY(xdgShellSpy.wait());
|
2021-08-29 05:11:06 +00:00
|
|
|
m_xdgShell = m_registry->createXdgShell(xdgShellSpy.first().first().value<quint32>(), xdgShellSpy.first().last().value<quint32>(), this);
|
2018-12-21 13:07:52 +00:00
|
|
|
|
2020-12-09 20:13:19 +00:00
|
|
|
m_xdgDecorationManagerInterface = new XdgDecorationManagerV1Interface(m_display, m_display);
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
QVERIFY(xdgDecorationManagerSpy.wait());
|
|
|
|
m_xdgDecorationManager = m_registry->createXdgDecorationManager(xdgDecorationManagerSpy.first().first().value<quint32>(),
|
2021-08-29 05:11:06 +00:00
|
|
|
xdgDecorationManagerSpy.first().last().value<quint32>(),
|
|
|
|
this);
|
2018-12-21 13:07:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestXdgDecoration::cleanup()
|
|
|
|
{
|
|
|
|
if (m_compositor) {
|
|
|
|
delete m_compositor;
|
|
|
|
m_compositor = nullptr;
|
|
|
|
}
|
|
|
|
if (m_xdgShell) {
|
|
|
|
delete m_xdgShell;
|
|
|
|
m_xdgShell = nullptr;
|
|
|
|
}
|
|
|
|
if (m_xdgDecorationManager) {
|
|
|
|
delete m_xdgDecorationManager;
|
|
|
|
m_xdgDecorationManager = nullptr;
|
|
|
|
}
|
|
|
|
if (m_queue) {
|
|
|
|
delete m_queue;
|
|
|
|
m_queue = nullptr;
|
|
|
|
}
|
|
|
|
if (m_registry) {
|
|
|
|
delete m_registry;
|
|
|
|
m_registry = nullptr;
|
|
|
|
}
|
|
|
|
if (m_thread) {
|
|
|
|
m_thread->quit();
|
|
|
|
m_thread->wait();
|
|
|
|
delete m_thread;
|
|
|
|
m_thread = nullptr;
|
|
|
|
}
|
|
|
|
delete m_connection;
|
|
|
|
m_connection = nullptr;
|
|
|
|
|
|
|
|
delete m_display;
|
|
|
|
m_display = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestXdgDecoration::testDecoration_data()
|
|
|
|
{
|
2023-09-13 17:59:29 +00:00
|
|
|
using namespace KWin;
|
|
|
|
QTest::addColumn<KWin::XdgToplevelDecorationV1Interface::Mode>("configuredMode");
|
2018-12-21 13:07:52 +00:00
|
|
|
QTest::addColumn<KWayland::Client::XdgDecoration::Mode>("configuredModeExp");
|
|
|
|
QTest::addColumn<KWayland::Client::XdgDecoration::Mode>("setMode");
|
2023-09-13 17:59:29 +00:00
|
|
|
QTest::addColumn<KWin::XdgToplevelDecorationV1Interface::Mode>("setModeExp");
|
2018-12-21 13:07:52 +00:00
|
|
|
|
2020-05-04 13:32:23 +00:00
|
|
|
const auto serverClient = XdgToplevelDecorationV1Interface::Mode::Client;
|
|
|
|
const auto serverServer = XdgToplevelDecorationV1Interface::Mode::Server;
|
2022-11-08 21:15:17 +00:00
|
|
|
const auto clientClient = KWayland::Client::XdgDecoration::Mode::ClientSide;
|
|
|
|
const auto clientServer = KWayland::Client::XdgDecoration::Mode::ServerSide;
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
QTest::newRow("client->client") << serverClient << clientClient << clientClient << serverClient;
|
|
|
|
QTest::newRow("client->server") << serverClient << clientClient << clientServer << serverServer;
|
|
|
|
QTest::newRow("server->client") << serverServer << clientServer << clientClient << serverClient;
|
|
|
|
QTest::newRow("server->server") << serverServer << clientServer << clientServer << serverServer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestXdgDecoration::testDecoration()
|
|
|
|
{
|
2023-09-13 17:59:29 +00:00
|
|
|
using namespace KWin;
|
2018-12-21 13:07:52 +00:00
|
|
|
|
2023-09-13 17:59:29 +00:00
|
|
|
QFETCH(KWin::XdgToplevelDecorationV1Interface::Mode, configuredMode);
|
2018-12-21 13:07:52 +00:00
|
|
|
QFETCH(KWayland::Client::XdgDecoration::Mode, configuredModeExp);
|
|
|
|
QFETCH(KWayland::Client::XdgDecoration::Mode, setMode);
|
2023-09-13 17:59:29 +00:00
|
|
|
QFETCH(KWin::XdgToplevelDecorationV1Interface::Mode, setModeExp);
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
|
2020-05-04 13:32:23 +00:00
|
|
|
QSignalSpy shellSurfaceCreatedSpy(m_xdgShellInterface, &XdgShellInterface::toplevelCreated);
|
|
|
|
QSignalSpy decorationCreatedSpy(m_xdgDecorationManagerInterface, &XdgDecorationManagerV1Interface::decorationCreated);
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
// create shell surface and deco object
|
2022-11-08 21:15:17 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface());
|
|
|
|
std::unique_ptr<KWayland::Client::XdgShellSurface> shellSurface(m_xdgShell->createSurface(surface.get()));
|
|
|
|
std::unique_ptr<KWayland::Client::XdgDecoration> decoration(m_xdgDecorationManager->getToplevelDecoration(shellSurface.get()));
|
2018-12-21 13:07:52 +00:00
|
|
|
|
2021-08-29 05:11:06 +00:00
|
|
|
// and receive all these on the "server"
|
2018-12-21 13:07:52 +00:00
|
|
|
QVERIFY(surfaceCreatedSpy.count() || surfaceCreatedSpy.wait());
|
|
|
|
QVERIFY(shellSurfaceCreatedSpy.count() || shellSurfaceCreatedSpy.wait());
|
|
|
|
QVERIFY(decorationCreatedSpy.count() || decorationCreatedSpy.wait());
|
|
|
|
|
2020-05-04 13:32:23 +00:00
|
|
|
auto shellSurfaceIface = shellSurfaceCreatedSpy.first().first().value<XdgToplevelInterface *>();
|
|
|
|
auto decorationIface = decorationCreatedSpy.first().first().value<XdgToplevelDecorationV1Interface *>();
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
QVERIFY(decorationIface);
|
|
|
|
QVERIFY(shellSurfaceIface);
|
2020-05-04 13:32:23 +00:00
|
|
|
QCOMPARE(decorationIface->toplevel(), shellSurfaceIface);
|
|
|
|
QCOMPARE(decorationIface->preferredMode(), XdgToplevelDecorationV1Interface::Mode::Undefined);
|
2018-12-21 13:07:52 +00:00
|
|
|
|
2022-11-08 21:15:17 +00:00
|
|
|
QSignalSpy clientConfiguredSpy(decoration.get(), &KWayland::Client::XdgDecoration::modeChanged);
|
2020-05-04 13:32:23 +00:00
|
|
|
QSignalSpy modeRequestedSpy(decorationIface, &XdgToplevelDecorationV1Interface::preferredModeChanged);
|
2018-12-21 13:07:52 +00:00
|
|
|
|
2021-08-29 05:11:06 +00:00
|
|
|
// server configuring a client
|
2020-05-04 13:32:23 +00:00
|
|
|
decorationIface->sendConfigure(configuredMode);
|
|
|
|
quint32 serial = shellSurfaceIface->sendConfigure(QSize(0, 0), {});
|
2018-12-21 13:07:52 +00:00
|
|
|
QVERIFY(clientConfiguredSpy.wait());
|
2022-11-08 21:15:17 +00:00
|
|
|
QCOMPARE(clientConfiguredSpy.first().first().value<KWayland::Client::XdgDecoration::Mode>(), configuredModeExp);
|
2018-12-21 13:07:52 +00:00
|
|
|
|
|
|
|
shellSurface->ackConfigure(serial);
|
|
|
|
|
2021-08-29 05:11:06 +00:00
|
|
|
// client requesting another mode
|
2018-12-21 13:07:52 +00:00
|
|
|
decoration->setMode(setMode);
|
|
|
|
QVERIFY(modeRequestedSpy.wait());
|
2020-05-04 13:32:23 +00:00
|
|
|
QCOMPARE(modeRequestedSpy.first().first().value<XdgToplevelDecorationV1Interface::Mode>(), setModeExp);
|
|
|
|
QCOMPARE(decorationIface->preferredMode(), setModeExp);
|
2018-12-21 13:07:52 +00:00
|
|
|
modeRequestedSpy.clear();
|
|
|
|
|
|
|
|
decoration->unsetMode();
|
|
|
|
QVERIFY(modeRequestedSpy.wait());
|
2021-08-29 05:11:06 +00:00
|
|
|
QCOMPARE(modeRequestedSpy.first().first().value<XdgToplevelDecorationV1Interface::Mode>(), XdgToplevelDecorationV1Interface::Mode::Undefined);
|
2018-12-21 13:07:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QTEST_GUILESS_MAIN(TestXdgDecoration)
|
|
|
|
#include "test_xdg_decoration.moc"
|