diff --git a/autotests/client/test_wayland_surface.cpp b/autotests/client/test_wayland_surface.cpp --- a/autotests/client/test_wayland_surface.cpp +++ b/autotests/client/test_wayland_surface.cpp @@ -51,6 +51,7 @@ void testMultipleSurfaces(); void testOpaque(); void testInput(); + void testScale(); void testDestroy(); private: @@ -631,6 +632,49 @@ QCOMPARE(serverSurface->inputIsInfinite(), true); } +void TestWaylandSurface::testScale() +{ + // this test verifies that updating the scale factor is correctly passed to the Wayland server + using namespace KWayland::Client; + using namespace KWayland::Server; + // create surface + QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); + QVERIFY(serverSurfaceCreated.isValid()); + QScopedPointer s(m_compositor->createSurface()); + QCOMPARE(s->scale(), 1); + QVERIFY(serverSurfaceCreated.wait()); + SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value(); + QVERIFY(serverSurface); + QCOMPARE(serverSurface->scale(), 1); + + // let's change the scale factor + QSignalSpy scaleChangedSpy(serverSurface, &SurfaceInterface::scaleChanged); + QVERIFY(scaleChangedSpy.isValid()); + s->setScale(2); + QCOMPARE(s->scale(), 2); + // needs a commit + QVERIFY(!scaleChangedSpy.wait(100)); + s->commit(Surface::CommitFlag::None); + QVERIFY(scaleChangedSpy.wait()); + QCOMPARE(scaleChangedSpy.count(), 1); + QCOMPARE(scaleChangedSpy.first().first().toInt(), 2); + QCOMPARE(serverSurface->scale(), 2); + + // let's try changing to same factor, should not emit changed on server + s->setScale(2); + s->commit(Surface::CommitFlag::None); + QVERIFY(!scaleChangedSpy.wait(100)); + + // but changing to a different value should still work + s->setScale(4); + s->commit(Surface::CommitFlag::None); + QVERIFY(scaleChangedSpy.wait()); + QCOMPARE(scaleChangedSpy.count(), 2); + QCOMPARE(scaleChangedSpy.first().first().toInt(), 2); + QCOMPARE(scaleChangedSpy.last().first().toInt(), 4); + QCOMPARE(serverSurface->scale(), 4); +} + void TestWaylandSurface::testDestroy() { using namespace KWayland::Client; diff --git a/src/client/surface.h b/src/client/surface.h --- a/src/client/surface.h +++ b/src/client/surface.h @@ -203,6 +203,31 @@ void setSize(const QSize &size); QSize size() const; + /** + * The purpose of this method is to allow to supply higher resolution buffer data for use + * on high resolution outputs. It's intended that the same buffer scale as the scale of the + * output that the surface is displayed on is used. + * This means the compositor can avoid scaling when rendering the surface on that output. + * + * Note that if @p scale is larger than 1 you have to attach a buffer that is larger + * (by a factor of scale in each dimension) than the desired surface size. + * + * The default scale factor is 1. + * + * The state is only applied with the next commit. + * + * @see scale + * @see commit + * @since 5.7 + **/ + void setScale(qint32 scale); + /** + * @returns The current scale factor, if not explicitly set it's @c 1. + * @see setScale + * @since 5.7 + **/ + qint32 scale() const; + operator wl_surface*(); operator wl_surface*() const; diff --git a/src/client/surface.cpp b/src/client/surface.cpp --- a/src/client/surface.cpp +++ b/src/client/surface.cpp @@ -45,6 +45,7 @@ bool frameCallbackInstalled = false; QSize size; bool foreign = false; + qint32 scale = 1; static QList s_surfaces; private: @@ -281,5 +282,16 @@ return wl_proxy_get_id(reinterpret_cast(s)); } +qint32 Surface::scale() const +{ + return d->scale; +} + +void Surface::setScale(qint32 scale) +{ + d->scale = scale; + wl_surface_set_buffer_scale(d->surface, scale); +} + } }