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(®istry, &KWayland::Client::Registry::compositorAnnounced); 0089 0090 QSignalSpy appmenuSpy(®istry, &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"