summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDavid Edmundson <davidedmundson@kde.org>2022-03-23 15:35:50 +0000
committerDavid Edmundson <davidedmundson@kde.org>2022-12-07 20:36:40 +0000
commit23d3fc712cdf7fc0a4ff837082de9ba773e8605c (patch)
tree5b4866d8c3c0b7eb524a8f70050b3c2868b6ba01 /tests
parent5bae5debdf94f6bbec61f4ff50ecbf3c1231e0e3 (diff)
downloadqtwayland-23d3fc712cdf7fc0a4ff837082de9ba773e8605c.tar.gz
Implement fractional_scale_v1 and wp_viewport
This allows compositors to hint a non-integer scale to use on a window which we can hook to Qt's existing fractional scaling support. The viewport is used to communicate the relationship between buffer size and logical size to the compositor. It is a non-integer alternative to wl_buffer_scale Change-Id: I1a850f1bcd40e8d04e241e18a538b11f18bc671c Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: David Edmundson <davidedmundson@kde.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/client/CMakeLists.txt2
-rw-r--r--tests/auto/client/scaling/CMakeLists.txt10
-rw-r--r--tests/auto/client/scaling/tst_scaling.cpp135
-rw-r--r--tests/auto/client/shared/CMakeLists.txt6
-rw-r--r--tests/auto/client/shared/fractionalscalev1.cpp40
-rw-r--r--tests/auto/client/shared/fractionalscalev1.h39
-rw-r--r--tests/auto/client/shared/mockcompositor.cpp3
-rw-r--r--tests/auto/client/shared/mockcompositor.h4
-rw-r--r--tests/auto/client/shared/viewport.cpp58
-rw-r--r--tests/auto/client/shared/viewport.h50
10 files changed, 347 insertions, 0 deletions
diff --git a/tests/auto/client/CMakeLists.txt b/tests/auto/client/CMakeLists.txt
index 749e6b83..44cf3271 100644
--- a/tests/auto/client/CMakeLists.txt
+++ b/tests/auto/client/CMakeLists.txt
@@ -25,8 +25,10 @@ if (NOT WEBOS)
add_subdirectory(xdgdecorationv1)
add_subdirectory(xdgoutput)
add_subdirectory(xdgshell)
+ add_subdirectory(scaling)
endif()
add_subdirectory(multithreaded)
+
if(QT_FEATURE_im)
add_subdirectory(inputcontext)
endif()
diff --git a/tests/auto/client/scaling/CMakeLists.txt b/tests/auto/client/scaling/CMakeLists.txt
new file mode 100644
index 00000000..a93f0c57
--- /dev/null
+++ b/tests/auto/client/scaling/CMakeLists.txt
@@ -0,0 +1,10 @@
+#####################################################################
+## tst_scaling Test:
+#####################################################################
+
+qt_internal_add_test(tst_scaling
+ SOURCES
+ tst_scaling.cpp
+ PUBLIC_LIBRARIES
+ SharedClientTest
+)
diff --git a/tests/auto/client/scaling/tst_scaling.cpp b/tests/auto/client/scaling/tst_scaling.cpp
new file mode 100644
index 00000000..bceea92d
--- /dev/null
+++ b/tests/auto/client/scaling/tst_scaling.cpp
@@ -0,0 +1,135 @@
+// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "mockcompositor.h"
+#include <QtOpenGL/QOpenGLWindow>
+#include <QtGui/QRasterWindow>
+#include <QtGui/qpa/qplatformnativeinterface.h>
+#include <QtWaylandClient/private/wayland-wayland-client-protocol.h>
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
+
+using namespace MockCompositor;
+
+class tst_scaling : public QObject, private DefaultCompositor
+{
+ Q_OBJECT
+private slots:
+ void init();
+ void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); }
+ void scaledWindow();
+ void roundingPolicy_data();
+ void roundingPolicy();
+
+};
+
+void tst_scaling::init()
+{
+ setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1);
+}
+
+void tst_scaling::scaledWindow()
+{
+ QRasterWindow window;
+ window.resize(100, 100);
+ window.show();
+ QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
+
+ QSignalSpy configureSpy(exec([=] { return xdgSurface(); }), &XdgSurface::configureCommitted);
+ QSignalSpy surfaceCommitSpy(exec([=] { return surface(); }), &Surface::commit);
+
+ const QSize configureSize(100, 100);
+
+ exec([=] {
+ QVERIFY(fractionalScale());
+ fractionalScale()->send_preferred_scale(1.5 * 120);
+ xdgToplevel()->sendCompleteConfigure(configureSize);
+ });
+
+ QTRY_COMPARE(configureSpy.count(), 1);
+ QCOMPARE(window.devicePixelRatio(), 1.5);
+
+ exec([=] {
+ Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer;
+ QVERIFY(buffer);
+ QCOMPARE(buffer->size(), QSize(150, 150));
+ Viewport *vp = viewport();
+ QVERIFY(vp);
+ QCOMPARE(vp->m_destination, QSize(100, 100));
+ });
+
+ // resize the window
+ window.resize(200,200);
+ QCOMPARE(window.size(), QSize(200,200));
+
+ QVERIFY(surfaceCommitSpy.wait());
+ exec([=] {
+ Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer;
+ QVERIFY(buffer);
+ QCOMPARE(buffer->size(), QSize(300, 300));
+ Viewport *vp = viewport();
+ QVERIFY(vp);
+ QCOMPARE(vp->m_destination, QSize(200, 200));
+ });
+
+ // dynamic scale change
+ exec([=] {
+ QVERIFY(fractionalScale());
+ fractionalScale()->send_preferred_scale(2.5 * 120);
+ });
+ QTRY_COMPARE(window.devicePixelRatio(), 2.5);
+ QCOMPARE(window.size(), QSize(200,200));
+
+ QVERIFY(surfaceCommitSpy.wait());
+ exec([=] {
+ Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer;
+ QVERIFY(buffer);
+ QCOMPARE(buffer->size(), QSize(500, 500));
+ Viewport *vp = viewport();
+ QVERIFY(vp);
+ QCOMPARE(vp->m_destination, QSize(200, 200));
+ });
+}
+
+void tst_scaling::roundingPolicy_data()
+{
+ QTest::addColumn<QSize>("windowSize");
+ QTest::addColumn<qreal>("scale");
+ QTest::addColumn<QSize>("expectedBufferSize");
+
+ QTest::newRow("1.125 - round down") << QSize(10, 10) << 1.125 << QSize(11,11);
+ QTest::newRow("1.25 - round up") << QSize(10, 10) << 1.25 << QSize(13,13);
+ QTest::newRow("1.5 - don't round") << QSize(10, 10) << 1.5 << QSize(15,15);
+}
+
+void tst_scaling::roundingPolicy()
+{
+ QFETCH(QSize, windowSize);
+ QFETCH(qreal, scale);
+ QFETCH(QSize, expectedBufferSize);
+
+
+ QRasterWindow window;
+ window.resize(windowSize);
+ window.show();
+ QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
+
+ QSignalSpy surfaceCommitSpy(exec([=] { return surface(); }), &Surface::commit);
+
+ exec([=] {
+ QVERIFY(fractionalScale());
+ fractionalScale()->send_preferred_scale(scale * 120);
+ xdgToplevel()->sendCompleteConfigure();
+ });
+
+ QVERIFY(surfaceCommitSpy.wait());
+
+ exec([=] {
+ Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer;
+ QVERIFY(buffer);
+ QCOMPARE(buffer->size(), expectedBufferSize);
+ });
+}
+
+
+QCOMPOSITOR_TEST_MAIN(tst_scaling)
+#include "tst_scaling.moc"
diff --git a/tests/auto/client/shared/CMakeLists.txt b/tests/auto/client/shared/CMakeLists.txt
index 653927f0..8112ffb7 100644
--- a/tests/auto/client/shared/CMakeLists.txt
+++ b/tests/auto/client/shared/CMakeLists.txt
@@ -11,9 +11,11 @@ qt_manual_moc(moc_files
corecompositor.h
datadevice.h
fullscreenshellv1.h
+ fractionalscalev1.h
iviapplication.h
textinput.h
qttextinput.h
+ viewport.h
xdgoutputv1.h
xdgshell.h
)
@@ -24,12 +26,14 @@ add_library(SharedClientTest
coreprotocol.cpp coreprotocol.h
datadevice.cpp datadevice.h
fullscreenshellv1.cpp fullscreenshellv1.h
+ fractionalscalev1.cpp fractionalscalev1.h
iviapplication.cpp iviapplication.h
mockcompositor.cpp mockcompositor.h
textinput.cpp textinput.h
qttextinput.cpp qttextinput.h
xdgoutputv1.cpp xdgoutputv1.h
xdgshell.cpp xdgshell.h
+ viewport.cpp viewport.h
${moc_files}
)
@@ -41,6 +45,8 @@ qt6_generate_wayland_protocol_server_sources(SharedClientTest
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/tablet-unstable-v2.xml
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/text-input-unstable-v2.xml
${PROJECT_SOURCE_DIR}/src/extensions/qt-text-input-method-unstable-v1.xml
+ ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/fractional-scale-v1.xml
+ ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/viewporter.xml
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/wayland.xml
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-decoration-unstable-v1.xml
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-output-unstable-v1.xml
diff --git a/tests/auto/client/shared/fractionalscalev1.cpp b/tests/auto/client/shared/fractionalscalev1.cpp
new file mode 100644
index 00000000..5548c3d6
--- /dev/null
+++ b/tests/auto/client/shared/fractionalscalev1.cpp
@@ -0,0 +1,40 @@
+// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "fractionalscalev1.h"
+
+namespace MockCompositor {
+
+FractionalScaleManager::FractionalScaleManager(CoreCompositor *compositor, int version)
+ : QtWaylandServer::wp_fractional_scale_manager_v1(compositor->m_display, version)
+{
+}
+
+void FractionalScaleManager::wp_fractional_scale_manager_v1_get_fractional_scale(Resource *resource, uint32_t id, wl_resource *surface)
+{
+ auto *s = fromResource<Surface>(surface);
+ auto *scaler = new FractionalScale(s, resource->client(), id, resource->version());
+ connect(scaler, &QObject::destroyed, this, [this, scaler]() {
+ m_fractionalScales.removeOne(scaler);
+ });
+ m_fractionalScales << scaler;
+}
+
+FractionalScale::FractionalScale(Surface *surface, wl_client *client, int id, int version)
+ : QtWaylandServer::wp_fractional_scale_v1(client, id, version)
+ , m_surface(surface)
+{
+}
+
+void FractionalScale::wp_fractional_scale_v1_destroy_resource(Resource *resource)
+{
+ Q_UNUSED(resource)
+ delete this;
+}
+
+void FractionalScale::wp_fractional_scale_v1_destroy(Resource *resource)
+{
+ wl_resource_destroy(resource->handle);
+}
+
+}
diff --git a/tests/auto/client/shared/fractionalscalev1.h b/tests/auto/client/shared/fractionalscalev1.h
new file mode 100644
index 00000000..fd5483e9
--- /dev/null
+++ b/tests/auto/client/shared/fractionalscalev1.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef MOCKCOMPOSITOR_FRACTIONALSCALE_H
+#define MOCKCOMPOSITOR_FRACTIONALSCALE_H
+
+#include "coreprotocol.h"
+#include <qwayland-server-fractional-scale-v1.h>
+
+namespace MockCompositor {
+
+class FractionalScale;
+
+class FractionalScaleManager : public Global, public QtWaylandServer::wp_fractional_scale_manager_v1
+{
+ Q_OBJECT
+public:
+ explicit FractionalScaleManager(CoreCompositor *compositor, int version = 1);
+ QList<FractionalScale *> m_fractionalScales;
+
+protected:
+ void wp_fractional_scale_manager_v1_get_fractional_scale(Resource *resource, uint32_t id, wl_resource *surface) override;
+};
+
+class FractionalScale : public QObject, public QtWaylandServer::wp_fractional_scale_v1
+{
+ Q_OBJECT
+public:
+ explicit FractionalScale(Surface *surface, wl_client *client, int id, int version);
+ Surface *m_surface;
+
+protected:
+ void wp_fractional_scale_v1_destroy_resource(Resource *resource) override;
+ void wp_fractional_scale_v1_destroy(Resource *resource) override;
+};
+
+}
+
+#endif
diff --git a/tests/auto/client/shared/mockcompositor.cpp b/tests/auto/client/shared/mockcompositor.cpp
index 1266f776..71f3775a 100644
--- a/tests/auto/client/shared/mockcompositor.cpp
+++ b/tests/auto/client/shared/mockcompositor.cpp
@@ -21,6 +21,9 @@ DefaultCompositor::DefaultCompositor(CompositorType t)
add<Seat>(Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch);
add<WlShell>();
add<XdgWmBase>();
+ add<FractionalScaleManager>();
+ add<Viewporter>();
+
switch (m_type) {
case CompositorType::Default:
add<Shm>();
diff --git a/tests/auto/client/shared/mockcompositor.h b/tests/auto/client/shared/mockcompositor.h
index 3b70a430..6803a646 100644
--- a/tests/auto/client/shared/mockcompositor.h
+++ b/tests/auto/client/shared/mockcompositor.h
@@ -11,6 +11,8 @@
#include "fullscreenshellv1.h"
#include "iviapplication.h"
#include "xdgshell.h"
+#include "viewport.h"
+#include "fractionalscalev1.h"
#include <QtGui/QGuiApplication>
@@ -46,6 +48,8 @@ public:
Keyboard *keyboard() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_keyboard; }
FullScreenShellV1 *fullScreenShellV1() {return get<FullScreenShellV1>();};
IviSurface *iviSurface(int i = 0) { return get<IviApplication>()->m_iviSurfaces.value(i, nullptr); }
+ FractionalScale *fractionalScale(int i = 0) {return get<FractionalScaleManager>()->m_fractionalScales.value(i, nullptr); }
+ Viewport *viewport(int i = 0) {return get<Viewporter>()->m_viewports.value(i, nullptr); }
uint sendXdgShellPing();
void xdgPingAndWaitForPong();
diff --git a/tests/auto/client/shared/viewport.cpp b/tests/auto/client/shared/viewport.cpp
new file mode 100644
index 00000000..c1e763fe
--- /dev/null
+++ b/tests/auto/client/shared/viewport.cpp
@@ -0,0 +1,58 @@
+// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "viewport.h"
+
+namespace MockCompositor {
+
+Viewporter::Viewporter(CoreCompositor *compositor, int version)
+ : QtWaylandServer::wp_viewporter(compositor->m_display, version)
+{
+}
+
+void Viewporter::wp_viewporter_get_viewport(Resource *resource, uint32_t id, wl_resource *surface)
+{
+ auto *s = fromResource<Surface>(surface);
+ auto *viewport = new Viewport(s, resource->client(), id, resource->version());
+ connect(viewport, &QObject::destroyed, this, [this, viewport]() {
+ m_viewports.removeOne(viewport);
+ });
+ m_viewports << viewport;
+}
+
+Viewport::Viewport(Surface *surface, wl_client *client, int id, int version)
+ : QtWaylandServer::wp_viewport(client, id, version)
+ , m_surface(surface)
+{
+}
+
+void Viewport::wp_viewport_set_source(Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height)
+{
+ Q_UNUSED(resource)
+ m_source = QRectF(wl_fixed_to_double(x),
+ wl_fixed_to_double(y),
+ wl_fixed_to_double(width),
+ wl_fixed_to_double(height));
+ Q_EMIT sourceChanged();
+}
+
+void Viewport::wp_viewport_set_destination(Resource *resource, int32_t width, int32_t height)
+{
+ Q_UNUSED(resource)
+
+ m_destination = QSize(width, height);
+ Q_EMIT destinationChanged();
+}
+
+void Viewport::wp_viewport_destroy_resource(Resource *resource)
+{
+ Q_UNUSED(resource)
+ delete this;
+}
+
+void Viewport::wp_viewport_destroy(Resource *resource)
+{
+ wl_resource_destroy(resource->handle);
+}
+
+}
diff --git a/tests/auto/client/shared/viewport.h b/tests/auto/client/shared/viewport.h
new file mode 100644
index 00000000..018e28e1
--- /dev/null
+++ b/tests/auto/client/shared/viewport.h
@@ -0,0 +1,50 @@
+// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef MOCKCOMPOSITOR_VIEWPORT_H
+#define MOCKCOMPOSITOR_VIEWPORT_H
+
+#include "coreprotocol.h"
+#include <qwayland-server-viewporter.h>
+
+namespace MockCompositor {
+
+class Viewport;
+
+class Viewporter : public Global, public QtWaylandServer::wp_viewporter
+{
+ Q_OBJECT
+public:
+ explicit Viewporter(CoreCompositor *compositor, int version = 1);
+ QList<Viewport *> m_viewports;
+
+protected:
+ void wp_viewporter_get_viewport(Resource *resource, uint32_t id, wl_resource *surface) override;
+};
+
+class Viewport : public QObject, public QtWaylandServer::wp_viewport
+{
+ Q_OBJECT
+public:
+ explicit Viewport(Surface *surface, wl_client *client, int id, int version);
+
+ QRectF m_source;
+ QSize m_destination;
+
+ Surface* m_surface;
+
+Q_SIGNALS:
+ void sourceChanged();
+ void destinationChanged();
+
+protected:
+ void wp_viewport_set_source(Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) override;
+ void wp_viewport_set_destination(Resource *resource, int32_t width, int32_t height) override;
+
+ void wp_viewport_destroy_resource(Resource *resource) override;
+ void wp_viewport_destroy(Resource *resource) override;
+};
+
+}
+
+#endif