Commit 1f4beb03 authored by Marco Martin's avatar Marco Martin
Browse files

Wayland protocol for background contrast

new wayland protocol used to define regions behind a window
in which the kwin background contrast effect should be applied
REVIEW:125030
parent 62ddb960
......@@ -22,6 +22,7 @@ set(SERVER_LIB_SRCS
seat_interface.cpp
shadow_interface.cpp
blur_interface.cpp
contrast_interface.cpp
shell_interface.cpp
surface_interface.cpp
subcompositor_interface.cpp
......@@ -63,6 +64,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
BASENAME blur
)
ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/contrast.xml
BASENAME contrast
)
add_library(KF5WaylandServer ${SERVER_LIB_SRCS})
generate_export_header(KF5WaylandServer
BASE_NAME
......@@ -99,6 +105,7 @@ install(TARGETS KF5WaylandServer EXPORT KF5WaylandTargets ${KF5_INSTALL_TARGETS_
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/KWayland/Server/kwaylandserver_export.h
blur_interface.h
contrast_interface.h
buffer_interface.h
clientconnection.h
compositor_interface.h
......
......@@ -146,6 +146,17 @@ target_link_libraries( testBlur Qt5::Test Qt5::Gui KF5::WaylandClient KF5::Wayla
add_test(kwayland-testBlur testBlur)
ecm_mark_as_test(testBlur)
########################################################
# Test Contrast
########################################################
set( testContrast_SRCS
test_wayland_contrast.cpp
)
add_executable(testContrast ${testContrast_SRCS})
target_link_libraries( testContrast Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer)
add_test(kwayland-testContrast testContrast)
ecm_mark_as_test(testContrast)
########################################################
# Test DataSource
########################################################
......
/********************************************************************
Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
Copyright 2015 Marco Martin <mart@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) version 3, or any
later version accepted by the membership of KDE e.V. (or its
successor approved by the membership of KDE e.V.), which shall
act as a proxy defined in Section 6 of version 3 of the license.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
// Qt
#include <QtTest/QtTest>
// KWin
#include "../../src/client/compositor.h"
#include "../../src/client/connection_thread.h"
#include "../../src/client/event_queue.h"
#include "../../src/client/region.h"
#include "../../src/client/registry.h"
#include "../../src/client/surface.h"
#include "../../src/client/contrast.h"
#include "../../src/server/display.h"
#include "../../src/server/compositor_interface.h"
#include "../../src/server/region_interface.h"
#include "../../src/server/contrast_interface.h"
#include <wayland-util.h>
class TestContrast : public QObject
{
Q_OBJECT
public:
explicit TestContrast(QObject *parent = nullptr);
private Q_SLOTS:
void init();
void cleanup();
void testCreate();
private:
KWayland::Server::Display *m_display;
KWayland::Server::CompositorInterface *m_compositorInterface;
KWayland::Server::ContrastManagerInterface *m_contrastManagerInterface;
KWayland::Client::ConnectionThread *m_connection;
KWayland::Client::Compositor *m_compositor;
KWayland::Client::ContrastManager *m_contrastManager;
KWayland::Client::EventQueue *m_queue;
QThread *m_thread;
KWayland::Client::Registry m_registry;
};
static const QString s_socketName = QStringLiteral("kwayland-test-wayland-contrast-0");
TestContrast::TestContrast(QObject *parent)
: QObject(parent)
, m_display(nullptr)
, m_compositorInterface(nullptr)
, m_connection(nullptr)
, m_compositor(nullptr)
, m_queue(nullptr)
, m_thread(nullptr)
{
}
void TestContrast::init()
{
using namespace KWayland::Server;
delete m_display;
m_display = new Display(this);
m_display->setSocketName(s_socketName);
m_display->start();
QVERIFY(m_display->isRunning());
// setup connection
m_connection = new KWayland::Client::ConnectionThread;
QSignalSpy connectedSpy(m_connection, SIGNAL(connected()));
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 KWayland::Client::EventQueue(this);
QVERIFY(!m_queue->isValid());
m_queue->setup(m_connection);
QVERIFY(m_queue->isValid());
QSignalSpy compositorSpy(&m_registry, SIGNAL(compositorAnnounced(quint32,quint32)));
QVERIFY(compositorSpy.isValid());
QSignalSpy contrastSpy(&m_registry, SIGNAL(contrastAnnounced(quint32,quint32)));
QVERIFY(contrastSpy.isValid());
QVERIFY(!m_registry.eventQueue());
m_registry.setEventQueue(m_queue);
QCOMPARE(m_registry.eventQueue(), m_queue);
m_registry.create(m_connection->display());
QVERIFY(m_registry.isValid());
m_registry.setup();
m_compositorInterface = m_display->createCompositor(m_display);
m_compositorInterface->create();
QVERIFY(m_compositorInterface->isValid());
QVERIFY(compositorSpy.wait());
m_compositor = m_registry.createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
m_contrastManagerInterface = m_display->createContrastManager(m_display);
m_contrastManagerInterface->create();
QVERIFY(m_contrastManagerInterface->isValid());
QVERIFY(contrastSpy.wait());
m_contrastManager = m_registry.createContrastManager(contrastSpy.first().first().value<quint32>(), contrastSpy.first().last().value<quint32>(), this);
}
void TestContrast::cleanup()
{
if (m_compositor) {
delete m_compositor;
m_compositor = nullptr;
}
if (m_queue) {
delete m_queue;
m_queue = nullptr;
}
if (m_thread) {
m_thread->quit();
m_thread->wait();
delete m_thread;
m_thread = nullptr;
}
delete m_connection;
m_connection = nullptr;
delete m_display;
m_display = nullptr;
}
void TestContrast::testCreate()
{
QSignalSpy serverSurfaceCreated(m_compositorInterface, SIGNAL(surfaceCreated(KWayland::Server::SurfaceInterface*)));
QVERIFY(serverSurfaceCreated.isValid());
QScopedPointer<KWayland::Client::Surface> surface(m_compositor->createSurface());
QVERIFY(serverSurfaceCreated.wait());
auto serverSurface = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>();
QSignalSpy contrastChanged(serverSurface, SIGNAL(contrastChanged()));
auto contrast = m_contrastManager->createContrast(surface.data(), surface.data());
contrast->setRegion(m_compositor->createRegion(QRegion(0, 0, 10, 20), nullptr));
contrast->setContrast(0.2);
contrast->setIntensity(2.0);
contrast->setSaturation(1.7);
contrast->commit();
surface->commit(KWayland::Client::Surface::CommitFlag::None);
QVERIFY(contrastChanged.wait());
QCOMPARE(serverSurface->contrast()->region(), QRegion(0, 0, 10, 20));
QCOMPARE(wl_fixed_from_double(serverSurface->contrast()->contrast()), wl_fixed_from_double(0.2));
QCOMPARE(wl_fixed_from_double(serverSurface->contrast()->intensity()), wl_fixed_from_double(2.0));
QCOMPARE(wl_fixed_from_double(serverSurface->contrast()->saturation()), wl_fixed_from_double(1.7));
}
QTEST_MAIN(TestContrast)
#include "test_wayland_contrast.moc"
......@@ -35,6 +35,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "../../src/server/seat_interface.h"
#include "../../src/server/shell_interface.h"
#include "../../src/server/blur_interface.h"
#include "../../src/server/contrast_interface.h"
#include "../../src/server/subcompositor_interface.h"
// Wayland
#include <wayland-client-protocol.h>
......@@ -57,6 +58,7 @@ private Q_SLOTS:
void testBindSubCompositor();
void testBindDataDeviceManager();
void testBindBlurManager();
void testBindContrastManager();
void testGlobalSync();
void testGlobalSyncThreaded();
void testRemoval();
......@@ -106,6 +108,7 @@ void TestWaylandRegistry::init()
m_dataDeviceManager = m_display->createDataDeviceManager();
m_dataDeviceManager->create();
m_display->createBlurManager(this)->create();
m_display->createContrastManager(this)->create();
}
void TestWaylandRegistry::cleanup()
......@@ -213,6 +216,11 @@ void TestWaylandRegistry::testBindBlurManager()
TEST_BIND(KWayland::Client::Registry::Interface::Blur, SIGNAL(blurAnnounced(quint32,quint32)), bindBlurManager, free)
}
void TestWaylandRegistry::testBindContrastManager()
{
TEST_BIND(KWayland::Client::Registry::Interface::Contrast, SIGNAL(contrastAnnounced(quint32,quint32)), bindContrastManager, free)
}
#undef TEST_BIND
void TestWaylandRegistry::testRemoval()
......
......@@ -30,6 +30,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "seat_interface.h"
#include "shadow_interface.h"
#include "blur_interface.h"
#include "contrast_interface.h"
#include "shell_interface.h"
#include "subcompositor_interface.h"
......@@ -279,6 +280,13 @@ BlurManagerInterface *Display::createBlurManager(QObject *parent)
return b;
}
ContrastManagerInterface *Display::createContrastManager(QObject *parent)
{
auto b = new ContrastManagerInterface(this, parent);
connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; });
return b;
}
void Display::createShm()
{
Q_ASSERT(d->display);
......
......@@ -47,6 +47,7 @@ class QtSurfaceExtensionInterface;
class SeatInterface;
class ShadowManagerInterface;
class BlurManagerInterface;
class ContrastManagerInterface;
class ShellInterface;
class SubCompositorInterface;
......@@ -128,6 +129,7 @@ public:
FakeInputInterface *createFakeInput(QObject *parent = nullptr);
ShadowManagerInterface *createShadowManager(QObject *parent = nullptr);
BlurManagerInterface *createBlurManager(QObject *parent = nullptr);
ContrastManagerInterface *createContrastManager(QObject *parent = nullptr);
/**
* Gets the ClientConnection for the given @p client.
......
......@@ -136,6 +136,12 @@ void SurfaceInterface::Private::setBlur(const QPointer<BlurInterface> &blur)
pending.blurIsSet = true;
}
void SurfaceInterface::Private::setContrast(const QPointer<ContrastInterface> &contrast)
{
pending.contrast = contrast;
pending.contrastIsSet = true;
}
const struct wl_surface_interface SurfaceInterface::Private::s_interface = {
destroyCallback,
attachCallback,
......@@ -193,6 +199,7 @@ void SurfaceInterface::Private::commit()
const bool transformFactorChanged = current.transform != pending.transform;
const bool shadowChanged = pending.shadowIsSet;
const bool blurChanged = pending.blurIsSet;
const bool contrastChanged = pending.contrastIsSet;
bool sizeChanged = false;
auto buffer = current.buffer;
if (bufferChanged) {
......@@ -218,6 +225,10 @@ void SurfaceInterface::Private::commit()
if (blurChanged) {
blur = pending.blur;
}
auto contrast = current.contrast;
if (contrastChanged) {
contrast = pending.contrast;
}
QList<wl_resource*> callbacks = current.callbacks;
callbacks.append(pending.callbacks);
// copy values
......@@ -226,6 +237,7 @@ void SurfaceInterface::Private::commit()
current.callbacks = callbacks;
current.shadow = shadow;
current.blur = blur;
current.contrast = contrast;
pending = State{};
pending.children = current.children;
pending.input = current.input;
......@@ -270,6 +282,9 @@ void SurfaceInterface::Private::commit()
if (blurChanged) {
emit q->blurChanged();
}
if (contrastChanged) {
emit q->contrastChanged();
}
}
void SurfaceInterface::Private::damage(const QRect &rect)
......@@ -501,6 +516,12 @@ QPointer< BlurInterface > SurfaceInterface::blur() const
return d->current.blur;
}
QPointer< ContrastInterface > SurfaceInterface::contrast() const
{
Q_D();
return d->current.contrast;
}
SurfaceInterface::Private *SurfaceInterface::d_func() const
{
return reinterpret_cast<Private*>(d.data());
......
......@@ -36,6 +36,8 @@ namespace Server
class BlurManagerInterface;
class BlurInterface;
class BufferInterface;
class ContrastInterface;
class ContrastManagerInterface;
class CompositorInterface;
class ShadowManagerInterface;
class ShadowInterface;
......@@ -90,6 +92,12 @@ public:
**/
QPointer<BlurInterface> blur() const;
/**
* @returns The Contrast for this Surface.
* @since 5.5
**/
QPointer<ContrastInterface> contrast() const;
static SurfaceInterface *get(wl_resource *native);
/**
* @returns The SurfaceInterface with given @p id for @p client, if it exists, otherwise @c nullptr.
......@@ -119,12 +127,17 @@ Q_SIGNALS:
* @since 5.5
**/
void blurChanged();
/**
* @since 5.5
**/
void contrastChanged();
private:
friend class CompositorInterface;
friend class SubSurfaceInterface;
friend class ShadowManagerInterface;
friend class BlurManagerInterface;
friend class ContrastManagerInterface;
explicit SurfaceInterface(CompositorInterface *parent, wl_resource *parentResource);
class Private;
......
......@@ -42,6 +42,7 @@ public:
bool bufferIsSet = false;
bool shadowIsSet = false;
bool blurIsSet = false;
bool contrastIsSet = false;
bool inputIsInfinite = true;
qint32 scale = 1;
OutputInterface::Transform transform = OutputInterface::Transform::Normal;
......@@ -52,6 +53,7 @@ public:
QList<QPointer<SubSurfaceInterface>> children;
QPointer<ShadowInterface> shadow;
QPointer<BlurInterface> blur;
QPointer<ContrastInterface> contrast;
};
Private(SurfaceInterface *q, CompositorInterface *c, wl_resource *parentResource);
~Private();
......@@ -64,6 +66,7 @@ public:
bool lowerChild(QPointer<SubSurfaceInterface> subsurface, SurfaceInterface *sibling);
void setShadow(const QPointer<ShadowInterface> &shadow);
void setBlur(const QPointer<BlurInterface> &blur);
void setContrast(const QPointer<ContrastInterface> &contrast);
State current;
State pending;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment