Commit cee6912d authored by Méven Car's avatar Méven Car
Browse files

Implement kde-output-device-v2 and kde-output-management-v2

parent 8d960739
......@@ -30,10 +30,10 @@ set(SERVER_LIB_SRCS
layershell_v1_interface.cpp
linuxdmabufv1clientbuffer.cpp
output_interface.cpp
outputchangeset.cpp
outputconfiguration_interface.cpp
outputdevice_interface.cpp
outputmanagement_interface.cpp
outputdevice_v2_interface.cpp
outputconfiguration_v2_interface.cpp
outputmanagement_v2_interface.cpp
outputchangeset_v2.cpp
plasmashell_interface.cpp
plasmavirtualdesktop_interface.cpp
plasmawindowmanagement_interface.cpp
......@@ -84,13 +84,13 @@ ecm_add_qtwayland_server_protocol_kde(SERVER_LIB_SRCS
)
ecm_add_qtwayland_server_protocol_kde(SERVER_LIB_SRCS
PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/output-management.xml
BASENAME outputmanagement
PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/kde-output-device-v2.xml
BASENAME kde-output-device-v2
)
ecm_add_qtwayland_server_protocol_kde(SERVER_LIB_SRCS
PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/outputdevice.xml
BASENAME org-kde-kwin-outputdevice
PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/kde-output-management-v2.xml
BASENAME kde-output-management-v2
)
ecm_add_qtwayland_server_protocol_kde(SERVER_LIB_SRCS
......@@ -349,10 +349,10 @@ set(SERVER_LIB_HEADERS
layershell_v1_interface.h
linuxdmabufv1clientbuffer.h
output_interface.h
outputchangeset.h
outputconfiguration_interface.h
outputdevice_interface.h
outputmanagement_interface.h
outputchangeset_v2.h
outputconfiguration_v2_interface.h
outputdevice_v2_interface.h
outputmanagement_v2_interface.h
plasmashell_interface.h
plasmavirtualdesktop_interface.h
plasmawindowmanagement_interface.h
......
......@@ -44,28 +44,6 @@ target_link_libraries( testShmPool Qt::Test Qt::Gui KF5::WaylandClient Plasma::K
add_test(NAME kwayland-testShmPool COMMAND testShmPool)
ecm_mark_as_test(testShmPool)
########################################################
# Test KWin OutputManagement
########################################################
set( test_wayland_outputmanagement_SRCS
test_wayland_outputmanagement.cpp
)
add_executable(testWaylandOutputManagement ${test_wayland_outputmanagement_SRCS})
target_link_libraries( testWaylandOutputManagement Qt::Test Qt::Gui KF5::WaylandClient Plasma::KWaylandServer Wayland::Client)
add_test(NAME kwayland-testWaylandOutputManagement COMMAND testWaylandOutputManagement)
ecm_mark_as_test(testWaylandOutputManagement)
########################################################
# Test KWin OutputDevice
########################################################
set( test_wayland_outputdevice_SRCS
test_wayland_outputdevice.cpp
)
add_executable(testWaylandOutputDevice ${test_wayland_outputdevice_SRCS})
target_link_libraries( testWaylandOutputDevice Qt::Test Qt::Gui KF5::WaylandClient Plasma::KWaylandServer Wayland::Client)
add_test(NAME kwayland-testWaylandOutputDevice COMMAND testWaylandOutputDevice)
ecm_mark_as_test(testWaylandOutputDevice)
########################################################
# Test Compositor
########################################################
......
......@@ -10,6 +10,7 @@
#include "../../src/server/display.h"
#include "../../src/server/output_interface.h"
#include "../../src/server/outputmanagement_interface.h"
#include "../../src/server/outputmanagement_v2_interface.h"
// Wayland
#include <wayland-server.h>
// system
......@@ -183,7 +184,7 @@ void TestWaylandServerDisplay::testOutputManagement()
Display display;
display.addSocketName("kwayland-test-0");
display.start();
new OutputManagementInterface(&display, this);
new OutputManagementV2Interface(&display, this);
}
void TestWaylandServerDisplay::testAutoSocketName()
......
......@@ -157,9 +157,9 @@ QList<OutputInterface *> Display::outputs() const
return d->outputs;
}
QList<OutputDeviceInterface *> Display::outputDevices() const
QList< OutputDeviceV2Interface* > Display::outputDevices() const
{
return d->outputdevices;
return d->outputdevicesV2;
}
QVector<OutputInterface *> Display::outputsIntersecting(const QRect &rect) const
......
......@@ -36,7 +36,7 @@ class ClientBuffer;
class ClientConnection;
class DisplayPrivate;
class OutputInterface;
class OutputDeviceInterface;
class OutputDeviceV2Interface;
class SeatInterface;
/**
......@@ -111,8 +111,8 @@ public:
/**
* @returns All SeatInterface currently managed on the Display.
*/
QVector<SeatInterface *> seats() const;
QList<OutputDeviceInterface *> outputDevices() const;
QVector<SeatInterface*> seats() const;
QList<OutputDeviceV2Interface *> outputDevices() const;
QList<OutputInterface *> outputs() const;
QVector<OutputInterface *> outputsIntersecting(const QRect &rect) const;
......
......@@ -26,7 +26,7 @@ class ClientBuffer;
class ClientConnection;
class Display;
class OutputInterface;
class OutputDeviceInterface;
class OutputDeviceV2Interface;
class SeatInterface;
struct ClientBufferDestroyListener;
......@@ -47,7 +47,7 @@ public:
wl_event_loop *loop = nullptr;
bool running = false;
QList<OutputInterface *> outputs;
QList<OutputDeviceInterface *> outputdevices;
QList<OutputDeviceV2Interface *> outputdevicesV2;
QVector<SeatInterface *> seats;
QVector<ClientConnection *> clients;
QStringList socketNames;
......
/*
SPDX-FileCopyrightText: 2015 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2021 Méven Car <meven.car@enioka.com>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "outputchangeset_v2.h"
#include "outputchangeset_v2_p.h"
namespace KWaylandServer
{
OutputChangeSetV2Private::OutputChangeSetV2Private(OutputDeviceV2Interface *outputdevice, OutputChangeSetV2 *parent)
: q(parent)
, outputDevice(outputdevice)
, enabled(outputDevice->enabled())
, size(outputDevice->pixelSize())
, refreshRate(outputDevice->refreshRate())
, transform(outputDevice->transform())
, position(outputDevice->globalPosition())
, scale(outputDevice->scale())
, overscan(outputDevice->overscan())
{
}
OutputChangeSetV2::OutputChangeSetV2(OutputDeviceV2Interface *outputdevice, QObject *parent)
: QObject(parent)
, d(new OutputChangeSetV2Private(outputdevice, this))
{
}
OutputChangeSetV2::~OutputChangeSetV2() = default;
bool OutputChangeSetV2::enabledChanged() const
{
return d->enabled != d->outputDevice->enabled();
}
bool OutputChangeSetV2::enabled() const
{
return d->enabled;
}
QSize OutputChangeSetV2::size() const
{
return d->size;
}
bool OutputChangeSetV2::sizeChanged() const
{
return d->size != d->outputDevice->pixelSize();
}
int OutputChangeSetV2::refreshRate() const
{
return d->refreshRate;
}
bool OutputChangeSetV2::refreshRateChanged() const
{
return d->refreshRate != d->outputDevice->refreshRate();
}
bool OutputChangeSetV2::transformChanged() const
{
return d->transform != d->outputDevice->transform();
}
OutputDeviceV2Interface::Transform OutputChangeSetV2::transform() const
{
return d->transform;
}
bool OutputChangeSetV2::positionChanged() const
{
return d->position != d->outputDevice->globalPosition();
}
QPoint OutputChangeSetV2::position() const
{
return d->position;
}
bool OutputChangeSetV2::scaleChanged() const
{
return !qFuzzyCompare(d->scale, d->outputDevice->scale());
}
qreal OutputChangeSetV2::scale() const
{
return d->scale;
}
bool OutputChangeSetV2::overscanChanged() const
{
return d->overscan != d->outputDevice->overscan();
}
uint32_t OutputChangeSetV2::overscan() const
{
return d->overscan;
}
bool OutputChangeSetV2::vrrPolicyChanged() const
{
return d->vrrPolicy != d->outputDevice->vrrPolicy();
}
OutputDeviceV2Interface::VrrPolicy OutputChangeSetV2::vrrPolicy() const
{
return d->vrrPolicy;
}
}
/*
SPDX-FileCopyrightText: 2015 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2021 Méven Car <meven.car@enioka.com>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#pragma once
#include <QObject>
#include "outputdevice_v2_interface.h"
#include <KWaylandServer/kwaylandserver_export.h>
namespace KWaylandServer
{
class OutputChangeSetV2Private;
/**
* @brief Holds a set of changes to an OutputInterface or OutputDeviceInterface.
*
* This class implements a set of changes that the compositor can apply to an
* OutputInterface after OutputConfiguration::apply has been called on the client
* side. The changes are per-configuration.
*
* @see OutputConfiguration
*/
class KWAYLANDSERVER_EXPORT OutputChangeSetV2 : public QObject
{
Q_OBJECT
public:
~OutputChangeSetV2() override;
/** Whether the enabled() property of the outputdevice changed.
* @returns @c true if the enabled property of the outputdevice has changed.
*/
bool enabledChanged() const;
/** Whether the transform() property of the outputdevice changed.
* @returns @c true if the enabled property of the outputdevice has changed.
* bool modeChanged() const;
*/
/** Whether the transform() property of the outputdevice changed. */
bool transformChanged() const;
/** Whether the size property of the outputdevice changed.
*/
bool sizeChanged() const;
/** Whether the refreshRate property of the outputdevice changed.
*/
bool refreshRateChanged() const;
/** Whether the globalPosition() property of the outputdevice changed.
* @returns @c true if the globalPosition() property of the outputdevice has changed.
*/
bool positionChanged() const;
/** Whether the scale() property of the outputdevice changed.
* @returns @c true if the scale() property of the outputdevice has changed.
*/
bool scaleChanged() const;
/** Whether the overscan() property of the outputdevice changed.
* @returns @c true if the overscan() property of the outputdevice has changed
*/
bool overscanChanged() const;
/**
* Whether the vrrPolicy() property of the outputdevice changed.
* @returns @c true if the vrrPolicy() property of the outputdevice has changed.
*/
bool vrrPolicyChanged() const;
/** The new value for enabled. */
bool enabled() const;
/** The new size */
QSize size() const;
/** The new refresh rate */
int refreshRate() const;
/** The new value for transform. */
OutputDeviceV2Interface::Transform transform() const;
/** The new value for globalPosition. */
QPoint position() const;
/** The new value for scale.
*/
qreal scale() const;
/** the overscan value in % */
uint32_t overscan() const;
/** The new value for vrrPolicy */
OutputDeviceV2Interface::VrrPolicy vrrPolicy() const;
private:
friend class OutputConfigurationV2InterfacePrivate;
explicit OutputChangeSetV2(OutputDeviceV2Interface *outputdevice, QObject *parent = nullptr);
QScopedPointer<OutputChangeSetV2Private> d;
};
}
/*
SPDX-FileCopyrightText: 2015 Sebastian Kügler <sebas@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#pragma once
#include "outputchangeset_v2.h"
namespace KWaylandServer
{
class OutputChangeSetV2Private
{
public:
OutputChangeSetV2Private(OutputDeviceV2Interface *outputdevice, OutputChangeSetV2 *parent);
OutputChangeSetV2 *q;
OutputDeviceV2Interface *outputDevice;
bool enabled;
QSize size;
int refreshRate;
OutputDeviceV2Interface::Transform transform;
QPoint position;
qreal scale;
uint32_t overscan;
OutputDeviceV2Interface::VrrPolicy vrrPolicy = OutputDeviceV2Interface::VrrPolicy::Automatic;
};
}
/*
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
SPDX-FileCopyrightText: 2015 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2021 Méven Car <meven.car@enioka.com>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "display.h"
#include "outputconfiguration_v2_interface.h"
#include "outputdevice_v2_interface.h"
#include "logging.h"
#include "outputchangeset_v2_p.h"
#include "qwayland-server-kde-output-management-v2.h"
#include "qwayland-server-kde-output-device-v2.h"
namespace KWaylandServer
{
class OutputConfigurationV2InterfacePrivate : public QtWaylandServer::kde_output_configuration_v2
{
public:
OutputConfigurationV2InterfacePrivate(OutputConfigurationV2Interface *q, OutputManagementV2Interface *outputManagement, wl_resource *resource);
void sendApplied();
void sendFailed();
void emitConfigurationChangeRequested() const;
void clearPendingChanges();
bool hasPendingChanges(OutputDeviceV2Interface *outputdevice) const;
OutputChangeSetV2 *pendingChanges(OutputDeviceV2Interface *outputdevice);
OutputManagementV2Interface *outputManagement;
QHash<OutputDeviceV2Interface *, OutputChangeSetV2 *> changes;
OutputConfigurationV2Interface *q;
protected:
void kde_output_configuration_v2_enable(Resource *resource, wl_resource *outputdevice, int32_t enable) override;
void kde_output_configuration_v2_mode(Resource *resource, struct ::wl_resource *outputdevice, struct ::wl_resource *mode) override;
void kde_output_configuration_v2_transform(Resource *resource, wl_resource *outputdevice, int32_t transform) override;
void kde_output_configuration_v2_position(Resource *resource, wl_resource *outputdevice, int32_t x, int32_t y) override;
void kde_output_configuration_v2_scale(Resource *resource, wl_resource *outputdevice, wl_fixed_t scale) override;
void kde_output_configuration_v2_apply(Resource *resource) override;
void kde_output_configuration_v2_destroy(Resource *resource) override;
void kde_output_configuration_v2_destroy_resource(Resource *resource) override;
void kde_output_configuration_v2_overscan(Resource *resource, wl_resource *outputdevice, uint32_t overscan) override;
void kde_output_configuration_v2_set_vrr_policy(Resource *resource, struct ::wl_resource *outputdevice, uint32_t policy) override;
};
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_enable(Resource *resource, wl_resource *outputdevice, int32_t enable)
{
Q_UNUSED(resource)
OutputDeviceV2Interface *output = OutputDeviceV2Interface::get(outputdevice);
pendingChanges(output)->d->enabled = enable == 1;
}
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_mode(Resource *resource, wl_resource *outputdevice, wl_resource *modeResource)
{
Q_UNUSED(resource)
OutputDeviceV2Interface *output = OutputDeviceV2Interface::get(outputdevice);
OutputDeviceModeV2Interface *mode = OutputDeviceModeV2Interface::get(modeResource);
pendingChanges(output)->d->size = mode->size();
pendingChanges(output)->d->refreshRate = mode->refreshRate();
}
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_transform(Resource *resource, wl_resource *outputdevice, int32_t transform)
{
Q_UNUSED(resource)
auto toTransform = [transform]() {
switch (transform) {
case WL_OUTPUT_TRANSFORM_90:
return OutputDeviceV2Interface::Transform::Rotated90;
case WL_OUTPUT_TRANSFORM_180:
return OutputDeviceV2Interface::Transform::Rotated180;
case WL_OUTPUT_TRANSFORM_270:
return OutputDeviceV2Interface::Transform::Rotated270;
case WL_OUTPUT_TRANSFORM_FLIPPED:
return OutputDeviceV2Interface::Transform::Flipped;
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
return OutputDeviceV2Interface::Transform::Flipped90;
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
return OutputDeviceV2Interface::Transform::Flipped180;
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
return OutputDeviceV2Interface::Transform::Flipped270;
case WL_OUTPUT_TRANSFORM_NORMAL:
default:
return OutputDeviceV2Interface::Transform::Normal;
}
};
auto _transform = toTransform();
OutputDeviceV2Interface *output = OutputDeviceV2Interface::get(outputdevice);
pendingChanges(output)->d->transform = _transform;
}
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_position(Resource *resource, wl_resource *outputdevice, int32_t x, int32_t y)
{
Q_UNUSED(resource)
auto _pos = QPoint(x, y);
OutputDeviceV2Interface *output = OutputDeviceV2Interface::get(outputdevice);
pendingChanges(output)->d->position = _pos;
}
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_scale(Resource *resource, wl_resource *outputdevice, wl_fixed_t scale)
{
Q_UNUSED(resource)
const qreal doubleScale = wl_fixed_to_double(scale);
if (doubleScale <= 0) {
qCWarning(KWAYLAND_SERVER) << "Requested to scale output device to" << doubleScale << ", but I can't do that.";
return;
}
OutputDeviceV2Interface *output = OutputDeviceV2Interface::get(outputdevice);
pendingChanges(output)->d->scale = doubleScale;
}
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_apply(Resource *resource)
{
Q_UNUSED(resource)
emitConfigurationChangeRequested();
}
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_overscan(Resource *resource, wl_resource *outputdevice, uint32_t overscan)
{
Q_UNUSED(resource)
if (overscan > 100) {
qCWarning(KWAYLAND_SERVER) << "Invalid overscan requested:" << overscan;
return;
}
OutputDeviceV2Interface *output = OutputDeviceV2Interface::get(outputdevice);
pendingChanges(output)->d->overscan = overscan;
}
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_set_vrr_policy(Resource *resource, wl_resource *outputdevice, uint32_t policy)
{
Q_UNUSED(resource)
if (policy > static_cast<uint32_t>(OutputDeviceV2Interface::VrrPolicy::Automatic)) {
qCWarning(KWAYLAND_SERVER) << "Invalid Vrr Policy requested:" << policy;
return;
}
OutputDeviceV2Interface *output = OutputDeviceV2Interface::get(outputdevice);
pendingChanges(output)->d->vrrPolicy = static_cast<OutputDeviceV2Interface::VrrPolicy>(policy);
}
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_destroy(Resource *resource)
{
wl_resource_destroy(resource->handle);
}
void OutputConfigurationV2InterfacePrivate::kde_output_configuration_v2_destroy_resource(Resource *resource)
{
Q_UNUSED(resource)
delete q;
}
void OutputConfigurationV2InterfacePrivate::emitConfigurationChangeRequested() const
{
auto configinterface = reinterpret_cast<OutputConfigurationV2Interface *>(q);
Q_EMIT outputManagement->configurationChangeRequested(configinterface);
}
OutputConfigurationV2InterfacePrivate::OutputConfigurationV2InterfacePrivate(OutputConfigurationV2Interface *q, OutputManagementV2Interface *outputManagement, wl_resource *resource)
: QtWaylandServer::kde_output_configuration_v2(resource)
, outputManagement(outputManagement)
, q(q)
{
}
QHash<OutputDeviceV2Interface*, OutputChangeSetV2*> OutputConfigurationV2Interface::changes() const
{
return d->changes;
}
void OutputConfigurationV2Interface::setApplied()
{
d->clearPendingChanges();
d->sendApplied();
}
void OutputConfigurationV2InterfacePrivate::sendApplied()
{
send_applied();
}
void OutputConfigurationV2Interface::setFailed()
{
d->clearPendingChanges();
d->sendFailed();
}
void OutputConfigurationV2InterfacePrivate::sendFailed()
{
send_failed();
}
OutputChangeSetV2 *OutputConfigurationV2InterfacePrivate::pendingChanges(OutputDeviceV2Interface *outputdevice)
{
auto &change = changes[outputdevice];
if (!change) {
change = new OutputChangeSetV2(outputdevice, q);
}
return change;
}
bool OutputConfigurationV2InterfacePrivate::hasPendingChanges(OutputDeviceV2Interface *outputdevice) const
{
auto it = changes.constFind(outputdevice);
if (it == changes.constEnd()) {