File indexing completed on 2024-05-12 05:30:31

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "kwin_wayland_test.h"
0010 
0011 #include "core/output.h"
0012 #include "debug_console.h"
0013 #include "internalwindow.h"
0014 #include "utils/xcbutils.h"
0015 #include "wayland_server.h"
0016 #include "window.h"
0017 #include "workspace.h"
0018 
0019 #include <KWayland/Client/compositor.h>
0020 #include <KWayland/Client/connection_thread.h>
0021 #include <KWayland/Client/shm_pool.h>
0022 #include <KWayland/Client/surface.h>
0023 
0024 #include <QPainter>
0025 #include <QRasterWindow>
0026 #include <QSignalSpy>
0027 
0028 namespace KWin
0029 {
0030 
0031 static const QString s_socketName = QStringLiteral("wayland_test_kwin_debug_console-0");
0032 
0033 class DebugConsoleTest : public QObject
0034 {
0035     Q_OBJECT
0036 private Q_SLOTS:
0037     void initTestCase();
0038     void cleanup();
0039     void topLevelTest_data();
0040     void topLevelTest();
0041     void testX11Window();
0042     void testX11Unmanaged();
0043     void testWaylandClient();
0044     void testInternalWindow();
0045     void testClosingDebugConsole();
0046 };
0047 
0048 void DebugConsoleTest::initTestCase()
0049 {
0050     qRegisterMetaType<KWin::Window *>();
0051     qRegisterMetaType<KWin::InternalWindow *>();
0052     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0053     QVERIFY(waylandServer()->init(s_socketName));
0054     Test::setOutputConfig({
0055         QRect(0, 0, 1280, 1024),
0056         QRect(1280, 0, 1280, 1024),
0057     });
0058 
0059     kwinApp()->start();
0060     QVERIFY(applicationStartedSpy.wait());
0061     const auto outputs = workspace()->outputs();
0062     QCOMPARE(outputs.count(), 2);
0063     QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
0064     QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
0065     setenv("QT_QPA_PLATFORM", "wayland", true);
0066 }
0067 
0068 void DebugConsoleTest::cleanup()
0069 {
0070     Test::destroyWaylandConnection();
0071 }
0072 
0073 void DebugConsoleTest::topLevelTest_data()
0074 {
0075     QTest::addColumn<int>("row");
0076     QTest::addColumn<int>("column");
0077     QTest::addColumn<bool>("expectedValid");
0078 
0079     // this tests various combinations of row/column on the top level whether they are valid
0080     // valid are rows 0-4 with column 0, everything else is invalid
0081     QTest::newRow("0/0") << 0 << 0 << true;
0082     QTest::newRow("0/1") << 0 << 1 << false;
0083     QTest::newRow("0/3") << 0 << 3 << false;
0084     QTest::newRow("1/0") << 1 << 0 << true;
0085     QTest::newRow("1/1") << 1 << 1 << false;
0086     QTest::newRow("1/3") << 1 << 3 << false;
0087     QTest::newRow("2/0") << 2 << 0 << true;
0088     QTest::newRow("3/0") << 3 << 0 << true;
0089     QTest::newRow("4/0") << 4 << 0 << false;
0090     QTest::newRow("100/0") << 4 << 0 << false;
0091 }
0092 
0093 void DebugConsoleTest::topLevelTest()
0094 {
0095     DebugConsoleModel model;
0096     QCOMPARE(model.rowCount(QModelIndex()), 4);
0097     QCOMPARE(model.columnCount(QModelIndex()), 2);
0098     QFETCH(int, row);
0099     QFETCH(int, column);
0100     const QModelIndex index = model.index(row, column, QModelIndex());
0101     QTEST(index.isValid(), "expectedValid");
0102     if (index.isValid()) {
0103         QVERIFY(!model.parent(index).isValid());
0104         QVERIFY(model.data(index, Qt::DisplayRole).isValid());
0105         QCOMPARE(model.data(index, Qt::DisplayRole).userType(), int(QMetaType::QString));
0106         for (int i = Qt::DecorationRole; i <= Qt::UserRole; i++) {
0107             QVERIFY(!model.data(index, i).isValid());
0108         }
0109     }
0110 }
0111 
0112 void DebugConsoleTest::testX11Window()
0113 {
0114     DebugConsoleModel model;
0115     QModelIndex x11TopLevelIndex = model.index(0, 0, QModelIndex());
0116     QVERIFY(x11TopLevelIndex.isValid());
0117     // we don't have any windows yet
0118     QCOMPARE(model.rowCount(x11TopLevelIndex), 0);
0119     QVERIFY(!model.hasChildren(x11TopLevelIndex));
0120     // child index must be invalid
0121     QVERIFY(!model.index(0, 0, x11TopLevelIndex).isValid());
0122     QVERIFY(!model.index(0, 1, x11TopLevelIndex).isValid());
0123     QVERIFY(!model.index(0, 2, x11TopLevelIndex).isValid());
0124     QVERIFY(!model.index(1, 0, x11TopLevelIndex).isValid());
0125 
0126     // start glxgears, to get a window, which should be added to the model
0127     QSignalSpy rowsInsertedSpy(&model, &QAbstractItemModel::rowsInserted);
0128 
0129     QProcess glxgears;
0130     glxgears.setProgram(QStringLiteral("glxgears"));
0131     glxgears.start();
0132     QVERIFY(glxgears.waitForStarted());
0133 
0134     QVERIFY(rowsInsertedSpy.wait());
0135     QCOMPARE(rowsInsertedSpy.count(), 1);
0136     QVERIFY(model.hasChildren(x11TopLevelIndex));
0137     QCOMPARE(model.rowCount(x11TopLevelIndex), 1);
0138     QCOMPARE(rowsInsertedSpy.first().at(0).value<QModelIndex>(), x11TopLevelIndex);
0139     QCOMPARE(rowsInsertedSpy.first().at(1).value<int>(), 0);
0140     QCOMPARE(rowsInsertedSpy.first().at(2).value<int>(), 0);
0141 
0142     QModelIndex windowIndex = model.index(0, 0, x11TopLevelIndex);
0143     QVERIFY(windowIndex.isValid());
0144     QCOMPARE(model.parent(windowIndex), x11TopLevelIndex);
0145     QVERIFY(model.hasChildren(windowIndex));
0146     QVERIFY(model.rowCount(windowIndex) != 0);
0147     QCOMPARE(model.columnCount(windowIndex), 2);
0148     // other indexes are still invalid
0149     QVERIFY(!model.index(0, 1, x11TopLevelIndex).isValid());
0150     QVERIFY(!model.index(0, 2, x11TopLevelIndex).isValid());
0151     QVERIFY(!model.index(1, 0, x11TopLevelIndex).isValid());
0152 
0153     // the windowIndex has children and those are properties
0154     for (int i = 0; i < model.rowCount(windowIndex); i++) {
0155         const QModelIndex propNameIndex = model.index(i, 0, windowIndex);
0156         QVERIFY(propNameIndex.isValid());
0157         QCOMPARE(model.parent(propNameIndex), windowIndex);
0158         QVERIFY(!model.hasChildren(propNameIndex));
0159         QVERIFY(!model.index(0, 0, propNameIndex).isValid());
0160         QVERIFY(model.data(propNameIndex, Qt::DisplayRole).isValid());
0161         QCOMPARE(model.data(propNameIndex, Qt::DisplayRole).userType(), int(QMetaType::QString));
0162 
0163         // and the value
0164         const QModelIndex propValueIndex = model.index(i, 1, windowIndex);
0165         QVERIFY(propValueIndex.isValid());
0166         QCOMPARE(model.parent(propValueIndex), windowIndex);
0167         QVERIFY(!model.index(0, 0, propValueIndex).isValid());
0168         QVERIFY(!model.hasChildren(propValueIndex));
0169         // TODO: how to test whether the values actually work?
0170 
0171         // and on third column we should not get an index any more
0172         QVERIFY(!model.index(i, 2, windowIndex).isValid());
0173     }
0174     // row after count should be invalid
0175     QVERIFY(!model.index(model.rowCount(windowIndex), 0, windowIndex).isValid());
0176 
0177     // creating a second model should be initialized directly with the X11 child
0178     DebugConsoleModel model2;
0179     QVERIFY(model2.hasChildren(model2.index(0, 0, QModelIndex())));
0180 
0181     // now close the window again, it should be removed from the model
0182     QSignalSpy rowsRemovedSpy(&model, &QAbstractItemModel::rowsRemoved);
0183 
0184     glxgears.terminate();
0185     QVERIFY(glxgears.waitForFinished());
0186 
0187     QVERIFY(rowsRemovedSpy.wait());
0188     QCOMPARE(rowsRemovedSpy.count(), 1);
0189     QCOMPARE(rowsRemovedSpy.first().first().value<QModelIndex>(), x11TopLevelIndex);
0190     QCOMPARE(rowsRemovedSpy.first().at(1).value<int>(), 0);
0191     QCOMPARE(rowsRemovedSpy.first().at(2).value<int>(), 0);
0192 
0193     // the child should be gone again
0194     QVERIFY(!model.hasChildren(x11TopLevelIndex));
0195     QVERIFY(!model2.hasChildren(model2.index(0, 0, QModelIndex())));
0196 }
0197 
0198 void DebugConsoleTest::testX11Unmanaged()
0199 {
0200     DebugConsoleModel model;
0201     QModelIndex unmanagedTopLevelIndex = model.index(1, 0, QModelIndex());
0202     QVERIFY(unmanagedTopLevelIndex.isValid());
0203     // we don't have any windows yet
0204     QCOMPARE(model.rowCount(unmanagedTopLevelIndex), 0);
0205     QVERIFY(!model.hasChildren(unmanagedTopLevelIndex));
0206     // child index must be invalid
0207     QVERIFY(!model.index(0, 0, unmanagedTopLevelIndex).isValid());
0208     QVERIFY(!model.index(0, 1, unmanagedTopLevelIndex).isValid());
0209     QVERIFY(!model.index(0, 2, unmanagedTopLevelIndex).isValid());
0210     QVERIFY(!model.index(1, 0, unmanagedTopLevelIndex).isValid());
0211 
0212     // we need to create an unmanaged window
0213     QSignalSpy rowsInsertedSpy(&model, &QAbstractItemModel::rowsInserted);
0214 
0215     // let's create an override redirect window
0216     const uint32_t values[] = {true};
0217     Xcb::Window window(QRect(0, 0, 10, 10), XCB_CW_OVERRIDE_REDIRECT, values);
0218     window.map();
0219 
0220     QVERIFY(rowsInsertedSpy.wait());
0221     QCOMPARE(rowsInsertedSpy.count(), 1);
0222     QVERIFY(model.hasChildren(unmanagedTopLevelIndex));
0223     QCOMPARE(model.rowCount(unmanagedTopLevelIndex), 1);
0224     QCOMPARE(rowsInsertedSpy.first().at(0).value<QModelIndex>(), unmanagedTopLevelIndex);
0225     QCOMPARE(rowsInsertedSpy.first().at(1).value<int>(), 0);
0226     QCOMPARE(rowsInsertedSpy.first().at(2).value<int>(), 0);
0227 
0228     QModelIndex windowIndex = model.index(0, 0, unmanagedTopLevelIndex);
0229     QVERIFY(windowIndex.isValid());
0230     QCOMPARE(model.parent(windowIndex), unmanagedTopLevelIndex);
0231     QVERIFY(model.hasChildren(windowIndex));
0232     QVERIFY(model.rowCount(windowIndex) != 0);
0233     QCOMPARE(model.columnCount(windowIndex), 2);
0234     // other indexes are still invalid
0235     QVERIFY(!model.index(0, 1, unmanagedTopLevelIndex).isValid());
0236     QVERIFY(!model.index(0, 2, unmanagedTopLevelIndex).isValid());
0237     QVERIFY(!model.index(1, 0, unmanagedTopLevelIndex).isValid());
0238 
0239     QCOMPARE(model.data(windowIndex, Qt::DisplayRole).toString(), QStringLiteral("0x%1").arg(window, 0, 16));
0240 
0241     // the windowIndex has children and those are properties
0242     for (int i = 0; i < model.rowCount(windowIndex); i++) {
0243         const QModelIndex propNameIndex = model.index(i, 0, windowIndex);
0244         QVERIFY(propNameIndex.isValid());
0245         QCOMPARE(model.parent(propNameIndex), windowIndex);
0246         QVERIFY(!model.hasChildren(propNameIndex));
0247         QVERIFY(!model.index(0, 0, propNameIndex).isValid());
0248         QVERIFY(model.data(propNameIndex, Qt::DisplayRole).isValid());
0249         QCOMPARE(model.data(propNameIndex, Qt::DisplayRole).userType(), int(QMetaType::QString));
0250 
0251         // and the value
0252         const QModelIndex propValueIndex = model.index(i, 1, windowIndex);
0253         QVERIFY(propValueIndex.isValid());
0254         QCOMPARE(model.parent(propValueIndex), windowIndex);
0255         QVERIFY(!model.index(0, 0, propValueIndex).isValid());
0256         QVERIFY(!model.hasChildren(propValueIndex));
0257         // TODO: how to test whether the values actually work?
0258 
0259         // and on third column we should not get an index any more
0260         QVERIFY(!model.index(i, 2, windowIndex).isValid());
0261     }
0262     // row after count should be invalid
0263     QVERIFY(!model.index(model.rowCount(windowIndex), 0, windowIndex).isValid());
0264 
0265     // creating a second model should be initialized directly with the X11 child
0266     DebugConsoleModel model2;
0267     QVERIFY(model2.hasChildren(model2.index(1, 0, QModelIndex())));
0268 
0269     // now close the window again, it should be removed from the model
0270     QSignalSpy rowsRemovedSpy(&model, &QAbstractItemModel::rowsRemoved);
0271 
0272     window.unmap();
0273 
0274     QVERIFY(rowsRemovedSpy.wait());
0275     QCOMPARE(rowsRemovedSpy.count(), 1);
0276     QCOMPARE(rowsRemovedSpy.first().first().value<QModelIndex>(), unmanagedTopLevelIndex);
0277     QCOMPARE(rowsRemovedSpy.first().at(1).value<int>(), 0);
0278     QCOMPARE(rowsRemovedSpy.first().at(2).value<int>(), 0);
0279 
0280     // the child should be gone again
0281     QVERIFY(!model.hasChildren(unmanagedTopLevelIndex));
0282     QVERIFY(!model2.hasChildren(model2.index(1, 0, QModelIndex())));
0283 }
0284 
0285 void DebugConsoleTest::testWaylandClient()
0286 {
0287     DebugConsoleModel model;
0288     QModelIndex waylandTopLevelIndex = model.index(2, 0, QModelIndex());
0289     QVERIFY(waylandTopLevelIndex.isValid());
0290 
0291     // we don't have any windows yet
0292     QCOMPARE(model.rowCount(waylandTopLevelIndex), 0);
0293     QVERIFY(!model.hasChildren(waylandTopLevelIndex));
0294     // child index must be invalid
0295     QVERIFY(!model.index(0, 0, waylandTopLevelIndex).isValid());
0296     QVERIFY(!model.index(0, 1, waylandTopLevelIndex).isValid());
0297     QVERIFY(!model.index(0, 2, waylandTopLevelIndex).isValid());
0298     QVERIFY(!model.index(1, 0, waylandTopLevelIndex).isValid());
0299 
0300     // we need to create a wayland window
0301     QSignalSpy rowsInsertedSpy(&model, &QAbstractItemModel::rowsInserted);
0302 
0303     // create our connection
0304     QVERIFY(Test::setupWaylandConnection());
0305 
0306     // create the Surface and ShellSurface
0307     std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
0308     QVERIFY(surface->isValid());
0309     std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
0310     QVERIFY(shellSurface != nullptr);
0311     Test::render(surface.get(), QSize(10, 10), Qt::red);
0312 
0313     // now we have the window, it should be added to our model
0314     QVERIFY(rowsInsertedSpy.wait());
0315     QCOMPARE(rowsInsertedSpy.count(), 1);
0316 
0317     QVERIFY(model.hasChildren(waylandTopLevelIndex));
0318     QCOMPARE(model.rowCount(waylandTopLevelIndex), 1);
0319     QCOMPARE(rowsInsertedSpy.first().at(0).value<QModelIndex>(), waylandTopLevelIndex);
0320     QCOMPARE(rowsInsertedSpy.first().at(1).value<int>(), 0);
0321     QCOMPARE(rowsInsertedSpy.first().at(2).value<int>(), 0);
0322 
0323     QModelIndex windowIndex = model.index(0, 0, waylandTopLevelIndex);
0324     QVERIFY(windowIndex.isValid());
0325     QCOMPARE(model.parent(windowIndex), waylandTopLevelIndex);
0326     QVERIFY(model.hasChildren(windowIndex));
0327     QVERIFY(model.rowCount(windowIndex) != 0);
0328     QCOMPARE(model.columnCount(windowIndex), 2);
0329     // other indexes are still invalid
0330     QVERIFY(!model.index(0, 1, waylandTopLevelIndex).isValid());
0331     QVERIFY(!model.index(0, 2, waylandTopLevelIndex).isValid());
0332     QVERIFY(!model.index(1, 0, waylandTopLevelIndex).isValid());
0333 
0334     // the windowIndex has children and those are properties
0335     for (int i = 0; i < model.rowCount(windowIndex); i++) {
0336         const QModelIndex propNameIndex = model.index(i, 0, windowIndex);
0337         QVERIFY(propNameIndex.isValid());
0338         QCOMPARE(model.parent(propNameIndex), windowIndex);
0339         QVERIFY(!model.hasChildren(propNameIndex));
0340         QVERIFY(!model.index(0, 0, propNameIndex).isValid());
0341         QVERIFY(model.data(propNameIndex, Qt::DisplayRole).isValid());
0342         QCOMPARE(model.data(propNameIndex, Qt::DisplayRole).userType(), int(QMetaType::QString));
0343 
0344         // and the value
0345         const QModelIndex propValueIndex = model.index(i, 1, windowIndex);
0346         QVERIFY(propValueIndex.isValid());
0347         QCOMPARE(model.parent(propValueIndex), windowIndex);
0348         QVERIFY(!model.index(0, 0, propValueIndex).isValid());
0349         QVERIFY(!model.hasChildren(propValueIndex));
0350         // TODO: how to test whether the values actually work?
0351 
0352         // and on third column we should not get an index any more
0353         QVERIFY(!model.index(i, 2, windowIndex).isValid());
0354     }
0355     // row after count should be invalid
0356     QVERIFY(!model.index(model.rowCount(windowIndex), 0, windowIndex).isValid());
0357 
0358     // creating a second model should be initialized directly with the X11 child
0359     DebugConsoleModel model2;
0360     QVERIFY(model2.hasChildren(model2.index(2, 0, QModelIndex())));
0361 
0362     // now close the window again, it should be removed from the model
0363     QSignalSpy rowsRemovedSpy(&model, &QAbstractItemModel::rowsRemoved);
0364 
0365     surface->attachBuffer(KWayland::Client::Buffer::Ptr());
0366     surface->commit(KWayland::Client::Surface::CommitFlag::None);
0367     QVERIFY(rowsRemovedSpy.wait());
0368 
0369     QCOMPARE(rowsRemovedSpy.count(), 1);
0370     QCOMPARE(rowsRemovedSpy.first().first().value<QModelIndex>(), waylandTopLevelIndex);
0371     QCOMPARE(rowsRemovedSpy.first().at(1).value<int>(), 0);
0372     QCOMPARE(rowsRemovedSpy.first().at(2).value<int>(), 0);
0373 
0374     // the child should be gone again
0375     QVERIFY(!model.hasChildren(waylandTopLevelIndex));
0376     QVERIFY(!model2.hasChildren(model2.index(2, 0, QModelIndex())));
0377 }
0378 
0379 class HelperWindow : public QRasterWindow
0380 {
0381     Q_OBJECT
0382 public:
0383     HelperWindow()
0384         : QRasterWindow(nullptr)
0385     {
0386     }
0387     ~HelperWindow() override = default;
0388 
0389 Q_SIGNALS:
0390     void entered();
0391     void left();
0392     void mouseMoved(const QPoint &global);
0393     void mousePressed();
0394     void mouseReleased();
0395     void wheel();
0396     void keyPressed();
0397     void keyReleased();
0398 
0399 protected:
0400     void paintEvent(QPaintEvent *event) override
0401     {
0402         QPainter p(this);
0403         p.fillRect(0, 0, width(), height(), Qt::red);
0404     }
0405 };
0406 
0407 void DebugConsoleTest::testInternalWindow()
0408 {
0409     DebugConsoleModel model;
0410     QModelIndex internalTopLevelIndex = model.index(3, 0, QModelIndex());
0411     QVERIFY(internalTopLevelIndex.isValid());
0412 
0413     // there might already be some internal windows, so we cannot reliable test whether there are children
0414     // given that we just test whether adding a window works.
0415 
0416     QSignalSpy rowsInsertedSpy(&model, &QAbstractItemModel::rowsInserted);
0417 
0418     std::unique_ptr<HelperWindow> w(new HelperWindow);
0419     w->setGeometry(0, 0, 100, 100);
0420     w->show();
0421 
0422     QTRY_COMPARE(rowsInsertedSpy.count(), 1);
0423     QCOMPARE(rowsInsertedSpy.first().first().value<QModelIndex>(), internalTopLevelIndex);
0424 
0425     QModelIndex windowIndex = model.index(rowsInsertedSpy.first().last().toInt(), 0, internalTopLevelIndex);
0426     QVERIFY(windowIndex.isValid());
0427     QCOMPARE(model.parent(windowIndex), internalTopLevelIndex);
0428     QVERIFY(model.hasChildren(windowIndex));
0429     QVERIFY(model.rowCount(windowIndex) != 0);
0430     QCOMPARE(model.columnCount(windowIndex), 2);
0431     // other indexes are still invalid
0432     QVERIFY(!model.index(rowsInsertedSpy.first().last().toInt(), 1, internalTopLevelIndex).isValid());
0433     QVERIFY(!model.index(rowsInsertedSpy.first().last().toInt(), 2, internalTopLevelIndex).isValid());
0434     QVERIFY(!model.index(rowsInsertedSpy.first().last().toInt() + 1, 0, internalTopLevelIndex).isValid());
0435 
0436     // the wayland shell client top level should not have gained this window
0437     QVERIFY(!model.hasChildren(model.index(2, 0, QModelIndex())));
0438 
0439     // the windowIndex has children and those are properties
0440     for (int i = 0; i < model.rowCount(windowIndex); i++) {
0441         const QModelIndex propNameIndex = model.index(i, 0, windowIndex);
0442         QVERIFY(propNameIndex.isValid());
0443         QCOMPARE(model.parent(propNameIndex), windowIndex);
0444         QVERIFY(!model.hasChildren(propNameIndex));
0445         QVERIFY(!model.index(0, 0, propNameIndex).isValid());
0446         QVERIFY(model.data(propNameIndex, Qt::DisplayRole).isValid());
0447         QCOMPARE(model.data(propNameIndex, Qt::DisplayRole).userType(), int(QMetaType::QString));
0448 
0449         // and the value
0450         const QModelIndex propValueIndex = model.index(i, 1, windowIndex);
0451         QVERIFY(propValueIndex.isValid());
0452         QCOMPARE(model.parent(propValueIndex), windowIndex);
0453         QVERIFY(!model.index(0, 0, propValueIndex).isValid());
0454         QVERIFY(!model.hasChildren(propValueIndex));
0455         // TODO: how to test whether the values actually work?
0456 
0457         // and on third column we should not get an index any more
0458         QVERIFY(!model.index(i, 2, windowIndex).isValid());
0459     }
0460     // row after count should be invalid
0461     QVERIFY(!model.index(model.rowCount(windowIndex), 0, windowIndex).isValid());
0462 
0463     // now close the window again, it should be removed from the model
0464     QSignalSpy rowsRemovedSpy(&model, &QAbstractItemModel::rowsRemoved);
0465 
0466     w->hide();
0467     w.reset();
0468 
0469     QTRY_COMPARE(rowsRemovedSpy.count(), 1);
0470     QCOMPARE(rowsRemovedSpy.first().first().value<QModelIndex>(), internalTopLevelIndex);
0471 }
0472 
0473 void DebugConsoleTest::testClosingDebugConsole()
0474 {
0475     // this test verifies that the DebugConsole gets destroyed when closing the window
0476     // BUG: 369858
0477 
0478     DebugConsole *console = new DebugConsole;
0479     QSignalSpy destroyedSpy(console, &QObject::destroyed);
0480 
0481     QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
0482     console->show();
0483     QCOMPARE(console->windowHandle()->isVisible(), true);
0484     QTRY_COMPARE(windowAddedSpy.count(), 1);
0485     InternalWindow *window = windowAddedSpy.first().first().value<InternalWindow *>();
0486     QVERIFY(window->isInternal());
0487     QCOMPARE(window->handle(), console->windowHandle());
0488     QVERIFY(window->isDecorated());
0489     QCOMPARE(window->isMinimizable(), false);
0490     window->closeWindow();
0491     QVERIFY(destroyedSpy.wait());
0492 }
0493 
0494 }
0495 
0496 WAYLANDTEST_MAIN(KWin::DebugConsoleTest)
0497 #include "debug_console_test.moc"