8e7a8c5a11
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.
144 lines
5.1 KiB
C++
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"
|