Add XDG Output Protocol
Summary: Done primarily for XWayland which for legacy reasons doesn't assume the logical size of a display is pixelSize / outputScale. Meaning xwayland windows that position themselves are wrong in a scaled environment. It also allows the possibility for us to support fractional scaling whilst keeping wl_output::scale as an integer. The protocol is a bit odd as it operates via the FooManager + Foo pattern rather than using globals like Output so I've wrapped it so it behaves more like globals. Test Plan: #plasma Reviewers: romangg Subscribers: #frameworks Tags: #frameworks Maniphest Tasks: T8501 Differential Revision: https://phabricator.kde.org/D12235
This commit is contained in:
parent
8da9a184ed
commit
b2f7c6ea02
8 changed files with 641 additions and 0 deletions
|
@ -54,6 +54,7 @@ set(SERVER_LIB_SRCS
|
|||
xdgforeign_v2_interface.cpp
|
||||
xdgforeign_interface.cpp
|
||||
xdgshell_v6_interface.cpp
|
||||
xdgoutput_interface.cpp
|
||||
)
|
||||
|
||||
ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
|
||||
|
@ -180,6 +181,11 @@ ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
|
|||
BASENAME remote-access
|
||||
)
|
||||
|
||||
ecm_add_wayland_server_protocol(SERVER_LIB_SRCS
|
||||
PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/xdg-output-unstable-v1.xml
|
||||
BASENAME xdg-output
|
||||
)
|
||||
|
||||
set(SERVER_GENERATED_SRCS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-output-management-client-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-output-management-server-protocol.h
|
||||
|
@ -227,6 +233,8 @@ set(SERVER_GENERATED_SRCS
|
|||
${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-foreign-unstable-v2-server-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-idle-inhibit-unstable-v1-client-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-idle-inhibit-unstable-v1-server-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-output-unstable-v1-client-protocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/wayland-output-unstable-v1-server-protocol.h
|
||||
)
|
||||
|
||||
set_source_files_properties(${SERVER_GENERATED_SRCS} PROPERTIES SKIP_AUTOMOC ON)
|
||||
|
@ -306,6 +314,7 @@ set(SERVER_LIB_HEADERS
|
|||
touch_interface.h
|
||||
xdgshell_interface.h
|
||||
xdgforeign_interface.h
|
||||
xdgoutput_interface.h
|
||||
)
|
||||
|
||||
install(FILES
|
||||
|
|
|
@ -429,3 +429,14 @@ add_executable(testRemoteAccess ${testRemoteAccess_SRCS})
|
|||
target_link_libraries( testRemoteAccess Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer)
|
||||
add_test(NAME kwayland-testRemoteAccess COMMAND testRemoteAccess)
|
||||
ecm_mark_as_test(testRemoteAccess)
|
||||
|
||||
########################################################
|
||||
# Test XDG Output
|
||||
########################################################
|
||||
set( testXdgOutput_SRCS
|
||||
test_xdg_output.cpp
|
||||
)
|
||||
add_executable(testXdgOutput ${testXdgOutput_SRCS})
|
||||
target_link_libraries( testXdgOutput Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer Wayland::Client Wayland::Server)
|
||||
add_test(NAME kwayland-testXdgOutput COMMAND testXdgOutput)
|
||||
ecm_mark_as_test(testXdgOutput)
|
||||
|
|
174
src/wayland/autotests/client/test_xdg_output.cpp
Normal file
174
src/wayland/autotests/client/test_xdg_output.cpp
Normal file
|
@ -0,0 +1,174 @@
|
|||
/********************************************************************
|
||||
Copyright 2018 David Edmundson <davidedmundson@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/connection_thread.h"
|
||||
#include "../../src/client/event_queue.h"
|
||||
#include "../../src/client/dpms.h"
|
||||
#include "../../src/client/output.h"
|
||||
#include "../../src/client/xdgoutput.h"
|
||||
#include "../../src/client/registry.h"
|
||||
#include "../../src/server/display.h"
|
||||
#include "../../src/server/dpms_interface.h"
|
||||
#include "../../src/server/output_interface.h"
|
||||
#include "../../src/server/xdgoutput_interface.h"
|
||||
|
||||
// Wayland
|
||||
|
||||
class TestXdgOutput : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TestXdgOutput(QObject *parent = nullptr);
|
||||
private Q_SLOTS:
|
||||
void init();
|
||||
void cleanup();
|
||||
void testChanges();
|
||||
private:
|
||||
KWayland::Server::Display *m_display;
|
||||
KWayland::Server::OutputInterface *m_serverOutput;
|
||||
KWayland::Server::XdgOutputManagerInterface *m_serverXdgOutputManager;
|
||||
KWayland::Server::XdgOutputInterface *m_serverXdgOutput;
|
||||
KWayland::Client::ConnectionThread *m_connection;
|
||||
KWayland::Client::EventQueue *m_queue;
|
||||
QThread *m_thread;
|
||||
};
|
||||
|
||||
static const QString s_socketName = QStringLiteral("kwin-test-xdg-output-0");
|
||||
|
||||
TestXdgOutput::TestXdgOutput(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_display(nullptr)
|
||||
, m_serverOutput(nullptr)
|
||||
, m_connection(nullptr)
|
||||
, m_thread(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void TestXdgOutput::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());
|
||||
|
||||
m_serverOutput = m_display->createOutput(this);
|
||||
m_serverOutput->addMode(QSize(1920, 1080), OutputInterface::ModeFlags(OutputInterface::ModeFlag::Preferred));
|
||||
m_serverOutput->setCurrentMode(QSize(1920, 1080));
|
||||
m_serverOutput->create();
|
||||
|
||||
m_serverXdgOutputManager = m_display->createXdgOutputManager(this);
|
||||
m_serverXdgOutputManager->create();
|
||||
m_serverXdgOutput = m_serverXdgOutputManager->createXdgOutput(m_serverOutput, this);
|
||||
m_serverXdgOutput->setLogicalSize(QSize(1280, 720)); //a 1.5 scale factor
|
||||
m_serverXdgOutput->setLogicalPosition(QPoint(11,12)); //not a sensible value for one monitor, but works for this test
|
||||
m_serverXdgOutput->done();
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
void TestXdgOutput::cleanup()
|
||||
{
|
||||
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_serverOutput;
|
||||
m_serverOutput = nullptr;
|
||||
|
||||
delete m_display;
|
||||
m_display = nullptr;
|
||||
}
|
||||
|
||||
void TestXdgOutput::testChanges()
|
||||
{
|
||||
// verify the server modes
|
||||
using namespace KWayland::Server;
|
||||
using namespace KWayland::Client;
|
||||
KWayland::Client::Registry registry;
|
||||
QSignalSpy announced(®istry, SIGNAL(outputAnnounced(quint32,quint32)));
|
||||
QSignalSpy xdgOutputAnnounced(®istry, SIGNAL(xdgOutputAnnounced(quint32,quint32)));
|
||||
|
||||
registry.setEventQueue(m_queue);
|
||||
registry.create(m_connection->display());
|
||||
QVERIFY(registry.isValid());
|
||||
registry.setup();
|
||||
QVERIFY(announced.wait());
|
||||
if (xdgOutputAnnounced.count() != 1) {
|
||||
QVERIFY(xdgOutputAnnounced.wait());
|
||||
}
|
||||
|
||||
KWayland::Client::Output output;
|
||||
QSignalSpy outputChanged(&output, SIGNAL(changed()));
|
||||
|
||||
output.setup(registry.bindOutput(announced.first().first().value<quint32>(), announced.first().last().value<quint32>()));
|
||||
QVERIFY(outputChanged.wait());
|
||||
|
||||
QScopedPointer<KWayland::Client::XdgOutputManager> xdgOutputManager(registry.createXdgOutputManager(xdgOutputAnnounced.first().first().value<quint32>(), xdgOutputAnnounced.first().last().value<quint32>(), this));
|
||||
|
||||
QScopedPointer<KWayland::Client::XdgOutput> xdgOutput(xdgOutputManager->getXdgOutput(&output, this));
|
||||
QSignalSpy xdgOutputChanged(xdgOutput.data(), SIGNAL(changed()));
|
||||
|
||||
//check details are sent on client bind
|
||||
QVERIFY(xdgOutputChanged.wait());
|
||||
xdgOutputChanged.clear();
|
||||
QCOMPARE(xdgOutput->logicalPosition(), QPoint(11,12));
|
||||
QCOMPARE(xdgOutput->logicalSize(), QSize(1280,720));
|
||||
|
||||
//dynamic updates
|
||||
m_serverXdgOutput->setLogicalPosition(QPoint(1000, 2000));
|
||||
m_serverXdgOutput->setLogicalSize(QSize(100,200));
|
||||
m_serverXdgOutput->done();
|
||||
|
||||
QVERIFY(xdgOutputChanged.wait());
|
||||
QCOMPARE(xdgOutputChanged.count(), 1);
|
||||
QCOMPARE(xdgOutput->logicalPosition(), QPoint(1000, 2000));
|
||||
QCOMPARE(xdgOutput->logicalSize(), QSize(100,200));
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(TestXdgOutput)
|
||||
#include "test_xdg_output.moc"
|
|
@ -50,6 +50,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "xdgshell_v6_interface_p.h"
|
||||
#include "appmenu_interface.h"
|
||||
#include "server_decoration_palette_interface.h"
|
||||
#include "xdgoutput_interface.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
@ -457,6 +458,13 @@ ServerSideDecorationPaletteManagerInterface *Display::createServerSideDecoration
|
|||
return b;
|
||||
}
|
||||
|
||||
XdgOutputManagerInterface *Display::createXdgOutputManager(QObject *parent)
|
||||
{
|
||||
auto b = new XdgOutputManagerInterface(this, parent);
|
||||
connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; });
|
||||
return b;
|
||||
}
|
||||
|
||||
void Display::createShm()
|
||||
{
|
||||
Q_ASSERT(d->display);
|
||||
|
|
|
@ -86,6 +86,7 @@ class PointerConstraintsInterface;
|
|||
class XdgForeignInterface;
|
||||
class AppMenuManagerInterface;
|
||||
class ServerSideDecorationPaletteManagerInterface;
|
||||
class XdgOutputManagerInterface;
|
||||
|
||||
/**
|
||||
* @brief Class holding the Wayland server display loop.
|
||||
|
@ -258,6 +259,14 @@ public:
|
|||
**/
|
||||
ServerSideDecorationPaletteManagerInterface *createServerSideDecorationPaletteManager(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* Creates the XdgOutputManagerInterface
|
||||
*
|
||||
* @return the created manager
|
||||
* @since 5.XDGOUTPUTVERSION
|
||||
*/
|
||||
XdgOutputManagerInterface *createXdgOutputManager(QObject *parent = nullptr);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the ClientConnection for the given @p client.
|
||||
|
|
307
src/wayland/server/xdgoutput_interface.cpp
Normal file
307
src/wayland/server/xdgoutput_interface.cpp
Normal file
|
@ -0,0 +1,307 @@
|
|||
/****************************************************************************
|
||||
Copyright 2018 David Edmundson <kde@davidedmundson.co.uk>
|
||||
|
||||
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 "xdgoutput_interface.h"
|
||||
#include "display.h"
|
||||
#include "global_p.h"
|
||||
#include "resource_p.h"
|
||||
#include "output_interface.h"
|
||||
|
||||
#include <wayland-xdg-output-server-protocol.h>
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Server
|
||||
{
|
||||
|
||||
class XdgOutputManagerInterface::Private : public Global::Private
|
||||
{
|
||||
public:
|
||||
Private(XdgOutputManagerInterface *q, Display *d);
|
||||
QHash<OutputInterface*, XdgOutputInterface*> outputs;
|
||||
|
||||
private:
|
||||
void bind(wl_client *client, uint32_t version, uint32_t id) override;
|
||||
|
||||
static void unbind(wl_resource *resource);
|
||||
static Private *cast(wl_resource *r) {
|
||||
return reinterpret_cast<Private*>(wl_resource_get_user_data(r));
|
||||
}
|
||||
|
||||
static void destroyCallback(wl_client *client, wl_resource *resource);
|
||||
static void getXdgOutputCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * output);
|
||||
|
||||
XdgOutputManagerInterface *q;
|
||||
static const struct zxdg_output_manager_v1_interface s_interface;
|
||||
static const quint32 s_version;
|
||||
};
|
||||
|
||||
const quint32 XdgOutputManagerInterface::Private::s_version = 1;
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
const struct zxdg_output_manager_v1_interface XdgOutputManagerInterface::Private::s_interface = {
|
||||
destroyCallback,
|
||||
getXdgOutputCallback
|
||||
};
|
||||
#endif
|
||||
|
||||
class XdgOutputV1Interface: public Resource
|
||||
{
|
||||
public:
|
||||
XdgOutputV1Interface(XdgOutputManagerInterface *parent, wl_resource *parentResource);
|
||||
~XdgOutputV1Interface();
|
||||
void setLogicalSize(const QSize &size);
|
||||
void setLogicalPosition(const QPoint &pos);
|
||||
void done();
|
||||
private:
|
||||
class Private;
|
||||
};
|
||||
|
||||
class XdgOutputInterface::Private
|
||||
{
|
||||
public:
|
||||
void resourceConnected(XdgOutputV1Interface *resource);
|
||||
void resourceDisconnected(XdgOutputV1Interface *resource);
|
||||
QPoint pos;
|
||||
QSize size;
|
||||
bool doneOnce = false;
|
||||
QList<XdgOutputV1Interface*> resources;
|
||||
};
|
||||
|
||||
|
||||
XdgOutputManagerInterface::XdgOutputManagerInterface(Display *display, QObject *parent)
|
||||
: Global(new XdgOutputManagerInterface::Private(this, display))
|
||||
{
|
||||
}
|
||||
|
||||
XdgOutputManagerInterface::~XdgOutputManagerInterface()
|
||||
{}
|
||||
|
||||
XdgOutputInterface* XdgOutputManagerInterface::createXdgOutput(OutputInterface *output, QObject *parent)
|
||||
{
|
||||
Q_D();
|
||||
if (!d->outputs.contains(output)) {
|
||||
auto xdgOutput = new XdgOutputInterface(parent);
|
||||
d->outputs[output] = xdgOutput;
|
||||
//as XdgOutput lifespan is managed by user, delete our mapping when either
|
||||
//it or the relevant Output gets deleted
|
||||
connect(output, &QObject::destroyed, this, [this, output]() {
|
||||
Q_D();
|
||||
d->outputs.remove(output);
|
||||
});
|
||||
connect(xdgOutput, &QObject::destroyed, this, [this, output]() {
|
||||
Q_D();
|
||||
d->outputs.remove(output);
|
||||
});
|
||||
|
||||
}
|
||||
return d->outputs[output];
|
||||
}
|
||||
|
||||
XdgOutputManagerInterface::Private* XdgOutputManagerInterface::d_func() const
|
||||
{
|
||||
return reinterpret_cast<Private*>(d.data());
|
||||
}
|
||||
|
||||
void XdgOutputManagerInterface::Private::destroyCallback(wl_client *client, wl_resource *resource)
|
||||
{
|
||||
Q_UNUSED(client)
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
void XdgOutputManagerInterface::Private::getXdgOutputCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * outputResource)
|
||||
{
|
||||
auto d = cast(resource);
|
||||
auto output = OutputInterface::get(outputResource);
|
||||
if (!output) { // output client is requesting XdgOutput for an Output that doesn't exist
|
||||
return;
|
||||
}
|
||||
if (!d->outputs.contains(output)) {
|
||||
return; //server hasn't created an XdgOutput for this output yet, give the client nothing
|
||||
}
|
||||
auto iface = new XdgOutputV1Interface(d->q, resource);
|
||||
iface->create(d->display->getConnection(client), wl_resource_get_version(resource), id);
|
||||
if (!iface->resource()) {
|
||||
wl_resource_post_no_memory(resource);
|
||||
delete iface;
|
||||
return;
|
||||
}
|
||||
|
||||
auto xdgOutput = d->outputs[output];
|
||||
xdgOutput->d->resourceConnected(iface);
|
||||
connect(iface, &XdgOutputV1Interface::unbound, xdgOutput, [xdgOutput, iface]() {
|
||||
xdgOutput->d->resourceDisconnected(iface);
|
||||
});
|
||||
}
|
||||
|
||||
XdgOutputManagerInterface::Private::Private(XdgOutputManagerInterface *q, Display *d)
|
||||
: Global::Private(d, &zxdg_output_manager_v1_interface, s_version)
|
||||
, q(q)
|
||||
{
|
||||
}
|
||||
|
||||
void XdgOutputManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
|
||||
{
|
||||
auto c = display->getConnection(client);
|
||||
wl_resource *resource = c->createResource(&zxdg_output_manager_v1_interface, qMin(version, s_version), id);
|
||||
if (!resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(resource, &s_interface, this, unbind);
|
||||
}
|
||||
|
||||
void XdgOutputManagerInterface::Private::unbind(wl_resource *resource)
|
||||
{
|
||||
Q_UNUSED(resource)
|
||||
}
|
||||
|
||||
XdgOutputInterface::XdgOutputInterface(QObject *parent):
|
||||
QObject(parent),
|
||||
d(new XdgOutputInterface::Private)
|
||||
{
|
||||
}
|
||||
|
||||
XdgOutputInterface::~XdgOutputInterface()
|
||||
{}
|
||||
|
||||
void XdgOutputInterface::setLogicalSize(const QSize &size)
|
||||
{
|
||||
if (size == d->size) {
|
||||
return;
|
||||
}
|
||||
d->size = size;
|
||||
for(auto resource: d->resources) {
|
||||
resource->setLogicalSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
QSize XdgOutputInterface::logicalSize() const
|
||||
{
|
||||
return d->size;
|
||||
}
|
||||
|
||||
void XdgOutputInterface::setLogicalPosition(const QPoint &pos)
|
||||
{
|
||||
if (pos == d->pos) {
|
||||
return;
|
||||
}
|
||||
d->pos = pos;
|
||||
for(auto resource: d->resources) {
|
||||
resource->setLogicalPosition(pos);
|
||||
}
|
||||
}
|
||||
|
||||
QPoint XdgOutputInterface::logicalPosition() const
|
||||
{
|
||||
return d->pos;
|
||||
}
|
||||
|
||||
void XdgOutputInterface::done()
|
||||
{
|
||||
d->doneOnce = true;
|
||||
for(auto resource: d->resources) {
|
||||
resource->done();
|
||||
}
|
||||
}
|
||||
|
||||
void XdgOutputInterface::Private::resourceConnected(XdgOutputV1Interface *resource)
|
||||
{
|
||||
resource->setLogicalPosition(pos);
|
||||
resource->setLogicalSize(size);
|
||||
if (doneOnce) {
|
||||
resource->done();
|
||||
}
|
||||
resources << resource;
|
||||
}
|
||||
|
||||
void XdgOutputInterface::Private::resourceDisconnected(XdgOutputV1Interface *resource)
|
||||
{
|
||||
resources.removeOne(resource);
|
||||
}
|
||||
|
||||
|
||||
class XdgOutputV1Interface::Private : public Resource::Private
|
||||
{
|
||||
public:
|
||||
Private(XdgOutputV1Interface *q, XdgOutputManagerInterface *c, wl_resource *parentResource);
|
||||
~Private();
|
||||
|
||||
private:
|
||||
|
||||
XdgOutputV1Interface *q_func() {
|
||||
return reinterpret_cast<XdgOutputV1Interface *>(q);
|
||||
}
|
||||
|
||||
static const struct zxdg_output_v1_interface s_interface;
|
||||
};
|
||||
|
||||
XdgOutputV1Interface::XdgOutputV1Interface(XdgOutputManagerInterface *parent, wl_resource *parentResource)
|
||||
:Resource(new XdgOutputV1Interface::Private(this, parent, parentResource))
|
||||
{}
|
||||
|
||||
XdgOutputV1Interface::~XdgOutputV1Interface()
|
||||
{}
|
||||
|
||||
void XdgOutputV1Interface::setLogicalSize(const QSize &size)
|
||||
{
|
||||
if (!d->resource) {
|
||||
return;
|
||||
}
|
||||
zxdg_output_v1_send_logical_size(d->resource, size.width(), size.height());
|
||||
}
|
||||
|
||||
void XdgOutputV1Interface::setLogicalPosition(const QPoint &pos)
|
||||
{
|
||||
if (!d->resource) {
|
||||
return;
|
||||
}
|
||||
zxdg_output_v1_send_logical_position(d->resource, pos.x(), pos.y());
|
||||
}
|
||||
|
||||
void XdgOutputV1Interface::done()
|
||||
{
|
||||
if (!d->resource) {
|
||||
return;
|
||||
}
|
||||
zxdg_output_v1_send_done(d->resource);
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
const struct zxdg_output_v1_interface XdgOutputV1Interface::Private::s_interface = {
|
||||
resourceDestroyedCallback
|
||||
};
|
||||
#endif
|
||||
|
||||
XdgOutputV1Interface::Private::Private(XdgOutputV1Interface *q, XdgOutputManagerInterface *c, wl_resource *parentResource)
|
||||
: Resource::Private(q, c, parentResource, &zxdg_output_v1_interface, &s_interface)
|
||||
{
|
||||
}
|
||||
|
||||
XdgOutputV1Interface::Private::~Private()
|
||||
{
|
||||
if (resource) {
|
||||
wl_resource_destroy(resource);
|
||||
resource = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
121
src/wayland/server/xdgoutput_interface.h
Normal file
121
src/wayland/server/xdgoutput_interface.h
Normal file
|
@ -0,0 +1,121 @@
|
|||
/****************************************************************************
|
||||
Copyright 2018 David Edmundson <kde@davidedmundson.co.uk>
|
||||
|
||||
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_XDGOUTPUT_H
|
||||
#define KWAYLAND_SERVER_XDGOUTPUT_H
|
||||
|
||||
#include "global.h"
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
#include <KWayland/Server/kwaylandserver_export.h>
|
||||
|
||||
|
||||
/*
|
||||
* In terms of protocol XdgOutputInterface are a resource
|
||||
* but for the sake of sanity, we should treat XdgOutputs as globals like Output is
|
||||
* Hence this doesn't match most of kwayland API paradigms.
|
||||
*/
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Server
|
||||
{
|
||||
|
||||
class Display;
|
||||
class OutputInterface;
|
||||
class XdgOutputInterface;
|
||||
|
||||
/**
|
||||
* Global manager for XdgOutputs
|
||||
* @since 5.XDGOUTPUT
|
||||
*/
|
||||
class KWAYLANDSERVER_EXPORT XdgOutputManagerInterface : public Global
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~XdgOutputManagerInterface();
|
||||
/**
|
||||
* Creates an XdgOutputInterface object for an existing Output
|
||||
* which exposes XDG specific properties of outputs
|
||||
*
|
||||
* @arg output the wl_output interface this XDG output is for
|
||||
* @parent the parent of the newly created object
|
||||
*/
|
||||
XdgOutputInterface* createXdgOutput(OutputInterface *output, QObject *parent);
|
||||
private:
|
||||
explicit XdgOutputManagerInterface(Display *display, QObject *parent = nullptr);
|
||||
friend class Display;
|
||||
class Private;
|
||||
Private *d_func() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Extension to Output
|
||||
* Users should set all relevant values on creation and on future changes.
|
||||
* done() should be explicitly called after change batches including initial setting.
|
||||
* @since 5.XDGOUTPUT
|
||||
*/
|
||||
class KWAYLANDSERVER_EXPORT XdgOutputInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~XdgOutputInterface();
|
||||
|
||||
/**
|
||||
* Sets the size of this output in logical co-ordinates.
|
||||
* Users should call done() after setting all values
|
||||
*/
|
||||
void setLogicalSize(const QSize &size);
|
||||
|
||||
/**
|
||||
* Returns the last set logical size on this output
|
||||
*/
|
||||
QSize logicalSize() const;
|
||||
|
||||
/**
|
||||
* Sets the topleft position of this output in logical co-ordinates.
|
||||
* Users should call done() after setting all values
|
||||
* @see OutputInterface::setPosition
|
||||
*/
|
||||
void setLogicalPosition(const QPoint &pos);
|
||||
|
||||
/**
|
||||
* Returns the last set logical position on this output
|
||||
*/
|
||||
QPoint logicalPosition() const;
|
||||
|
||||
/**
|
||||
* Submit changes to all clients
|
||||
*/
|
||||
void done();
|
||||
|
||||
private:
|
||||
explicit XdgOutputInterface(QObject *parent);
|
||||
friend class XdgOutputManagerInterface;
|
||||
|
||||
class Private;
|
||||
QScopedPointer<Private> d;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -62,3 +62,5 @@ zwp_idle_inhibit_manager_v1;IdleInhibitManager
|
|||
zwp_idle_inhibitor_v1;IdleInhibitor
|
||||
org_kde_kwin_remote_access_manager;RemoteAccessManager
|
||||
org_kde_kwin_remote_buffer;RemoteBuffer
|
||||
zxdg_output_v1;XdgOutput
|
||||
zxdg_output_manager_v1;XdgOutputManager
|
||||
|
|
Loading…
Reference in a new issue