File indexing completed on 2024-11-10 04:56:22
0001 /* 0002 SPDX-FileCopyrightText: 2020 Benjamin Port <benjamin.port@enioka.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 // Qt 0008 #include <QHash> 0009 #include <QSignalSpy> 0010 #include <QTest> 0011 #include <QThread> 0012 // WaylandServer 0013 #include "wayland/compositor.h" 0014 #include "wayland/display.h" 0015 #include "wayland/keyboard_shortcuts_inhibit_v1.h" 0016 #include "wayland/seat.h" 0017 0018 #include "KWayland/Client/compositor.h" 0019 #include "KWayland/Client/connection_thread.h" 0020 #include "KWayland/Client/event_queue.h" 0021 #include "KWayland/Client/registry.h" 0022 #include "KWayland/Client/seat.h" 0023 #include "KWayland/Client/surface.h" 0024 0025 #include "qwayland-keyboard-shortcuts-inhibit-unstable-v1.h" 0026 0027 using namespace KWin; 0028 0029 class KeyboardShortcutsInhibitManager : public QObject, public QtWayland::zwp_keyboard_shortcuts_inhibit_manager_v1 0030 { 0031 Q_OBJECT 0032 public: 0033 KeyboardShortcutsInhibitManager(wl_registry *registry, quint32 id, quint32 version) 0034 : QtWayland::zwp_keyboard_shortcuts_inhibit_manager_v1(registry, id, version) 0035 { 0036 } 0037 }; 0038 0039 class KeyboardShortcutsInhibitor : public QObject, public QtWayland::zwp_keyboard_shortcuts_inhibitor_v1 0040 { 0041 Q_OBJECT 0042 public: 0043 KeyboardShortcutsInhibitor(::zwp_keyboard_shortcuts_inhibitor_v1 *inhibitorV1) 0044 : QtWayland::zwp_keyboard_shortcuts_inhibitor_v1(inhibitorV1) 0045 { 0046 } 0047 0048 void zwp_keyboard_shortcuts_inhibitor_v1_active() override 0049 { 0050 Q_EMIT inhibitorActive(); 0051 } 0052 0053 void zwp_keyboard_shortcuts_inhibitor_v1_inactive() override 0054 { 0055 Q_EMIT inhibitorInactive(); 0056 } 0057 0058 Q_SIGNALS: 0059 void inhibitorActive(); 0060 void inhibitorInactive(); 0061 }; 0062 0063 class TestKeyboardShortcutsInhibitorInterface : public QObject 0064 { 0065 Q_OBJECT 0066 public: 0067 TestKeyboardShortcutsInhibitorInterface() 0068 { 0069 } 0070 ~TestKeyboardShortcutsInhibitorInterface() override; 0071 0072 private Q_SLOTS: 0073 void initTestCase(); 0074 void testKeyboardShortcuts(); 0075 0076 private: 0077 KWayland::Client::ConnectionThread *m_connection; 0078 KWayland::Client::EventQueue *m_queue; 0079 KWayland::Client::Compositor *m_clientCompositor; 0080 KWayland::Client::Seat *m_clientSeat = nullptr; 0081 0082 QThread *m_thread; 0083 KWin::Display m_display; 0084 SeatInterface *m_seat; 0085 CompositorInterface *m_serverCompositor; 0086 0087 KeyboardShortcutsInhibitManagerV1Interface *m_manager; 0088 QList<SurfaceInterface *> m_surfaces; 0089 QList<wl_surface *> m_clientSurfaces; 0090 KeyboardShortcutsInhibitManager *m_inhibitManagerClient = nullptr; 0091 }; 0092 0093 static const QString s_socketName = QStringLiteral("kwin-wayland-server-keyboard-shortcuts-inhibitor-test-0"); 0094 0095 void TestKeyboardShortcutsInhibitorInterface::initTestCase() 0096 { 0097 m_display.addSocketName(s_socketName); 0098 m_display.start(); 0099 QVERIFY(m_display.isRunning()); 0100 0101 m_seat = new SeatInterface(&m_display, this); 0102 m_serverCompositor = new CompositorInterface(&m_display, this); 0103 m_manager = new KeyboardShortcutsInhibitManagerV1Interface(&m_display, this); 0104 0105 connect(m_serverCompositor, &CompositorInterface::surfaceCreated, this, [this](SurfaceInterface *surface) { 0106 m_surfaces += surface; 0107 }); 0108 0109 // setup connection 0110 m_connection = new KWayland::Client::ConnectionThread; 0111 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected); 0112 m_connection->setSocketName(s_socketName); 0113 0114 m_thread = new QThread(this); 0115 m_connection->moveToThread(m_thread); 0116 m_thread->start(); 0117 0118 m_connection->initConnection(); 0119 QVERIFY(connectedSpy.wait()); 0120 QVERIFY(!m_connection->connections().isEmpty()); 0121 0122 m_queue = new KWayland::Client::EventQueue(this); 0123 QVERIFY(!m_queue->isValid()); 0124 m_queue->setup(m_connection); 0125 QVERIFY(m_queue->isValid()); 0126 0127 auto registry = new KWayland::Client::Registry(this); 0128 connect(registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, registry](const QByteArray &interface, quint32 id, quint32 version) { 0129 if (interface == "zwp_keyboard_shortcuts_inhibit_manager_v1") { 0130 m_inhibitManagerClient = new KeyboardShortcutsInhibitManager(registry->registry(), id, version); 0131 } 0132 }); 0133 connect(registry, &KWayland::Client::Registry::seatAnnounced, this, [this, registry](quint32 name, quint32 version) { 0134 m_clientSeat = registry->createSeat(name, version); 0135 }); 0136 registry->setEventQueue(m_queue); 0137 QSignalSpy compositorSpy(registry, &KWayland::Client::Registry::compositorAnnounced); 0138 registry->create(m_connection->display()); 0139 QVERIFY(registry->isValid()); 0140 registry->setup(); 0141 wl_display_flush(m_connection->display()); 0142 0143 QVERIFY(compositorSpy.wait()); 0144 m_clientCompositor = registry->createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this); 0145 QVERIFY(m_clientCompositor->isValid()); 0146 0147 QSignalSpy surfaceSpy(m_serverCompositor, &CompositorInterface::surfaceCreated); 0148 for (int i = 0; i < 3; ++i) { 0149 KWayland::Client::Surface *s = m_clientCompositor->createSurface(this); 0150 m_clientSurfaces += s->operator wl_surface *(); 0151 } 0152 QVERIFY(surfaceSpy.count() < 3 && surfaceSpy.wait(200)); 0153 QVERIFY(m_surfaces.count() == 3); 0154 QVERIFY(m_inhibitManagerClient); 0155 } 0156 0157 TestKeyboardShortcutsInhibitorInterface::~TestKeyboardShortcutsInhibitorInterface() 0158 { 0159 if (m_queue) { 0160 delete m_queue; 0161 m_queue = nullptr; 0162 } 0163 if (m_thread) { 0164 m_thread->quit(); 0165 m_thread->wait(); 0166 delete m_thread; 0167 m_thread = nullptr; 0168 } 0169 m_connection->deleteLater(); 0170 m_connection = nullptr; 0171 } 0172 0173 void TestKeyboardShortcutsInhibitorInterface::testKeyboardShortcuts() 0174 { 0175 auto clientSurface = m_clientSurfaces[0]; 0176 auto surface = m_surfaces[0]; 0177 0178 // Test creation 0179 auto inhibitorClientV1 = m_inhibitManagerClient->inhibit_shortcuts(clientSurface, m_clientSeat->operator wl_seat *()); 0180 auto inhibitorClient = new KeyboardShortcutsInhibitor(inhibitorClientV1); 0181 QSignalSpy inhibitorActiveSpy(inhibitorClient, &KeyboardShortcutsInhibitor::inhibitorActive); 0182 QSignalSpy inhibitorInactiveSpy(inhibitorClient, &KeyboardShortcutsInhibitor::inhibitorInactive); 0183 QSignalSpy inhibitorCreatedSpy(m_manager, &KeyboardShortcutsInhibitManagerV1Interface::inhibitorCreated); 0184 QVERIFY(inhibitorCreatedSpy.wait() || inhibitorCreatedSpy.count() == 1); 0185 auto inhibitorServer = m_manager->findInhibitor(surface, m_seat); 0186 0187 // Test deactivate 0188 inhibitorServer->setActive(false); 0189 QVERIFY(inhibitorInactiveSpy.wait() || inhibitorInactiveSpy.count() == 1); 0190 0191 // Test activate 0192 inhibitorServer->setActive(true); 0193 QVERIFY(inhibitorActiveSpy.wait() || inhibitorActiveSpy.count() == 1); 0194 0195 // Test creating for another surface 0196 m_inhibitManagerClient->inhibit_shortcuts(m_clientSurfaces[1], m_clientSeat->operator wl_seat *()); 0197 QVERIFY(inhibitorCreatedSpy.wait() || inhibitorCreatedSpy.count() == 2); 0198 0199 // Test destroy is working 0200 inhibitorClient->destroy(); 0201 m_inhibitManagerClient->inhibit_shortcuts(clientSurface, m_clientSeat->operator wl_seat *()); 0202 QVERIFY(inhibitorCreatedSpy.wait() || inhibitorCreatedSpy.count() == 3); 0203 0204 // Test creating with same surface / seat (expect error) 0205 QSignalSpy errorOccured(m_connection, &KWayland::Client::ConnectionThread::errorOccurred); 0206 m_inhibitManagerClient->inhibit_shortcuts(m_clientSurfaces[0], m_clientSeat->operator wl_seat *()); 0207 QVERIFY(errorOccured.wait() || errorOccured.count() == 1); 0208 } 0209 0210 QTEST_GUILESS_MAIN(TestKeyboardShortcutsInhibitorInterface) 0211 0212 #include "test_keyboard_shortcuts_inhibitor_interface.moc"