kwin/autotests/integration/dont_crash_aurorae_destroy_deco.cpp
Vlad Zahorodnii 8e7a8c5a11 Rename AbstractOutput to Output
AbstractOutput is not so Abstract and it's common to avoid the word
"Abstract" in class names as it doesn't contribute any new information.
It also significantly reduces the line width in some places.
2022-04-15 17:49:49 +03:00

144 lines
5.1 KiB
C++

/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "kwin_wayland_test.h"
#include "composite.h"
#include "cursor.h"
#include "output.h"
#include "platform.h"
#include "renderbackend.h"
#include "wayland_server.h"
#include "workspace.h"
#include "x11client.h"
#include <kwineffects.h>
#include <KDecoration2/Decoration>
#include <QQuickItem>
#include <linux/input.h>
namespace KWin
{
static const QString s_socketName = QStringLiteral("wayland_test_kwin_dont_crash_aurorae_destroy_deco-0");
class DontCrashAuroraeDestroyDecoTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void init();
void testBorderlessMaximizedWindows();
};
void DontCrashAuroraeDestroyDecoTest::initTestCase()
{
qputenv("XDG_DATA_DIRS", QCoreApplication::applicationDirPath().toUtf8());
qRegisterMetaType<KWin::AbstractClient *>();
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
QVERIFY(applicationStartedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QVERIFY(waylandServer()->init(s_socketName));
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2));
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("org.kde.kdecoration2").writeEntry("library", "org.kde.kwin.aurorae");
config->sync();
kwinApp()->setConfig(config);
// this test needs to enforce OpenGL compositing to get into the crashy condition
qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2"));
kwinApp()->start();
QVERIFY(applicationStartedSpy.wait());
const auto outputs = kwinApp()->platform()->enabledOutputs();
QCOMPARE(outputs.count(), 2);
QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
setenv("QT_QPA_PLATFORM", "wayland", true);
Test::initWaylandWorkspace();
QCOMPARE(Compositor::self()->backend()->compositingType(), KWin::OpenGLCompositing);
}
void DontCrashAuroraeDestroyDecoTest::init()
{
workspace()->setActiveOutput(QPoint(640, 512));
Cursors::self()->mouse()->setPos(QPoint(640, 512));
}
void DontCrashAuroraeDestroyDecoTest::testBorderlessMaximizedWindows()
{
// this test verifies that Aurorae doesn't crash when clicking the maximize button
// with kwin config option BorderlessMaximizedWindows
// see BUG 362772
// first adjust the config
KConfigGroup group = kwinApp()->config()->group("Windows");
group.writeEntry("BorderlessMaximizedWindows", true);
group.sync();
workspace()->slotReconfigure();
QCOMPARE(options->borderlessMaximizedWindows(), true);
// create an xcb window
xcb_connection_t *c = xcb_connect(nullptr, nullptr);
QVERIFY(!xcb_connection_has_error(c));
xcb_window_t w = xcb_generate_id(c);
xcb_create_window(c, XCB_COPY_FROM_PARENT, w, rootWindow(), 0, 0, 100, 200, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
xcb_map_window(c, w);
xcb_flush(c);
// we should get a client for it
QSignalSpy windowCreatedSpy(workspace(), &Workspace::clientAdded);
QVERIFY(windowCreatedSpy.isValid());
QVERIFY(windowCreatedSpy.wait());
X11Client *client = windowCreatedSpy.first().first().value<X11Client *>();
QVERIFY(client);
QCOMPARE(client->window(), w);
QVERIFY(client->isDecorated());
QCOMPARE(client->maximizeMode(), MaximizeRestore);
QCOMPARE(client->noBorder(), false);
// verify that the deco is Aurorae
QCOMPARE(qstrcmp(client->decoration()->metaObject()->className(), "Aurorae::Decoration"), 0);
// find the maximize button
QQuickItem *item = client->decoration()->findChild<QQuickItem *>("maximizeButton");
QVERIFY(item);
const QPointF scenePoint = item->mapToScene(QPoint(0, 0));
// mark the window as ready for painting, otherwise it doesn't get input events
QMetaObject::invokeMethod(client, "setReadyForPainting");
QVERIFY(client->readyForPainting());
// simulate click on maximize button
QSignalSpy maximizedStateChangedSpy(client, static_cast<void (AbstractClient::*)(KWin::AbstractClient *, MaximizeMode)>(&AbstractClient::clientMaximizedStateChanged));
QVERIFY(maximizedStateChangedSpy.isValid());
quint32 timestamp = 1;
Test::pointerMotion(client->frameGeometry().topLeft() + scenePoint.toPoint(), timestamp++);
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
QVERIFY(maximizedStateChangedSpy.wait());
QCOMPARE(client->maximizeMode(), MaximizeFull);
QCOMPARE(client->noBorder(), true);
// and destroy the window again
xcb_unmap_window(c, w);
xcb_destroy_window(c, w);
xcb_flush(c);
xcb_disconnect(c);
QSignalSpy windowClosedSpy(client, &X11Client::windowClosed);
QVERIFY(windowClosedSpy.isValid());
QVERIFY(windowClosedSpy.wait());
}
}
WAYLANDTEST_MAIN(KWin::DontCrashAuroraeDestroyDecoTest)
#include "dont_crash_aurorae_destroy_deco.moc"