Add the activity management protocol server implementation
This commit is contained in:
parent
b822c1e63a
commit
d92fa7f140
4 changed files with 296 additions and 1 deletions
|
@ -353,6 +353,17 @@ target_link_libraries( testPlasmaVirtualDesktop Qt::Test Qt::Gui KF5::WaylandCli
|
||||||
add_test(NAME kwayland-testPlasmaVirtualDesktop COMMAND testPlasmaVirtualDesktop)
|
add_test(NAME kwayland-testPlasmaVirtualDesktop COMMAND testPlasmaVirtualDesktop)
|
||||||
ecm_mark_as_test(testPlasmaVirtualDesktop)
|
ecm_mark_as_test(testPlasmaVirtualDesktop)
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
# Test Activities
|
||||||
|
########################################################
|
||||||
|
set( testPlasmaActivities_SRCS
|
||||||
|
test_plasma_activities.cpp
|
||||||
|
)
|
||||||
|
add_executable(testPlasmaActivities ${testPlasmaActivities_SRCS})
|
||||||
|
target_link_libraries( testPlasmaActivities Qt::Test Qt::Gui KF5::WaylandClient Plasma::KWaylandServer)
|
||||||
|
add_test(NAME kwayland-testPlasmaActivities COMMAND testPlasmaActivities)
|
||||||
|
ecm_mark_as_test(testPlasmaActivities)
|
||||||
|
|
||||||
########################################################
|
########################################################
|
||||||
# Test XDG Output
|
# Test XDG Output
|
||||||
########################################################
|
########################################################
|
||||||
|
|
199
src/wayland/autotests/client/test_plasma_activities.cpp
Normal file
199
src/wayland/autotests/client/test_plasma_activities.cpp
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Kevin Ottens <kevin.ottens@enioka.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||||
|
*/
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
// KWin
|
||||||
|
#include "KWayland/Client/compositor.h"
|
||||||
|
#include "KWayland/Client/connection_thread.h"
|
||||||
|
#include "KWayland/Client/event_queue.h"
|
||||||
|
#include "KWayland/Client/region.h"
|
||||||
|
#include "KWayland/Client/registry.h"
|
||||||
|
#include "KWayland/Client/surface.h"
|
||||||
|
#include "../../src/server/display.h"
|
||||||
|
#include "../../src/server/compositor_interface.h"
|
||||||
|
#include "../../src/server/plasmawindowmanagement_interface.h"
|
||||||
|
#include "KWayland/Client/plasmawindowmanagement.h"
|
||||||
|
|
||||||
|
using namespace KWayland::Client;
|
||||||
|
|
||||||
|
class TestActivities : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit TestActivities(QObject *parent = nullptr);
|
||||||
|
private Q_SLOTS:
|
||||||
|
void init();
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
void testEnterLeaveActivity();
|
||||||
|
|
||||||
|
private:
|
||||||
|
KWaylandServer::Display *m_display;
|
||||||
|
KWaylandServer::CompositorInterface *m_compositorInterface;
|
||||||
|
KWaylandServer::PlasmaWindowManagementInterface *m_windowManagementInterface;
|
||||||
|
KWaylandServer::PlasmaWindowInterface *m_windowInterface;
|
||||||
|
|
||||||
|
KWayland::Client::ConnectionThread *m_connection;
|
||||||
|
KWayland::Client::Compositor *m_compositor;
|
||||||
|
KWayland::Client::EventQueue *m_queue;
|
||||||
|
KWayland::Client::PlasmaWindowManagement *m_windowManagement;
|
||||||
|
KWayland::Client::PlasmaWindow *m_window;
|
||||||
|
|
||||||
|
QThread *m_thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QString s_socketName = QStringLiteral("kwayland-test-wayland-activities-0");
|
||||||
|
|
||||||
|
TestActivities::TestActivities(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_display(nullptr)
|
||||||
|
, m_compositorInterface(nullptr)
|
||||||
|
, m_connection(nullptr)
|
||||||
|
, m_compositor(nullptr)
|
||||||
|
, m_queue(nullptr)
|
||||||
|
, m_thread(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestActivities::init()
|
||||||
|
{
|
||||||
|
using namespace KWaylandServer;
|
||||||
|
delete m_display;
|
||||||
|
m_display = new Display(this);
|
||||||
|
m_display->addSocketName(s_socketName);
|
||||||
|
m_display->start();
|
||||||
|
QVERIFY(m_display->isRunning());
|
||||||
|
|
||||||
|
// setup connection
|
||||||
|
m_connection = new KWayland::Client::ConnectionThread;
|
||||||
|
QSignalSpy connectedSpy(m_connection, &ConnectionThread::connected);
|
||||||
|
QVERIFY(connectedSpy.isValid());
|
||||||
|
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());
|
||||||
|
|
||||||
|
Registry registry;
|
||||||
|
QSignalSpy compositorSpy(®istry, &Registry::compositorAnnounced);
|
||||||
|
QVERIFY(compositorSpy.isValid());
|
||||||
|
|
||||||
|
QSignalSpy windowManagementSpy(®istry, &Registry::plasmaWindowManagementAnnounced);
|
||||||
|
QVERIFY(windowManagementSpy.isValid());
|
||||||
|
|
||||||
|
QVERIFY(!registry.eventQueue());
|
||||||
|
registry.setEventQueue(m_queue);
|
||||||
|
QCOMPARE(registry.eventQueue(), m_queue);
|
||||||
|
registry.create(m_connection->display());
|
||||||
|
QVERIFY(registry.isValid());
|
||||||
|
registry.setup();
|
||||||
|
|
||||||
|
m_compositorInterface = new CompositorInterface(m_display, m_display);
|
||||||
|
QVERIFY(compositorSpy.wait());
|
||||||
|
m_compositor = registry.createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
|
||||||
|
|
||||||
|
m_windowManagementInterface = new PlasmaWindowManagementInterface(m_display, m_display);
|
||||||
|
|
||||||
|
QVERIFY(windowManagementSpy.wait());
|
||||||
|
m_windowManagement = registry.createPlasmaWindowManagement(windowManagementSpy.first().first().value<quint32>(), windowManagementSpy.first().last().value<quint32>(), this);
|
||||||
|
|
||||||
|
QSignalSpy windowSpy(m_windowManagement, &PlasmaWindowManagement::windowCreated);
|
||||||
|
QVERIFY(windowSpy.isValid());
|
||||||
|
m_windowInterface = m_windowManagementInterface->createWindow(this, QUuid::createUuid());
|
||||||
|
m_windowInterface->setPid(1337);
|
||||||
|
|
||||||
|
QVERIFY(windowSpy.wait());
|
||||||
|
m_window = windowSpy.first().first().value<PlasmaWindow *>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestActivities::cleanup()
|
||||||
|
{
|
||||||
|
#define CLEANUP(variable) \
|
||||||
|
if (variable) { \
|
||||||
|
delete variable; \
|
||||||
|
variable = nullptr; \
|
||||||
|
}
|
||||||
|
CLEANUP(m_compositor)
|
||||||
|
CLEANUP(m_windowInterface)
|
||||||
|
CLEANUP(m_windowManagement)
|
||||||
|
CLEANUP(m_queue)
|
||||||
|
if (m_connection) {
|
||||||
|
m_connection->deleteLater();
|
||||||
|
m_connection = nullptr;
|
||||||
|
}
|
||||||
|
if (m_thread) {
|
||||||
|
m_thread->quit();
|
||||||
|
m_thread->wait();
|
||||||
|
delete m_thread;
|
||||||
|
m_thread = nullptr;
|
||||||
|
}
|
||||||
|
CLEANUP(m_compositorInterface)
|
||||||
|
CLEANUP(m_windowManagementInterface)
|
||||||
|
CLEANUP(m_display)
|
||||||
|
#undef CLEANUP
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestActivities::testEnterLeaveActivity()
|
||||||
|
{
|
||||||
|
QSignalSpy enterRequestedSpy(m_windowInterface, &KWaylandServer::PlasmaWindowInterface::enterPlasmaActivityRequested);
|
||||||
|
m_window->requestEnterActivity(QStringLiteral("0-1"));
|
||||||
|
enterRequestedSpy.wait();
|
||||||
|
|
||||||
|
QCOMPARE(enterRequestedSpy.takeFirst().at(0).toString(), QStringLiteral("0-1"));
|
||||||
|
|
||||||
|
QSignalSpy activityEnteredSpy(m_window, &KWayland::Client::PlasmaWindow::plasmaActivityEntered);
|
||||||
|
|
||||||
|
//agree to the request
|
||||||
|
m_windowInterface->addPlasmaActivity(QStringLiteral("0-1"));
|
||||||
|
QCOMPARE(m_windowInterface->plasmaActivities().length(), 1);
|
||||||
|
QCOMPARE(m_windowInterface->plasmaActivities().first(), QStringLiteral("0-1"));
|
||||||
|
|
||||||
|
//check if the client received the enter
|
||||||
|
activityEnteredSpy.wait();
|
||||||
|
QCOMPARE(activityEnteredSpy.takeFirst().at(0).toString(), QStringLiteral("0-1"));
|
||||||
|
QCOMPARE(m_window->plasmaActivities().length(), 1);
|
||||||
|
QCOMPARE(m_window->plasmaActivities().first(), QStringLiteral("0-1"));
|
||||||
|
|
||||||
|
//add another activity, server side
|
||||||
|
m_windowInterface->addPlasmaActivity(QStringLiteral("0-3"));
|
||||||
|
activityEnteredSpy.wait();
|
||||||
|
QCOMPARE(activityEnteredSpy.takeFirst().at(0).toString(), QStringLiteral("0-3"));
|
||||||
|
QCOMPARE(m_windowInterface->plasmaActivities().length(), 2);
|
||||||
|
QCOMPARE(m_window->plasmaActivities().length(), 2);
|
||||||
|
QCOMPARE(m_window->plasmaActivities()[1], QStringLiteral("0-3"));
|
||||||
|
|
||||||
|
|
||||||
|
//remove an activity
|
||||||
|
QSignalSpy leaveRequestedSpy(m_windowInterface, &KWaylandServer::PlasmaWindowInterface::leavePlasmaActivityRequested);
|
||||||
|
m_window->requestLeaveActivity(QStringLiteral("0-1"));
|
||||||
|
leaveRequestedSpy.wait();
|
||||||
|
|
||||||
|
QCOMPARE(leaveRequestedSpy.takeFirst().at(0).toString(), QStringLiteral("0-1"));
|
||||||
|
|
||||||
|
QSignalSpy activityLeftSpy(m_window, &KWayland::Client::PlasmaWindow::plasmaActivityLeft);
|
||||||
|
|
||||||
|
//agree to the request
|
||||||
|
m_windowInterface->removePlasmaActivity(QStringLiteral("0-1"));
|
||||||
|
QCOMPARE(m_windowInterface->plasmaActivities().length(), 1);
|
||||||
|
QCOMPARE(m_windowInterface->plasmaActivities().first(), QStringLiteral("0-3"));
|
||||||
|
|
||||||
|
//check if the client received the leave
|
||||||
|
activityLeftSpy.wait();
|
||||||
|
QCOMPARE(activityLeftSpy.takeFirst().at(0).toString(), QStringLiteral("0-1"));
|
||||||
|
QCOMPARE(m_window->plasmaActivities().length(), 1);
|
||||||
|
QCOMPARE(m_window->plasmaActivities().first(), QStringLiteral("0-3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_GUILESS_MAIN(TestActivities)
|
||||||
|
#include "test_plasma_activities.moc"
|
|
@ -23,7 +23,7 @@
|
||||||
namespace KWaylandServer
|
namespace KWaylandServer
|
||||||
{
|
{
|
||||||
|
|
||||||
static const quint32 s_version = 13;
|
static const quint32 s_version = 14;
|
||||||
|
|
||||||
class PlasmaWindowManagementInterfacePrivate : public QtWaylandServer::org_kde_plasma_window_management
|
class PlasmaWindowManagementInterfacePrivate : public QtWaylandServer::org_kde_plasma_window_management
|
||||||
{
|
{
|
||||||
|
@ -78,6 +78,7 @@ public:
|
||||||
PlasmaWindowInterface *parentWindow = nullptr;
|
PlasmaWindowInterface *parentWindow = nullptr;
|
||||||
QMetaObject::Connection parentWindowDestroyConnection;
|
QMetaObject::Connection parentWindowDestroyConnection;
|
||||||
QStringList plasmaVirtualDesktops;
|
QStringList plasmaVirtualDesktops;
|
||||||
|
QStringList plasmaActivities;
|
||||||
QRect geometry;
|
QRect geometry;
|
||||||
PlasmaWindowInterface *q;
|
PlasmaWindowInterface *q;
|
||||||
QString m_title;
|
QString m_title;
|
||||||
|
@ -105,6 +106,8 @@ protected:
|
||||||
void org_kde_plasma_window_request_enter_virtual_desktop(Resource *resource, const QString &id) override;
|
void org_kde_plasma_window_request_enter_virtual_desktop(Resource *resource, const QString &id) override;
|
||||||
void org_kde_plasma_window_request_enter_new_virtual_desktop(Resource *resource) override;
|
void org_kde_plasma_window_request_enter_new_virtual_desktop(Resource *resource) override;
|
||||||
void org_kde_plasma_window_request_leave_virtual_desktop(Resource *resource, const QString &id) override;
|
void org_kde_plasma_window_request_leave_virtual_desktop(Resource *resource, const QString &id) override;
|
||||||
|
void org_kde_plasma_window_request_enter_activity(Resource *resource, const QString &id) override;
|
||||||
|
void org_kde_plasma_window_request_leave_activity(Resource *resource, const QString &id) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
PlasmaWindowManagementInterfacePrivate::PlasmaWindowManagementInterfacePrivate(PlasmaWindowManagementInterface *_q, Display *display)
|
PlasmaWindowManagementInterfacePrivate::PlasmaWindowManagementInterfacePrivate(PlasmaWindowManagementInterface *_q, Display *display)
|
||||||
|
@ -343,6 +346,11 @@ void PlasmaWindowInterfacePrivate::org_kde_plasma_window_bind_resource(Resource
|
||||||
for (const auto &desk : plasmaVirtualDesktops) {
|
for (const auto &desk : plasmaVirtualDesktops) {
|
||||||
send_virtual_desktop_entered(resource->handle, desk);
|
send_virtual_desktop_entered(resource->handle, desk);
|
||||||
}
|
}
|
||||||
|
for (const auto &activity : plasmaActivities) {
|
||||||
|
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_ENTERED_SINCE_VERSION) {
|
||||||
|
send_activity_entered(resource->handle, activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!m_appId.isEmpty()) {
|
if (!m_appId.isEmpty()) {
|
||||||
send_app_id_changed(resource->handle, m_appId);
|
send_app_id_changed(resource->handle, m_appId);
|
||||||
}
|
}
|
||||||
|
@ -461,6 +469,18 @@ void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_leave_virtual_d
|
||||||
emit q->leavePlasmaVirtualDesktopRequested(id);
|
emit q->leavePlasmaVirtualDesktopRequested(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_enter_activity(Resource *resource, const QString &id)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource)
|
||||||
|
emit q->enterPlasmaActivityRequested(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_leave_activity(Resource *resource, const QString &id)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource)
|
||||||
|
emit q->leavePlasmaActivityRequested(id);
|
||||||
|
}
|
||||||
|
|
||||||
void PlasmaWindowInterfacePrivate::setTitle(const QString &title)
|
void PlasmaWindowInterfacePrivate::setTitle(const QString &title)
|
||||||
{
|
{
|
||||||
if (m_title == title) {
|
if (m_title == title) {
|
||||||
|
@ -915,6 +935,41 @@ QStringList PlasmaWindowInterface::plasmaVirtualDesktops() const
|
||||||
return d->plasmaVirtualDesktops;
|
return d->plasmaVirtualDesktops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlasmaWindowInterface::addPlasmaActivity(const QString &id)
|
||||||
|
{
|
||||||
|
if (d->plasmaActivities.contains(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->plasmaActivities << id;
|
||||||
|
|
||||||
|
const auto clientResources = d->resourceMap();
|
||||||
|
for (auto resource : clientResources) {
|
||||||
|
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_ENTERED_SINCE_VERSION) {
|
||||||
|
d->send_activity_entered(resource->handle, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlasmaWindowInterface::removePlasmaActivity(const QString &id)
|
||||||
|
{
|
||||||
|
if (!d->plasmaActivities.removeOne(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto clientResources = d->resourceMap();
|
||||||
|
for (auto resource : clientResources) {
|
||||||
|
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_LEFT_SINCE_VERSION) {
|
||||||
|
d->send_activity_left(resource->handle, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList PlasmaWindowInterface::plasmaActivities() const
|
||||||
|
{
|
||||||
|
return d->plasmaActivities;
|
||||||
|
}
|
||||||
|
|
||||||
void PlasmaWindowInterface::setShadeable(bool set)
|
void PlasmaWindowInterface::setShadeable(bool set)
|
||||||
{
|
{
|
||||||
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE, set);
|
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE, set);
|
||||||
|
|
|
@ -174,6 +174,24 @@ public:
|
||||||
*/
|
*/
|
||||||
QStringList plasmaVirtualDesktops() const;
|
QStringList plasmaVirtualDesktops() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an activity to this window: a window can be on
|
||||||
|
* an arbitrary subset of activities.
|
||||||
|
* If it's on none it will be considered on all activities.
|
||||||
|
*/
|
||||||
|
void addPlasmaActivity(const QString &id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an activity from a window
|
||||||
|
*/
|
||||||
|
void removePlasmaActivity(const QString &id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ids of all the activities currently associated with this window.
|
||||||
|
* When an activity is deleted it will be automatically removed from this list
|
||||||
|
*/
|
||||||
|
QStringList plasmaActivities() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the application menu D-BUS service name and object path for the window.
|
* Set the application menu D-BUS service name and object path for the window.
|
||||||
*/
|
*/
|
||||||
|
@ -242,6 +260,18 @@ Q_SIGNALS:
|
||||||
*/
|
*/
|
||||||
void leavePlasmaVirtualDesktopRequested(const QString &desktop);
|
void leavePlasmaVirtualDesktopRequested(const QString &desktop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the client wishes this window to enter an activity.
|
||||||
|
* The server will decide whether to consent this request
|
||||||
|
*/
|
||||||
|
void enterPlasmaActivityRequested(const QString &activity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the client wishes to remove this window from an activity.
|
||||||
|
* The server will decide whether to consent this request
|
||||||
|
*/
|
||||||
|
void leavePlasmaActivityRequested(const QString &activity);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class PlasmaWindowManagementInterface;
|
friend class PlasmaWindowManagementInterface;
|
||||||
friend class PlasmaWindowInterfacePrivate;
|
friend class PlasmaWindowInterfacePrivate;
|
||||||
|
|
Loading…
Reference in a new issue