File indexing completed on 2024-11-10 04:56:17

0001 /*
0002     SPDX-FileCopyrightText: 2017 David Edmundson <davidedmundson@kde.org>
0003     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 // Qt
0008 #include <QSignalSpy>
0009 #include <QTest>
0010 // KWin
0011 #include "wayland/appmenu.h"
0012 #include "wayland/compositor.h"
0013 #include "wayland/display.h"
0014 
0015 #include "KWayland/Client/appmenu.h"
0016 #include "KWayland/Client/compositor.h"
0017 #include "KWayland/Client/connection_thread.h"
0018 #include "KWayland/Client/event_queue.h"
0019 #include "KWayland/Client/region.h"
0020 #include "KWayland/Client/registry.h"
0021 #include "KWayland/Client/surface.h"
0022 
0023 Q_DECLARE_METATYPE(KWin::AppMenuInterface::InterfaceAddress)
0024 
0025 class TestAppmenu : public QObject
0026 {
0027     Q_OBJECT
0028 public:
0029     explicit TestAppmenu(QObject *parent = nullptr);
0030 private Q_SLOTS:
0031     void init();
0032     void cleanup();
0033 
0034     void testCreateAndSet();
0035 
0036 private:
0037     KWin::Display *m_display;
0038     KWin::CompositorInterface *m_compositorInterface;
0039     KWin::AppMenuManagerInterface *m_appmenuManagerInterface;
0040     KWayland::Client::ConnectionThread *m_connection;
0041     KWayland::Client::Compositor *m_compositor;
0042     KWayland::Client::AppMenuManager *m_appmenuManager;
0043     KWayland::Client::EventQueue *m_queue;
0044     QThread *m_thread;
0045 };
0046 
0047 static const QString s_socketName = QStringLiteral("kwayland-test-wayland-appmenu-0");
0048 
0049 TestAppmenu::TestAppmenu(QObject *parent)
0050     : QObject(parent)
0051     , m_display(nullptr)
0052     , m_compositorInterface(nullptr)
0053     , m_connection(nullptr)
0054     , m_compositor(nullptr)
0055     , m_queue(nullptr)
0056     , m_thread(nullptr)
0057 {
0058 }
0059 
0060 void TestAppmenu::init()
0061 {
0062     using namespace KWin;
0063     qRegisterMetaType<AppMenuInterface::InterfaceAddress>();
0064     delete m_display;
0065     m_display = new KWin::Display(this);
0066     m_display->addSocketName(s_socketName);
0067     m_display->start();
0068     QVERIFY(m_display->isRunning());
0069 
0070     // setup connection
0071     m_connection = new KWayland::Client::ConnectionThread;
0072     QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
0073     m_connection->setSocketName(s_socketName);
0074 
0075     m_thread = new QThread(this);
0076     m_connection->moveToThread(m_thread);
0077     m_thread->start();
0078 
0079     m_connection->initConnection();
0080     QVERIFY(connectedSpy.wait());
0081 
0082     m_queue = new KWayland::Client::EventQueue(this);
0083     QVERIFY(!m_queue->isValid());
0084     m_queue->setup(m_connection);
0085     QVERIFY(m_queue->isValid());
0086 
0087     KWayland::Client::Registry registry;
0088     QSignalSpy compositorSpy(&registry, &KWayland::Client::Registry::compositorAnnounced);
0089 
0090     QSignalSpy appmenuSpy(&registry, &KWayland::Client::Registry::appMenuAnnounced);
0091 
0092     QVERIFY(!registry.eventQueue());
0093     registry.setEventQueue(m_queue);
0094     QCOMPARE(registry.eventQueue(), m_queue);
0095     registry.create(m_connection->display());
0096     QVERIFY(registry.isValid());
0097     registry.setup();
0098 
0099     m_compositorInterface = new CompositorInterface(m_display, m_display);
0100     QVERIFY(compositorSpy.wait());
0101     m_compositor = registry.createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
0102 
0103     m_appmenuManagerInterface = new AppMenuManagerInterface(m_display, m_display);
0104 
0105     QVERIFY(appmenuSpy.wait());
0106     m_appmenuManager = registry.createAppMenuManager(appmenuSpy.first().first().value<quint32>(), appmenuSpy.first().last().value<quint32>(), this);
0107 }
0108 
0109 void TestAppmenu::cleanup()
0110 {
0111 #define CLEANUP(variable)   \
0112     if (variable) {         \
0113         delete variable;    \
0114         variable = nullptr; \
0115     }
0116     CLEANUP(m_compositor)
0117     CLEANUP(m_appmenuManager)
0118     CLEANUP(m_queue)
0119     if (m_connection) {
0120         m_connection->deleteLater();
0121         m_connection = nullptr;
0122     }
0123     if (m_thread) {
0124         m_thread->quit();
0125         m_thread->wait();
0126         delete m_thread;
0127         m_thread = nullptr;
0128     }
0129     CLEANUP(m_compositorInterface)
0130     CLEANUP(m_appmenuManagerInterface)
0131     CLEANUP(m_display)
0132 #undef CLEANUP
0133 }
0134 
0135 void TestAppmenu::testCreateAndSet()
0136 {
0137     QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated);
0138 
0139     std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface());
0140     QVERIFY(serverSurfaceCreated.wait());
0141 
0142     auto serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>();
0143     QSignalSpy appMenuCreated(m_appmenuManagerInterface, &KWin::AppMenuManagerInterface::appMenuCreated);
0144 
0145     QVERIFY(!m_appmenuManagerInterface->appMenuForSurface(serverSurface));
0146 
0147     auto appmenu = m_appmenuManager->create(surface.get(), surface.get());
0148     QVERIFY(appMenuCreated.wait());
0149     auto appMenuInterface = appMenuCreated.first().first().value<KWin::AppMenuInterface *>();
0150     QCOMPARE(m_appmenuManagerInterface->appMenuForSurface(serverSurface), appMenuInterface);
0151 
0152     QCOMPARE(appMenuInterface->address().serviceName, QString());
0153     QCOMPARE(appMenuInterface->address().objectPath, QString());
0154 
0155     QSignalSpy appMenuChangedSpy(appMenuInterface, &KWin::AppMenuInterface::addressChanged);
0156 
0157     appmenu->setAddress("net.somename", "/test/path");
0158 
0159     QVERIFY(appMenuChangedSpy.wait());
0160     QCOMPARE(appMenuInterface->address().serviceName, QString("net.somename"));
0161     QCOMPARE(appMenuInterface->address().objectPath, QString("/test/path"));
0162 
0163     // and destroy
0164     QSignalSpy destroyedSpy(appMenuInterface, &QObject::destroyed);
0165     delete appmenu;
0166     QVERIFY(destroyedSpy.wait());
0167     QVERIFY(!m_appmenuManagerInterface->appMenuForSurface(serverSurface));
0168 }
0169 
0170 QTEST_GUILESS_MAIN(TestAppmenu)
0171 #include "test_wayland_appmenu.moc"