From 5debfb683283141f80f6930b33197263f7157eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 16 Oct 2014 14:59:01 +0200 Subject: [PATCH] Add support for opaque and input region to Surface Implemented on both Client and Server side. --- .../autotests/client/test_wayland_surface.cpp | 119 ++++++++++++++++++ src/wayland/surface_interface.cpp | 42 +++++-- src/wayland/surface_interface.h | 1 + src/wayland/surface_interface_p.h | 5 + 4 files changed, 157 insertions(+), 10 deletions(-) diff --git a/src/wayland/autotests/client/test_wayland_surface.cpp b/src/wayland/autotests/client/test_wayland_surface.cpp index 2be1b99c4b..be6986909b 100644 --- a/src/wayland/autotests/client/test_wayland_surface.cpp +++ b/src/wayland/autotests/client/test_wayland_surface.cpp @@ -24,6 +24,7 @@ License along with this library. If not, see . #include "../../src/client/compositor.h" #include "../../src/client/connection_thread.h" #include "../../src/client/surface.h" +#include "../../src/client/region.h" #include "../../src/client/registry.h" #include "../../src/client/shm_pool.h" #include "../../src/server/buffer_interface.h" @@ -46,6 +47,8 @@ private Q_SLOTS: void testDamage(); void testFrameCallback(); void testAttachBuffer(); + void testOpaque(); + void testInput(); void testDestroy(); private: @@ -344,6 +347,122 @@ void TestWaylandSurface::testAttachBuffer() buffer->unref(); } +void TestWaylandSurface::testOpaque() +{ + using namespace KWayland::Client; + using namespace KWayland::Server; + QSignalSpy serverSurfaceCreated(m_compositorInterface, SIGNAL(surfaceCreated(KWayland::Server::SurfaceInterface*))); + QVERIFY(serverSurfaceCreated.isValid()); + Surface *s = m_compositor->createSurface(); + QVERIFY(serverSurfaceCreated.wait()); + SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value(); + QVERIFY(serverSurface); + QSignalSpy opaqueRegionChangedSpy(serverSurface, SIGNAL(opaqueChanged(QRegion))); + QVERIFY(opaqueRegionChangedSpy.isValid()); + + // by default there should be an empty opaque region + QCOMPARE(serverSurface->opaque(), QRegion()); + + // let's install an opaque region + s->setOpaqueRegion(m_compositor->createRegion(QRegion(0, 10, 20, 30)).get()); + // the region should only be applied after the surface got commited + wl_display_flush(m_connection->display()); + QCoreApplication::processEvents(); + QCOMPARE(serverSurface->opaque(), QRegion()); + QCOMPARE(opaqueRegionChangedSpy.count(), 0); + + // so let's commit to get the new region + s->commit(Surface::CommitFlag::None); + QVERIFY(opaqueRegionChangedSpy.wait()); + QCOMPARE(opaqueRegionChangedSpy.count(), 1); + QCOMPARE(opaqueRegionChangedSpy.last().first().value(), QRegion(0, 10, 20, 30)); + QCOMPARE(serverSurface->opaque(), QRegion(0, 10, 20, 30)); + + // committing without setting a new region shouldn't change + s->commit(Surface::CommitFlag::None); + wl_display_flush(m_connection->display()); + QCoreApplication::processEvents(); + QCOMPARE(opaqueRegionChangedSpy.count(), 1); + QCOMPARE(serverSurface->opaque(), QRegion(0, 10, 20, 30)); + + // let's change the opaque region + s->setOpaqueRegion(m_compositor->createRegion(QRegion(10, 20, 30, 40)).get()); + s->commit(Surface::CommitFlag::None); + QVERIFY(opaqueRegionChangedSpy.wait()); + QCOMPARE(opaqueRegionChangedSpy.count(), 2); + QCOMPARE(opaqueRegionChangedSpy.last().first().value(), QRegion(10, 20, 30, 40)); + QCOMPARE(serverSurface->opaque(), QRegion(10, 20, 30, 40)); + + // and let's go back to an empty region + s->setOpaqueRegion(); + s->commit(Surface::CommitFlag::None); + QVERIFY(opaqueRegionChangedSpy.wait()); + QCOMPARE(opaqueRegionChangedSpy.count(), 3); + QCOMPARE(opaqueRegionChangedSpy.last().first().value(), QRegion()); + QCOMPARE(serverSurface->opaque(), QRegion()); +} + +void TestWaylandSurface::testInput() +{ + using namespace KWayland::Client; + using namespace KWayland::Server; + QSignalSpy serverSurfaceCreated(m_compositorInterface, SIGNAL(surfaceCreated(KWayland::Server::SurfaceInterface*))); + QVERIFY(serverSurfaceCreated.isValid()); + Surface *s = m_compositor->createSurface(); + QVERIFY(serverSurfaceCreated.wait()); + SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value(); + QVERIFY(serverSurface); + QSignalSpy inputRegionChangedSpy(serverSurface, SIGNAL(inputChanged(QRegion))); + QVERIFY(inputRegionChangedSpy.isValid()); + + // by default there should be an empty == infinite input region + QCOMPARE(serverSurface->input(), QRegion()); + QCOMPARE(serverSurface->inputIsInfitine(), true); + + // let's install an input region + s->setInputRegion(m_compositor->createRegion(QRegion(0, 10, 20, 30)).get()); + // the region should only be applied after the surface got commited + wl_display_flush(m_connection->display()); + QCoreApplication::processEvents(); + QCOMPARE(serverSurface->input(), QRegion()); + QCOMPARE(serverSurface->inputIsInfitine(), true); + QCOMPARE(inputRegionChangedSpy.count(), 0); + + // so let's commit to get the new region + s->commit(Surface::CommitFlag::None); + QVERIFY(inputRegionChangedSpy.wait()); + QCOMPARE(inputRegionChangedSpy.count(), 1); + QCOMPARE(inputRegionChangedSpy.last().first().value(), QRegion(0, 10, 20, 30)); + QCOMPARE(serverSurface->input(), QRegion(0, 10, 20, 30)); + QCOMPARE(serverSurface->inputIsInfitine(), false); + + // committing without setting a new region shouldn't change + s->commit(Surface::CommitFlag::None); + wl_display_flush(m_connection->display()); + QCoreApplication::processEvents(); + QCOMPARE(inputRegionChangedSpy.count(), 1); + QCOMPARE(serverSurface->input(), QRegion(0, 10, 20, 30)); + QCOMPARE(serverSurface->inputIsInfitine(), false); + + // let's change the input region + s->setInputRegion(m_compositor->createRegion(QRegion(10, 20, 30, 40)).get()); + s->commit(Surface::CommitFlag::None); + QVERIFY(inputRegionChangedSpy.wait()); + QCOMPARE(inputRegionChangedSpy.count(), 2); + QCOMPARE(inputRegionChangedSpy.last().first().value(), QRegion(10, 20, 30, 40)); + QCOMPARE(serverSurface->input(), QRegion(10, 20, 30, 40)); + QCOMPARE(serverSurface->inputIsInfitine(), false); + + // and let's go back to an empty region + s->setInputRegion(); + s->commit(Surface::CommitFlag::None); + QVERIFY(inputRegionChangedSpy.wait()); + QCOMPARE(inputRegionChangedSpy.count(), 3); + QCOMPARE(inputRegionChangedSpy.last().first().value(), QRegion()); + QCOMPARE(serverSurface->input(), QRegion()); + QCOMPARE(serverSurface->inputIsInfitine(), true); +} + void TestWaylandSurface::testDestroy() { using namespace KWayland::Client; diff --git a/src/wayland/surface_interface.cpp b/src/wayland/surface_interface.cpp index 79a74e1073..6914da2ece 100644 --- a/src/wayland/surface_interface.cpp +++ b/src/wayland/surface_interface.cpp @@ -21,6 +21,7 @@ License along with this library. If not, see . #include "surface_interface_p.h" #include "buffer_interface.h" #include "compositor_interface.h" +#include "region_interface.h" #include "subcompositor_interface.h" #include "subsurface_interface_p.h" // Wayland @@ -217,8 +218,8 @@ void SurfaceInterface::Private::commit() for (wl_resource *c : current.callbacks) { wl_resource_destroy(c); } - const bool opaqueRegionChanged = current.opaque != pending.opaque; - const bool inputRegionChanged = current.input != pending.input; + const bool opaqueRegionChanged = pending.opaqueIsSet; + const bool inputRegionChanged = pending.inputIsSet; const bool scaleFactorChanged = current.scale != pending.scale; const bool transformFactorChanged = current.transform != pending.transform; if (current.buffer) { @@ -231,6 +232,9 @@ void SurfaceInterface::Private::commit() current = pending; pending = State{}; pending.children = current.children; + pending.input = current.input; + pending.inputIsInfinite = current.inputIsInfinite; + pending.opaque = current.opaque; // commit all subSurfaces to apply position changes for (auto it = current.children.constBegin(); it != current.children.constEnd(); ++it) { if (!(*it)) { @@ -325,18 +329,31 @@ void SurfaceInterface::Private::frameCallaback(wl_client *client, wl_resource *r void SurfaceInterface::Private::opaqueRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region) { - Q_UNUSED(client) - Q_UNUSED(resource) - Q_UNUSED(region) - // TODO: implement me + auto s = cast(resource); + Q_ASSERT(client == s->client); + auto r = RegionInterface::get(region); + s->setOpaque(r ? r->region() : QRegion()); +} + +void SurfaceInterface::Private::setOpaque(const QRegion ®ion) +{ + pending.opaqueIsSet = true; + pending.opaque = region; } void SurfaceInterface::Private::inputRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region) { - Q_UNUSED(client) - Q_UNUSED(resource) - Q_UNUSED(region) - // TODO: implement me + auto s = cast(resource); + Q_ASSERT(client == s->client); + auto r = RegionInterface::get(region); + s->setInput(r ? r->region() : QRegion(), !r); +} + +void SurfaceInterface::Private::setInput(const QRegion ®ion, bool isInfinite) +{ + pending.inputIsSet = true; + pending.inputIsInfinite = isInfinite; + pending.input = region; } void SurfaceInterface::Private::commitCallback(wl_client *client, wl_resource *resource) @@ -382,6 +399,11 @@ QRegion SurfaceInterface::input() const return d->current.input; } +bool SurfaceInterface::inputIsInfitine() const +{ + return d->current.inputIsInfinite; +} + qint32 SurfaceInterface::scale() const { return d->current.scale; diff --git a/src/wayland/surface_interface.h b/src/wayland/surface_interface.h index 92f0629615..92aa693e88 100644 --- a/src/wayland/surface_interface.h +++ b/src/wayland/surface_interface.h @@ -57,6 +57,7 @@ public: QRegion damage() const; QRegion opaque() const; QRegion input() const; + bool inputIsInfitine() const; qint32 scale() const; OutputInterface::Transform transform() const; BufferInterface *buffer(); diff --git a/src/wayland/surface_interface_p.h b/src/wayland/surface_interface_p.h index 530cd17aba..d5ee5a9238 100644 --- a/src/wayland/surface_interface_p.h +++ b/src/wayland/surface_interface_p.h @@ -36,6 +36,9 @@ public: QRegion damage = QRegion(); QRegion opaque = QRegion(); QRegion input = QRegion(); + bool inputIsSet = false; + bool opaqueIsSet = false; + bool inputIsInfinite = true; qint32 scale = 1; OutputInterface::Transform transform = OutputInterface::Transform::Normal; QList callbacks = QList(); @@ -71,6 +74,8 @@ private: void setTransform(OutputInterface::Transform transform); void addFrameCallback(uint32_t callback); void attachBuffer(wl_resource *buffer, const QPoint &offset); + void setOpaque(const QRegion ®ion); + void setInput(const QRegion ®ion, bool isInfinite); static Private *cast(wl_resource *r);