[autotest/wayland] Add a test for quick tiling Wayland clients
Base test verifies the quick tile positions. No maximization or direct state changes tested yet. Required to have Toplevel and AbstractClient exported. Otherwise we cannot use the SignalSpy.
This commit is contained in:
parent
41af9c400c
commit
996c828da3
4 changed files with 233 additions and 2 deletions
|
@ -49,7 +49,7 @@ namespace Decoration
|
||||||
class DecorationPalette;
|
class DecorationPalette;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AbstractClient : public Toplevel
|
class KWIN_EXPORT AbstractClient : public Toplevel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,3 +17,12 @@ add_executable(testTransientNoInput ${testTransientNoInput_SRCS})
|
||||||
target_link_libraries( testTransientNoInput kwin Qt5::Test)
|
target_link_libraries( testTransientNoInput kwin Qt5::Test)
|
||||||
add_test(kwin-testTransientNoInput testTransientNoInput)
|
add_test(kwin-testTransientNoInput testTransientNoInput)
|
||||||
ecm_mark_as_test(testTransientNoInput)
|
ecm_mark_as_test(testTransientNoInput)
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
# Quick Tiling test
|
||||||
|
########################################################
|
||||||
|
set( testQuickTiling_SRCS quick_tiling_test.cpp kwin_wayland_test.cpp )
|
||||||
|
add_executable(testQuickTiling ${testQuickTiling_SRCS})
|
||||||
|
target_link_libraries( testQuickTiling kwin Qt5::Test)
|
||||||
|
add_test(kwin-testQuickTiling testQuickTiling)
|
||||||
|
ecm_mark_as_test(testQuickTiling)
|
||||||
|
|
222
autotests/wayland/quick_tiling_test.cpp
Normal file
222
autotests/wayland/quick_tiling_test.cpp
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
/********************************************************************
|
||||||
|
KWin - the KDE window manager
|
||||||
|
This file is part of the KDE project.
|
||||||
|
|
||||||
|
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*********************************************************************/
|
||||||
|
#include "kwin_wayland_test.h"
|
||||||
|
#include "abstract_backend.h"
|
||||||
|
#include "abstract_client.h"
|
||||||
|
#include "screens.h"
|
||||||
|
#include "wayland_server.h"
|
||||||
|
#include "workspace.h"
|
||||||
|
#include "shell_client.h"
|
||||||
|
|
||||||
|
#include <KWayland/Client/connection_thread.h>
|
||||||
|
#include <KWayland/Client/compositor.h>
|
||||||
|
#include <KWayland/Client/event_queue.h>
|
||||||
|
#include <KWayland/Client/registry.h>
|
||||||
|
#include <KWayland/Client/shell.h>
|
||||||
|
#include <KWayland/Client/shm_pool.h>
|
||||||
|
#include <KWayland/Client/surface.h>
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(KWin::AbstractClient::QuickTileMode)
|
||||||
|
|
||||||
|
namespace KWin
|
||||||
|
{
|
||||||
|
|
||||||
|
static const QString s_socketName = QStringLiteral("wayland_test_kwin_quick_tiling-0");
|
||||||
|
|
||||||
|
class QuickTilingTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private Q_SLOTS:
|
||||||
|
void initTestCase();
|
||||||
|
void init();
|
||||||
|
void cleanup();
|
||||||
|
void testQuickTiling_data();
|
||||||
|
void testQuickTiling();
|
||||||
|
|
||||||
|
private:
|
||||||
|
KWayland::Client::ConnectionThread *m_connection = nullptr;
|
||||||
|
KWayland::Client::Compositor *m_compositor = nullptr;
|
||||||
|
KWayland::Client::ShmPool *m_shm = nullptr;
|
||||||
|
KWayland::Client::Shell *m_shell = nullptr;
|
||||||
|
KWayland::Client::EventQueue *m_queue = nullptr;
|
||||||
|
QThread *m_thread = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
void QuickTilingTest::initTestCase()
|
||||||
|
{
|
||||||
|
qRegisterMetaType<KWin::ShellClient*>();
|
||||||
|
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
|
||||||
|
QVERIFY(workspaceCreatedSpy.isValid());
|
||||||
|
waylandServer()->backend()->setInitialWindowSize(QSize(1280, 1024));
|
||||||
|
waylandServer()->init(s_socketName.toLocal8Bit());
|
||||||
|
kwinApp()->start();
|
||||||
|
QVERIFY(workspaceCreatedSpy.wait());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickTilingTest::init()
|
||||||
|
{
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
// setup connection
|
||||||
|
m_connection = new ConnectionThread;
|
||||||
|
QSignalSpy connectedSpy(m_connection, &ConnectionThread::connected);
|
||||||
|
QVERIFY(connectedSpy.isValid());
|
||||||
|
m_connection->setSocketName(s_socketName);
|
||||||
|
|
||||||
|
m_thread = new QThread(this);
|
||||||
|
m_connection->moveToThread(m_thread);
|
||||||
|
m_thread->start();
|
||||||
|
|
||||||
|
m_connection->initConnection();
|
||||||
|
QVERIFY(connectedSpy.wait());
|
||||||
|
|
||||||
|
m_queue = new EventQueue(this);
|
||||||
|
QVERIFY(!m_queue->isValid());
|
||||||
|
m_queue->setup(m_connection);
|
||||||
|
QVERIFY(m_queue->isValid());
|
||||||
|
|
||||||
|
Registry registry;
|
||||||
|
registry.setEventQueue(m_queue);
|
||||||
|
QSignalSpy compositorSpy(®istry, &Registry::compositorAnnounced);
|
||||||
|
QSignalSpy shmSpy(®istry, &Registry::shmAnnounced);
|
||||||
|
QSignalSpy shellSpy(®istry, &Registry::shellAnnounced);
|
||||||
|
QSignalSpy allAnnounced(®istry, &Registry::interfacesAnnounced);
|
||||||
|
QVERIFY(allAnnounced.isValid());
|
||||||
|
QVERIFY(shmSpy.isValid());
|
||||||
|
QVERIFY(shellSpy.isValid());
|
||||||
|
QVERIFY(compositorSpy.isValid());
|
||||||
|
registry.create(m_connection->display());
|
||||||
|
QVERIFY(registry.isValid());
|
||||||
|
registry.setup();
|
||||||
|
QVERIFY(allAnnounced.wait());
|
||||||
|
QVERIFY(!compositorSpy.isEmpty());
|
||||||
|
QVERIFY(!shmSpy.isEmpty());
|
||||||
|
QVERIFY(!shellSpy.isEmpty());
|
||||||
|
|
||||||
|
m_compositor = registry.createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
|
||||||
|
QVERIFY(m_compositor->isValid());
|
||||||
|
m_shm = registry.createShmPool(shmSpy.first().first().value<quint32>(), shmSpy.first().last().value<quint32>(), this);
|
||||||
|
QVERIFY(m_shm->isValid());
|
||||||
|
m_shell = registry.createShell(shellSpy.first().first().value<quint32>(), shellSpy.first().last().value<quint32>(), this);
|
||||||
|
QVERIFY(m_shell->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickTilingTest::cleanup()
|
||||||
|
{
|
||||||
|
delete m_compositor;
|
||||||
|
m_compositor = nullptr;
|
||||||
|
delete m_shm;
|
||||||
|
m_shm = nullptr;
|
||||||
|
delete m_shell;
|
||||||
|
m_shell = nullptr;
|
||||||
|
delete m_queue;
|
||||||
|
m_queue = nullptr;
|
||||||
|
if (m_thread) {
|
||||||
|
m_thread->quit();
|
||||||
|
m_thread->wait();
|
||||||
|
delete m_thread;
|
||||||
|
m_thread = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickTilingTest::testQuickTiling_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<AbstractClient::QuickTileMode>("mode");
|
||||||
|
QTest::addColumn<QRect>("expectedGeometry");
|
||||||
|
|
||||||
|
#define FLAG(name) AbstractClient::QuickTileMode(AbstractClient::QuickTile##name)
|
||||||
|
|
||||||
|
QTest::newRow("left") << FLAG(Left) << QRect(0, 0, 640, 1024);
|
||||||
|
QTest::newRow("top") << FLAG(Top) << QRect(0, 0, 1280, 512);
|
||||||
|
QTest::newRow("right") << FLAG(Right) << QRect(640, 0, 640, 1024);
|
||||||
|
QTest::newRow("bottom") << FLAG(Bottom) << QRect(0, 512, 1280, 512);
|
||||||
|
|
||||||
|
QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRect(0, 0, 640, 512);
|
||||||
|
QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRect(640, 0, 640, 512);
|
||||||
|
QTest::newRow("bottom left") << (FLAG(Left) | FLAG(Bottom)) << QRect(0, 512, 640, 512);
|
||||||
|
QTest::newRow("bottom right") << (FLAG(Right) | FLAG(Bottom)) << QRect(640, 512, 640, 512);
|
||||||
|
|
||||||
|
#undef FLAG
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickTilingTest::testQuickTiling()
|
||||||
|
{
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
|
||||||
|
QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
|
||||||
|
QVERIFY(clientAddedSpy.isValid());
|
||||||
|
|
||||||
|
QScopedPointer<Surface> surface(m_compositor->createSurface());
|
||||||
|
QVERIFY(!surface.isNull());
|
||||||
|
|
||||||
|
QScopedPointer<ShellSurface> shellSurface(m_shell->createSurface(surface.data()));
|
||||||
|
QVERIFY(!shellSurface.isNull());
|
||||||
|
QSignalSpy sizeChangeSpy(shellSurface.data(), &ShellSurface::sizeChanged);
|
||||||
|
QVERIFY(sizeChangeSpy.isValid());
|
||||||
|
// let's render
|
||||||
|
QImage img(QSize(100, 50), QImage::Format_ARGB32);
|
||||||
|
img.fill(Qt::blue);
|
||||||
|
surface->attachBuffer(m_shm->createBuffer(img));
|
||||||
|
surface->damage(QRect(0, 0, 100, 50));
|
||||||
|
surface->commit(Surface::CommitFlag::None);
|
||||||
|
|
||||||
|
m_connection->flush();
|
||||||
|
QVERIFY(clientAddedSpy.wait());
|
||||||
|
AbstractClient *c = workspace()->activeClient();
|
||||||
|
QVERIFY(c);
|
||||||
|
QCOMPARE(clientAddedSpy.first().first().value<ShellClient*>(), c);
|
||||||
|
QCOMPARE(c->geometry(), QRect(0, 0, 100, 50));
|
||||||
|
QCOMPARE(c->quickTileMode(), AbstractClient::QuickTileNone);
|
||||||
|
QSignalSpy quickTileChangedSpy(c, &AbstractClient::quickTileModeChanged);
|
||||||
|
QVERIFY(quickTileChangedSpy.isValid());
|
||||||
|
QSignalSpy geometryChangedSpy(c, &AbstractClient::geometryChanged);
|
||||||
|
QVERIFY(geometryChangedSpy.isValid());
|
||||||
|
|
||||||
|
QFETCH(AbstractClient::QuickTileMode, mode);
|
||||||
|
QFETCH(QRect, expectedGeometry);
|
||||||
|
c->setQuickTileMode(mode, true);
|
||||||
|
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||||
|
// at this point the geometry did not yet change
|
||||||
|
QCOMPARE(c->geometry(), QRect(0, 0, 100, 50));
|
||||||
|
// but quick tile mode already changed
|
||||||
|
QCOMPARE(c->quickTileMode(), mode);
|
||||||
|
|
||||||
|
// but we got requested a new geometry
|
||||||
|
QVERIFY(sizeChangeSpy.wait());
|
||||||
|
QCOMPARE(sizeChangeSpy.count(), 1);
|
||||||
|
QCOMPARE(sizeChangeSpy.first().first().toSize(), expectedGeometry.size());
|
||||||
|
|
||||||
|
// attach a new image
|
||||||
|
img = QImage(expectedGeometry.size(), QImage::Format_ARGB32);
|
||||||
|
img.fill(Qt::red);
|
||||||
|
surface->attachBuffer(m_shm->createBuffer(img));
|
||||||
|
surface->damage(QRect(QPoint(0, 0), expectedGeometry.size()));
|
||||||
|
surface->commit(Surface::CommitFlag::None);
|
||||||
|
m_connection->flush();
|
||||||
|
|
||||||
|
QVERIFY(geometryChangedSpy.wait());
|
||||||
|
QCOMPARE(geometryChangedSpy.count(), 1);
|
||||||
|
QCOMPARE(c->geometry(), expectedGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
WAYLANTEST_MAIN(KWin::QuickTilingTest)
|
||||||
|
#include "quick_tiling_test.moc"
|
|
@ -67,7 +67,7 @@ enum class ReleaseReason {
|
||||||
KWinShutsDown ///< Release on KWin Shutdown (window still valid)
|
KWinShutsDown ///< Release on KWin Shutdown (window still valid)
|
||||||
};
|
};
|
||||||
|
|
||||||
class Toplevel
|
class KWIN_EXPORT Toplevel
|
||||||
: public QObject
|
: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
Loading…
Reference in a new issue