Commit 4b9ee54d authored by Marco Martin's avatar Marco Martin
Browse files

Interface for a Slide effect

a kwayland interface plus autotests for
the slide KWin effect, marks a window the direction
it wants to slide from and the offset from the screen edge
parent 0676d539
......@@ -20,6 +20,7 @@ set(SERVER_LIB_SRCS
region_interface.cpp
resource.cpp
seat_interface.cpp
slide_interface.cpp
shadow_interface.cpp
blur_interface.cpp
contrast_interface.cpp
......@@ -69,6 +70,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
BASENAME contrast
)
ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
PROTOCOL ${KWAYLAND_SOURCE_DIR}/src/client/protocols/slide.xml
BASENAME slide
)
add_library(KF5WaylandServer ${SERVER_LIB_SRCS})
generate_export_header(KF5WaylandServer
BASE_NAME
......
......@@ -157,6 +157,17 @@ target_link_libraries( testContrast Qt5::Test Qt5::Gui KF5::WaylandClient KF5::W
add_test(kwayland-testContrast testContrast)
ecm_mark_as_test(testContrast)
########################################################
# Test Slide
########################################################
set( testSlide_SRCS
test_wayland_slide.cpp
)
add_executable(testSlide ${testSlide_SRCS})
target_link_libraries( testSlide Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client)
add_test(kwayland-testSlide testSlide)
ecm_mark_as_test(testSlide)
########################################################
# Test DataSource
########################################################
......
......@@ -36,6 +36,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "../../src/server/shell_interface.h"
#include "../../src/server/blur_interface.h"
#include "../../src/server/contrast_interface.h"
#include "../../src/server/slide_interface.h"
#include "../../src/server/subcompositor_interface.h"
// Wayland
#include <wayland-client-protocol.h>
......@@ -59,6 +60,7 @@ private Q_SLOTS:
void testBindDataDeviceManager();
void testBindBlurManager();
void testBindContrastManager();
void testBindSlideManager();
void testGlobalSync();
void testGlobalSyncThreaded();
void testRemoval();
......@@ -109,6 +111,7 @@ void TestWaylandRegistry::init()
m_dataDeviceManager->create();
m_display->createBlurManager(this)->create();
m_display->createContrastManager(this)->create();
m_display->createSlideManager(this)->create();
}
void TestWaylandRegistry::cleanup()
......@@ -221,6 +224,11 @@ void TestWaylandRegistry::testBindContrastManager()
TEST_BIND(KWayland::Client::Registry::Interface::Contrast, SIGNAL(contrastAnnounced(quint32,quint32)), bindContrastManager, free)
}
void TestWaylandRegistry::testBindSlideManager()
{
TEST_BIND(KWayland::Client::Registry::Interface::Slide, SIGNAL(slideAnnounced(quint32,quint32)), bindSlideManager, free)
}
#undef TEST_BIND
void TestWaylandRegistry::testRemoval()
......
/********************************************************************
Copyright 2014 Martin Gräßlin <mgraesslin@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/slide.h"
#include "../../src/server/display.h"
#include "../../src/server/compositor_interface.h"
#include "../../src/server/region_interface.h"
#include "../../src/server/slide_interface.h"
class TestSlide : public QObject
{
Q_OBJECT
public:
explicit TestSlide(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::SlideManagerInterface *m_slideManagerInterface;
KWayland::Client::ConnectionThread *m_connection;
KWayland::Client::Compositor *m_compositor;
KWayland::Client::SlideManager *m_slideManager;
KWayland::Client::EventQueue *m_queue;
QThread *m_thread;
KWayland::Client::Registry m_registry;
};
static const QString s_socketName = QStringLiteral("kwayland-test-wayland-slide-0");
TestSlide::TestSlide(QObject *parent)
: QObject(parent)
, m_display(nullptr)
, m_compositorInterface(nullptr)
, m_connection(nullptr)
, m_compositor(nullptr)
, m_queue(nullptr)
, m_thread(nullptr)
{
}
void TestSlide::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 slideSpy(&m_registry, SIGNAL(slideAnnounced(quint32,quint32)));
QVERIFY(slideSpy.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_slideManagerInterface = m_display->createSlideManager(m_display);
m_slideManagerInterface->create();
QVERIFY(m_slideManagerInterface->isValid());
QVERIFY(slideSpy.wait());
m_slideManager = m_registry.createSlideManager(slideSpy.first().first().value<quint32>(), slideSpy.first().last().value<quint32>(), this);
}
void TestSlide::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 TestSlide::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 slideChanged(serverSurface, SIGNAL(slideChanged()));
auto slide = m_slideManager->createSlide(surface.data(), surface.data());
slide->setLocation(KWayland::Client::Slide::Location::Top);
slide->setOffset(15);
slide->commit();
surface->commit(KWayland::Client::Surface::CommitFlag::None);
QVERIFY(slideChanged.wait());
QCOMPARE(serverSurface->slideOnShowHide()->location(), KWayland::Server::SlideInterface::Location::Top);
QCOMPARE(serverSurface->slideOnShowHide()->offset(), 15);
}
QTEST_MAIN(TestSlide)
#include "test_wayland_slide.moc"
......@@ -31,6 +31,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "shadow_interface.h"
#include "blur_interface.h"
#include "contrast_interface.h"
#include "slide_interface.h"
#include "shell_interface.h"
#include "subcompositor_interface.h"
......@@ -287,6 +288,13 @@ ContrastManagerInterface *Display::createContrastManager(QObject *parent)
return b;
}
SlideManagerInterface *Display::createSlideManager(QObject *parent)
{
auto b = new SlideManagerInterface(this, parent);
connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; });
return b;
}
void Display::createShm()
{
Q_ASSERT(d->display);
......
......@@ -48,6 +48,7 @@ class SeatInterface;
class ShadowManagerInterface;
class BlurManagerInterface;
class ContrastManagerInterface;
class SlideManagerInterface;
class ShellInterface;
class SubCompositorInterface;
......@@ -135,6 +136,7 @@ public:
ShadowManagerInterface *createShadowManager(QObject *parent = nullptr);
BlurManagerInterface *createBlurManager(QObject *parent = nullptr);
ContrastManagerInterface *createContrastManager(QObject *parent = nullptr);
SlideManagerInterface *createSlideManager(QObject *parent = nullptr);
/**
* Gets the ClientConnection for the given @p client.
......
/****************************************************************************
Copyright 2015 Marco Martin <notmart@gmail.com>
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/>.
****************************************************************************/
#include "slide_interface.h"
#include "display.h"
#include "global_p.h"
#include "surface_interface.h"
#include "resource_p.h"
#include "surface_interface_p.h"
#include <wayland-server.h>
#include <wayland-slide-server-protocol.h>
namespace KWayland
{
namespace Server
{
class SlideManagerInterface::Private : public Global::Private
{
public:
Private(SlideManagerInterface *q, Display *d);
private:
void bind(wl_client *client, uint32_t version, uint32_t id) override;
void createSlide(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface);
static void unbind(wl_resource *resource);
static Private *cast(wl_resource *r) {
return reinterpret_cast<Private*>(wl_resource_get_user_data(r));
}
static void createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * surface);
static void unsetCallback(wl_client *client, wl_resource *resource, wl_resource * surface);
SlideManagerInterface *q;
static const struct org_kde_kwin_slide_manager_interface s_interface;
//initializing here doesn't link
static const quint32 s_version;
};
const quint32 SlideManagerInterface::Private::s_version = 1;
#ifndef DOXYGEN_SHOULD_SKIP_THIS
const struct org_kde_kwin_slide_manager_interface SlideManagerInterface::Private::s_interface = {
createCallback,
unsetCallback
};
#endif
void SlideManagerInterface::Private::createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * surface)
{
cast(resource)->createSlide(client, resource, id, surface);
}
void SlideManagerInterface::Private::createSlide(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * surface)
{
SurfaceInterface *s = SurfaceInterface::get(surface);
if (!s) {
return;
}
SlideInterface *slide = new SlideInterface(q, resource);
slide->create(display->getConnection(client), wl_resource_get_version(resource), id);
if (!slide->resource()) {
wl_resource_post_no_memory(resource);
delete slide;
return;
}
QObject::connect(s, &QObject::destroyed, slide,
[slide] {
if (slide->resource()) {
wl_resource_destroy(slide->resource());
delete slide;
}
}
);
s->d_func()->setSlide(QPointer<SlideInterface>(slide));
}
void SlideManagerInterface::Private::unsetCallback(wl_client *client, wl_resource *resource, wl_resource * surface)
{
// TODO: implement
}
SlideManagerInterface::Private::Private(SlideManagerInterface *q, Display *d)
: Global::Private(d, &org_kde_kwin_slide_manager_interface, s_version)
, q(q)
{
}
void SlideManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
{
auto c = display->getConnection(client);
wl_resource *resource = c->createResource(&org_kde_kwin_slide_manager_interface, qMin(version, s_version), id);
if (!resource) {
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(resource, &s_interface, this, unbind);
// TODO: should we track?
}
void SlideManagerInterface::Private::unbind(wl_resource *resource)
{
Q_UNUSED(resource)
// TODO: implement?
}
SlideManagerInterface::SlideManagerInterface(Display *display, QObject *parent)
: Global(new Private(this, display), parent)
{
}
SlideManagerInterface::~SlideManagerInterface() = default;
class SlideInterface::Private : public Resource::Private
{
public:
Private(SlideInterface *q, SlideManagerInterface *c, wl_resource *parentResource);
~Private();
SlideInterface::Location pendingLocation;
SlideInterface::Location currentLocation;
uint32_t pendingOffset;
uint32_t currentOffset;
private:
static void commitCallback(wl_client *client, wl_resource *resource);
static void setLocationCallback(wl_client *client, wl_resource *resource, uint32_t location);
static void setOffsetCallback(wl_client *client, wl_resource *resource, int32_t offset);
static void releaseCallback(wl_client *client, wl_resource *resource);
SlideInterface *q_func() {
return reinterpret_cast<SlideInterface *>(q);
}
static const struct org_kde_kwin_slide_interface s_interface;
};
#ifndef DOXYGEN_SHOULD_SKIP_THIS
const struct org_kde_kwin_slide_interface SlideInterface::Private::s_interface = {
commitCallback,
setLocationCallback,
setOffsetCallback,
releaseCallback
};
#endif
void SlideInterface::Private::commitCallback(wl_client *client, wl_resource *resource)
{
Q_UNUSED(client)
Private *p = cast<Private>(resource);
p->currentLocation = p->pendingLocation;
p->currentOffset = p->pendingOffset;
}
void SlideInterface::Private::setLocationCallback(wl_client *client, wl_resource *resource, uint32_t location)
{
Q_UNUSED(client)
Private *p = cast<Private>(resource);
p->pendingLocation = (SlideInterface::Location)location;
}
void SlideInterface::Private::setOffsetCallback(wl_client *client, wl_resource *resource, int32_t offset)
{
Private *p = cast<Private>(resource);
p->pendingOffset = offset;
}
void SlideInterface::Private::releaseCallback(wl_client *client, wl_resource *resource)
{
// TODO: implement
}
SlideInterface::Private::Private(SlideInterface *q, SlideManagerInterface *c, wl_resource *parentResource)
: Resource::Private(q, c, parentResource, &org_kde_kwin_slide_interface, &s_interface)
{
}
SlideInterface::Private::~Private()
{
if (resource) {
wl_resource_destroy(resource);
resource = nullptr;
}
}
SlideInterface::SlideInterface(SlideManagerInterface *parent, wl_resource *parentResource)
: Resource(new Private(this, parent, parentResource))
{
}
SlideInterface::~SlideInterface() = default;
SlideInterface::Location SlideInterface::location() const
{
Q_D();
return d->currentLocation;
}
qint32 SlideInterface::offset() const
{
Q_D();
return d->currentOffset;
}
SlideInterface::Private *SlideInterface::d_func() const
{
return reinterpret_cast<Private*>(d.data());
}
}
}
/****************************************************************************
Copyright 2015 Marco Martin <notmart@gmail.com>
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/>.
****************************************************************************/
#ifndef KWAYLAND_SERVER_SLIDE_H
#define KWAYLAND_SERVER_SLIDE_H
#include "global.h"
#include "resource.h"
#include <KWayland/Server/kwaylandserver_export.h>
namespace KWayland
{
namespace Server
{
class Display;
class KWAYLANDSERVER_EXPORT SlideManagerInterface : public Global
{
Q_OBJECT
public:
virtual ~SlideManagerInterface();
private:
explicit SlideManagerInterface(Display *display, QObject *parent = nullptr);
friend class Display;
class Private;
};
class KWAYLANDSERVER_EXPORT SlideInterface : public Resource
{
Q_OBJECT
public:
enum Location {
Left = 0, /** Slide from the left edge of the screen */
Top, /** Slide from the top edge of the screen */
Right, /** Slide from the bottom edge of the screen */
Bottom /** Slide from the bottom edge of the screen */
};
virtual ~SlideInterface();
/**
* @returns the location the window will be slided from
*/
Location location() const;
/**
* @returns the offset from the screen edge the window will
* be slided from
*/
qint32 offset() const;
private:
explicit SlideInterface(SlideManagerInterface *parent, wl_resource *parentResource);
friend class SlideManagerInterface;
class Private;
Private *d_func() const;
};
}
}
#endif
......@@ -136,6 +136,12 @@ void SurfaceInterface::Private::setBlur(const QPointer<BlurInterface> &blur)
pending.blurIsSet = true;
}
void SurfaceInterface::Private::setSlide(const QPointer<SlideInterface> &slide)
{
pending.slide = slide;
pending.slideIsSet = true;