174 lines
7.3 KiB
C++
174 lines
7.3 KiB
C++
// SPDX-License-Identifier: MIT
|
|
|
|
#include <QQmlComponent>
|
|
#include <QQmlEngine>
|
|
#include <QQuickWindow>
|
|
#include <QQuickItem>
|
|
#include <QTest>
|
|
#include <memory>
|
|
#include <QDBusConnection>
|
|
#include <QSignalSpy>
|
|
#include <plasma/plasma.h>
|
|
#include "../previewplacement.h"
|
|
#include "../taskbargeometry.h"
|
|
#include <abstracttasksmodel.h>
|
|
#include <tasksmodel.h>
|
|
|
|
class PreviewTest : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private Q_SLOTS:
|
|
void placementTracksButtonAndScreenEdges()
|
|
{
|
|
const QRect screen(0, 0, 1000, 800);
|
|
const QSize size(300, 200);
|
|
QCOMPARE(previewPosition(QRect(400, 760, 100, 40), screen, size, Plasma::Types::BottomEdge), QPoint(300, 560));
|
|
QCOMPARE(previewPosition(QRect(0, 760, 100, 40), screen, size, Plasma::Types::BottomEdge), QPoint(0, 560));
|
|
QCOMPARE(previewPosition(QRect(900, 760, 100, 40), screen, size, Plasma::Types::BottomEdge), QPoint(700, 560));
|
|
QCOMPARE(previewPosition(QRect(400, 0, 100, 40), screen, size, Plasma::Types::TopEdge), QPoint(300, 40));
|
|
QCOMPARE(previewPosition(QRect(0, 300, 40, 100), screen, size, Plasma::Types::LeftEdge), QPoint(40, 250));
|
|
QCOMPARE(previewPosition(QRect(960, 300, 40, 100), screen, size, Plasma::Types::RightEdge), QPoint(660, 250));
|
|
QCOMPARE(previewPosition(QRect(-1000, 760, 100, 40), QRect(-1000, 0, 1000, 800), size,
|
|
Plasma::Types::BottomEdge), QPoint(-1000, 560));
|
|
QCOMPARE(previewPosition({}, screen, size, Plasma::Types::BottomEdge), QPoint(350, 600));
|
|
}
|
|
|
|
void geometryBridgeOnWayland()
|
|
{
|
|
if (QGuiApplication::platformName() != QLatin1String("wayland")) {
|
|
QSKIP("Requires KWin's Wayland compositor");
|
|
}
|
|
auto bus = QDBusConnection::sessionBus();
|
|
const QString service = QStringLiteral("se.ajpanton.plasma-task-group-shortcuts");
|
|
QVERIFY(bus.registerService(service));
|
|
{
|
|
TaskbarGeometry geometry;
|
|
QSignalSpy results(&geometry, &TaskbarGeometry::received);
|
|
QSignalSpy lookups(&geometry, &TaskbarGeometry::lookup);
|
|
// The script must respond even when a window has disappeared.
|
|
geometry.request(QStringLiteral("nonexistent-window"));
|
|
QTRY_COMPARE(lookups.count(), 1);
|
|
QTRY_COMPARE(results.count(), 1);
|
|
QVERIFY(results.first().first().toRectF().isEmpty());
|
|
geometry.request(QStringLiteral("another-window"));
|
|
geometry.cancel();
|
|
QTest::qWait(100);
|
|
QCOMPARE(results.count(), 1);
|
|
}
|
|
QVERIFY(bus.unregisterService(service));
|
|
}
|
|
|
|
void findsPublishedButtonGeometryOnWayland()
|
|
{
|
|
if (QGuiApplication::platformName() != QLatin1String("wayland")) {
|
|
QSKIP("Requires KWin and the plasma-window-management protocol");
|
|
}
|
|
TaskManager::TasksModel model;
|
|
model.setGroupMode(TaskManager::TasksModel::GroupDisabled);
|
|
QQuickWindow target;
|
|
target.setTitle(QStringLiteral("Task group geometry test"));
|
|
target.resize(400, 300);
|
|
target.show();
|
|
QTRY_VERIFY(target.isExposed());
|
|
const auto matching = [&] {
|
|
return model.match(model.index(0, 0), Qt::DisplayRole, target.title());
|
|
};
|
|
QTRY_VERIFY(!matching().isEmpty());
|
|
const QModelIndex index = matching().first();
|
|
const QString uuid = index.data(TaskManager::AbstractTasksModel::WinIdList).toList().first().toString();
|
|
QVERIFY(!uuid.isEmpty());
|
|
|
|
QQuickWindow panel;
|
|
panel.setTitle(QStringLiteral("Task group geometry panel"));
|
|
panel.resize(1000, 40);
|
|
panel.show();
|
|
QTRY_VERIFY(panel.isExposed());
|
|
const auto panelTask = [&] {
|
|
return model.match(model.index(0, 0), Qt::DisplayRole, panel.title());
|
|
};
|
|
QTRY_VERIFY(!panelTask().isEmpty());
|
|
QTRY_VERIFY(panelTask().first().data(TaskManager::AbstractTasksModel::Geometry).toRect().isValid());
|
|
const QPoint origin = panelTask().first().data(TaskManager::AbstractTasksModel::Geometry).toRect().topLeft();
|
|
const QRect button(origin + QPoint(120, 0), QSize(180, 40));
|
|
QQuickItem delegate(panel.contentItem());
|
|
delegate.setPosition(QPointF(120, 0));
|
|
delegate.setSize(QSizeF(180, 40));
|
|
model.requestPublishDelegateGeometry(index, button, &delegate);
|
|
QTest::qWait(100);
|
|
|
|
auto bus = QDBusConnection::sessionBus();
|
|
const QString service = QStringLiteral("se.ajpanton.plasma-task-group-shortcuts");
|
|
QVERIFY(bus.registerService(service));
|
|
{
|
|
TaskbarGeometry geometry;
|
|
QSignalSpy results(&geometry, &TaskbarGeometry::received);
|
|
geometry.request(uuid);
|
|
QTRY_COMPARE(results.count(), 1);
|
|
QCOMPARE(results.first().first().toRectF(), QRectF(button));
|
|
}
|
|
QVERIFY(bus.unregisterService(service));
|
|
}
|
|
|
|
void loadsWithoutTakingFocus()
|
|
{
|
|
QTest::failOnWarning(QRegularExpression(QStringLiteral(".*Failed to create .*popup.*")));
|
|
QQmlEngine engine;
|
|
QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/Preview.qml")));
|
|
std::unique_ptr<QObject> object(component.create());
|
|
QVERIFY2(object, qPrintable(component.errorString()));
|
|
auto *window = qobject_cast<QQuickWindow *>(object.get());
|
|
QVERIFY(window);
|
|
QVERIFY(!window->isVisible());
|
|
QCOMPARE(window->type(), Qt::Tool);
|
|
QVERIFY(!window->transientParent());
|
|
QVERIFY(window->flags().testFlag(Qt::FramelessWindowHint));
|
|
QVERIFY(window->flags().testFlag(Qt::WindowDoesNotAcceptFocus));
|
|
QVERIFY(window->flags().testFlag(Qt::WindowTransparentForInput));
|
|
window->show();
|
|
QTRY_VERIFY(window->isExposed());
|
|
// Wayland can reject a window with an asynchronously delivered close.
|
|
QTest::qWait(100);
|
|
QVERIFY(window->isVisible());
|
|
QVERIFY(window->isExposed());
|
|
QTRY_VERIFY(window->width() > 0);
|
|
QTRY_VERIFY(window->height() > 0);
|
|
QVERIFY(window->flags().testFlag(Qt::WindowDoesNotAcceptFocus));
|
|
window->setProperty("windowTitle", QStringLiteral("Test window"));
|
|
window->setProperty("position", 2);
|
|
window->setProperty("count", 3);
|
|
QCOMPARE(window->property("windowTitle").toString(), QStringLiteral("Test window"));
|
|
window->hide();
|
|
}
|
|
|
|
void preservesFocusOnWayland()
|
|
{
|
|
if (QGuiApplication::platformName() != QLatin1String("wayland")) {
|
|
QSKIP("Requires a Wayland compositor");
|
|
}
|
|
QQuickWindow original;
|
|
original.resize(400, 300);
|
|
original.show();
|
|
QTRY_VERIFY(original.isActive());
|
|
|
|
QQmlEngine engine;
|
|
QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/Preview.qml")));
|
|
std::unique_ptr<QObject> object(component.create());
|
|
QVERIFY2(object, qPrintable(component.errorString()));
|
|
auto *preview = qobject_cast<QQuickWindow *>(object.get());
|
|
QVERIFY(preview);
|
|
preview->show();
|
|
QTRY_VERIFY(preview->isExposed());
|
|
QTest::qWait(100);
|
|
QVERIFY(preview->isVisible());
|
|
QVERIFY(!preview->isActive());
|
|
QVERIFY(original.isActive());
|
|
preview->hide();
|
|
QTest::qWait(100);
|
|
QVERIFY(original.isActive());
|
|
}
|
|
};
|
|
|
|
QTEST_MAIN(PreviewTest)
|
|
#include "test-preview.moc"
|