wayland: Make XdgOutputV1Interface pull information from Output
This commit is contained in:
parent
e9e97e49bf
commit
c3f970b3c3
7 changed files with 88 additions and 167 deletions
|
@ -61,17 +61,16 @@ void TestXdgOutput::init()
|
|||
|
||||
m_outputHandle = std::make_unique<FakeOutput>();
|
||||
m_outputHandle->setMode(QSize(1920, 1080), 60000);
|
||||
m_outputHandle->moveTo(QPoint(11, 12)); // not a sensible value for one monitor, but works for this test
|
||||
m_outputHandle->setScale(1.5);
|
||||
m_outputHandle->setName("testName");
|
||||
m_outputHandle->setManufacturer("foo");
|
||||
m_outputHandle->setModel("bar");
|
||||
|
||||
m_serverOutput = new OutputInterface(m_display, m_outputHandle.get(), this);
|
||||
|
||||
m_serverXdgOutputManager = new XdgOutputManagerV1Interface(m_display, this);
|
||||
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->setName("testName");
|
||||
m_serverXdgOutput->setDescription("testDescription");
|
||||
|
||||
m_serverXdgOutput->done();
|
||||
|
||||
// setup connection
|
||||
m_connection = new KWayland::Client::ConnectionThread;
|
||||
|
@ -150,20 +149,23 @@ void TestXdgOutput::testChanges()
|
|||
QCOMPARE(xdgOutput->logicalPosition(), QPoint(11, 12));
|
||||
QCOMPARE(xdgOutput->logicalSize(), QSize(1280, 720));
|
||||
QCOMPARE(xdgOutput->name(), "testName");
|
||||
QCOMPARE(xdgOutput->description(), "testDescription");
|
||||
|
||||
// dynamic updates
|
||||
m_serverXdgOutput->setLogicalPosition(QPoint(1000, 2000));
|
||||
m_serverXdgOutput->setLogicalSize(QSize(100, 200));
|
||||
// names cannot dynamically change according to the spec
|
||||
|
||||
m_serverXdgOutput->done();
|
||||
m_serverOutput->scheduleDone();
|
||||
QCOMPARE(xdgOutput->description(), "foo bar");
|
||||
|
||||
// change the logical position
|
||||
m_outputHandle->moveTo(QPoint(1000, 2000));
|
||||
QVERIFY(xdgOutputChanged.wait());
|
||||
QCOMPARE(xdgOutputChanged.count(), 1);
|
||||
QCOMPARE(xdgOutput->logicalPosition(), QPoint(1000, 2000));
|
||||
QCOMPARE(xdgOutput->logicalSize(), QSize(100, 200));
|
||||
QEXPECT_FAIL("", "KWayland::Client::XdgOutput incorrectly handles partial updates", Continue);
|
||||
QCOMPARE(xdgOutput->logicalSize(), QSize(1280, 720));
|
||||
|
||||
// change the logical size
|
||||
m_outputHandle->setScale(2);
|
||||
QVERIFY(xdgOutputChanged.wait());
|
||||
QCOMPARE(xdgOutputChanged.count(), 2);
|
||||
QEXPECT_FAIL("", "KWayland::Client::XdgOutput incorrectly handles partial updates", Continue);
|
||||
QCOMPARE(xdgOutput->logicalPosition(), QPoint(1000, 2000));
|
||||
QCOMPARE(xdgOutput->logicalSize(), QSize(960, 540));
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(TestXdgOutput)
|
||||
|
|
|
@ -69,3 +69,24 @@ void FakeOutput::setPhysicalSize(QSize size)
|
|||
.physicalSize = size,
|
||||
});
|
||||
}
|
||||
|
||||
void FakeOutput::setName(const QString &name)
|
||||
{
|
||||
Information info = m_information;
|
||||
info.name = name;
|
||||
setInformation(info);
|
||||
}
|
||||
|
||||
void FakeOutput::setManufacturer(const QString &manufacturer)
|
||||
{
|
||||
Information info = m_information;
|
||||
info.manufacturer = manufacturer;
|
||||
setInformation(info);
|
||||
}
|
||||
|
||||
void FakeOutput::setModel(const QString &model)
|
||||
{
|
||||
Information info = m_information;
|
||||
info.model = model;
|
||||
setInformation(info);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@ public:
|
|||
FakeOutput();
|
||||
|
||||
KWin::RenderLoop *renderLoop() const override;
|
||||
void setName(const QString &name);
|
||||
void setManufacturer(const QString &manufacturer);
|
||||
void setModel(const QString &model);
|
||||
void setMode(QSize size, uint32_t refreshRate);
|
||||
void setSubPixel(SubPixel subPixel);
|
||||
void setDpmsSupported(bool supported);
|
||||
|
|
|
@ -10,10 +10,14 @@
|
|||
|
||||
#include "qwayland-server-xdg-output-unstable-v1.h"
|
||||
|
||||
#include "core/output.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <QPointer>
|
||||
|
||||
using namespace KWin;
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
static const quint32 s_version = 3;
|
||||
|
@ -44,14 +48,11 @@ public:
|
|||
QSize size;
|
||||
QString name;
|
||||
QString description;
|
||||
bool dirty = false;
|
||||
bool doneOnce = false;
|
||||
QPointer<OutputInterface> output;
|
||||
XdgOutputV1Interface *const q;
|
||||
|
||||
void sendLogicalPosition(Resource *resource, const QPoint &position);
|
||||
void sendLogicalSize(Resource *resource, const QSize &size);
|
||||
|
||||
void sendLogicalPosition(Resource *resource);
|
||||
void sendLogicalSize(Resource *resource);
|
||||
void sendDone(Resource *resource);
|
||||
|
||||
protected:
|
||||
|
@ -116,76 +117,50 @@ XdgOutputV1Interface::XdgOutputV1Interface(OutputInterface *output, QObject *par
|
|||
: QObject(parent)
|
||||
, d(new XdgOutputV1InterfacePrivate(this, output))
|
||||
{
|
||||
const Output *handle = output->handle();
|
||||
|
||||
d->name = handle->name();
|
||||
d->description = handle->description();
|
||||
d->pos = handle->geometry().topLeft();
|
||||
d->size = handle->geometry().size();
|
||||
|
||||
connect(handle, &Output::geometryChanged, this, &XdgOutputV1Interface::update);
|
||||
}
|
||||
|
||||
XdgOutputV1Interface::~XdgOutputV1Interface()
|
||||
{
|
||||
}
|
||||
|
||||
void XdgOutputV1Interface::setLogicalSize(const QSize &size)
|
||||
void XdgOutputV1Interface::update()
|
||||
{
|
||||
if (size == d->size) {
|
||||
if (!d->output || d->output->isRemoved()) {
|
||||
return;
|
||||
}
|
||||
d->size = size;
|
||||
d->dirty = true;
|
||||
|
||||
const auto outputResources = d->resourceMap();
|
||||
for (auto resource : outputResources) {
|
||||
d->sendLogicalSize(resource, size);
|
||||
const QRect geometry = d->output->handle()->geometry();
|
||||
const auto resources = d->resourceMap();
|
||||
|
||||
if (d->pos != geometry.topLeft()) {
|
||||
d->pos = geometry.topLeft();
|
||||
for (auto resource : resources) {
|
||||
d->sendLogicalPosition(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QSize XdgOutputV1Interface::logicalSize() const
|
||||
{
|
||||
return d->size;
|
||||
}
|
||||
|
||||
void XdgOutputV1Interface::setLogicalPosition(const QPoint &pos)
|
||||
{
|
||||
if (pos == d->pos) {
|
||||
return;
|
||||
if (d->size != geometry.size()) {
|
||||
d->size = geometry.size();
|
||||
for (auto resource : resources) {
|
||||
d->sendLogicalSize(resource);
|
||||
}
|
||||
}
|
||||
d->pos = pos;
|
||||
d->dirty = true;
|
||||
|
||||
const auto outputResources = d->resourceMap();
|
||||
for (auto resource : outputResources) {
|
||||
d->sendLogicalPosition(resource, pos);
|
||||
}
|
||||
}
|
||||
|
||||
QPoint XdgOutputV1Interface::logicalPosition() const
|
||||
{
|
||||
return d->pos;
|
||||
}
|
||||
|
||||
void XdgOutputV1Interface::setName(const QString &name)
|
||||
{
|
||||
d->name = name;
|
||||
// this can only be set once before the client connects
|
||||
}
|
||||
|
||||
void XdgOutputV1Interface::setDescription(const QString &description)
|
||||
{
|
||||
d->description = description;
|
||||
// this can only be set once before the client connects
|
||||
}
|
||||
|
||||
void XdgOutputV1Interface::done()
|
||||
{
|
||||
d->doneOnce = true;
|
||||
if (!d->dirty) {
|
||||
return;
|
||||
}
|
||||
d->dirty = false;
|
||||
|
||||
const auto outputResources = d->resourceMap();
|
||||
for (auto resource : outputResources) {
|
||||
for (auto resource : resources) {
|
||||
if (wl_resource_get_version(resource->handle) < 3) {
|
||||
d->send_done(resource->handle);
|
||||
}
|
||||
}
|
||||
|
||||
d->output->scheduleDone();
|
||||
}
|
||||
|
||||
void XdgOutputV1InterfacePrivate::zxdg_output_v1_destroy(Resource *resource)
|
||||
|
@ -199,8 +174,8 @@ void XdgOutputV1InterfacePrivate::zxdg_output_v1_bind_resource(Resource *resourc
|
|||
return;
|
||||
}
|
||||
|
||||
sendLogicalPosition(resource, pos);
|
||||
sendLogicalSize(resource, size);
|
||||
sendLogicalPosition(resource);
|
||||
sendLogicalSize(resource);
|
||||
if (resource->version() >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) {
|
||||
send_name(resource->handle, name);
|
||||
}
|
||||
|
@ -211,25 +186,19 @@ void XdgOutputV1InterfacePrivate::zxdg_output_v1_bind_resource(Resource *resourc
|
|||
sendDone(resource);
|
||||
|
||||
ClientConnection *connection = output->display()->getConnection(resource->client());
|
||||
QObject::connect(connection, &ClientConnection::scaleOverrideChanged, q, &XdgOutputV1Interface::sendRefresh, Qt::UniqueConnection);
|
||||
QObject::connect(connection, &ClientConnection::scaleOverrideChanged, q, &XdgOutputV1Interface::resend, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void XdgOutputV1InterfacePrivate::sendLogicalSize(Resource *resource, const QSize &size)
|
||||
void XdgOutputV1InterfacePrivate::sendLogicalSize(Resource *resource)
|
||||
{
|
||||
if (!output || output->isRemoved()) {
|
||||
return;
|
||||
}
|
||||
ClientConnection *connection = output->display()->getConnection(resource->client());
|
||||
qreal scaleOverride = connection->scaleOverride();
|
||||
|
||||
send_logical_size(resource->handle, size.width() * scaleOverride, size.height() * scaleOverride);
|
||||
}
|
||||
|
||||
void XdgOutputV1InterfacePrivate::sendLogicalPosition(Resource *resource, const QPoint &pos)
|
||||
void XdgOutputV1InterfacePrivate::sendLogicalPosition(Resource *resource)
|
||||
{
|
||||
if (!output || output->isRemoved()) {
|
||||
return;
|
||||
}
|
||||
ClientConnection *connection = output->display()->getConnection(resource->client());
|
||||
qreal scaleOverride = connection->scaleOverride();
|
||||
|
||||
|
@ -238,10 +207,6 @@ void XdgOutputV1InterfacePrivate::sendLogicalPosition(Resource *resource, const
|
|||
|
||||
void XdgOutputV1InterfacePrivate::sendDone(Resource *resource)
|
||||
{
|
||||
if (!doneOnce || !output || output->isRemoved()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wl_resource_get_version(resource->handle) >= 3) {
|
||||
output->done(resource->client());
|
||||
} else {
|
||||
|
@ -249,16 +214,19 @@ void XdgOutputV1InterfacePrivate::sendDone(Resource *resource)
|
|||
}
|
||||
}
|
||||
|
||||
void XdgOutputV1Interface::sendRefresh()
|
||||
void XdgOutputV1Interface::resend()
|
||||
{
|
||||
auto changedConnection = qobject_cast<ClientConnection *>(sender());
|
||||
if (!d->output || d->output->isRemoved()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto changedConnection = qobject_cast<ClientConnection *>(sender());
|
||||
const auto outputResources = d->resourceMap();
|
||||
for (auto resource : outputResources) {
|
||||
ClientConnection *connection = d->output->display()->getConnection(resource->client());
|
||||
if (connection == changedConnection) {
|
||||
d->sendLogicalPosition(resource, d->pos);
|
||||
d->sendLogicalSize(resource, d->size);
|
||||
d->sendLogicalPosition(resource);
|
||||
d->sendLogicalSize(resource);
|
||||
d->sendDone(resource);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,58 +61,9 @@ class KWIN_EXPORT XdgOutputV1Interface : public QObject
|
|||
public:
|
||||
~XdgOutputV1Interface() override;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @brief Sets a short name of the output
|
||||
* This should be consistent across reboots for the same monitor
|
||||
* It should be set once before the first done call
|
||||
*/
|
||||
void setName(const QString &name);
|
||||
/**
|
||||
* The last set name
|
||||
*/
|
||||
void name() const;
|
||||
|
||||
/**
|
||||
* @brief Sets a longer description of the output
|
||||
* This should be consistent across reboots for the same monitor
|
||||
* It should be set once before the first done call
|
||||
*/
|
||||
void setDescription(const QString &description);
|
||||
/**
|
||||
* The last set description
|
||||
*/
|
||||
void description() const;
|
||||
|
||||
/**
|
||||
* Submit changes to all clients
|
||||
*/
|
||||
void done();
|
||||
|
||||
private:
|
||||
void sendRefresh();
|
||||
void resend();
|
||||
void update();
|
||||
|
||||
explicit XdgOutputV1Interface(OutputInterface *output, QObject *parent);
|
||||
friend class XdgOutputV1InterfacePrivate;
|
||||
|
|
|
@ -18,27 +18,6 @@ WaylandOutput::WaylandOutput(Output *output, QObject *parent)
|
|||
, m_waylandOutput(new KWaylandServer::OutputInterface(waylandServer()->display(), output))
|
||||
, m_xdgOutputV1(waylandServer()->xdgOutputManagerV1()->createXdgOutput(m_waylandOutput.get(), m_waylandOutput.get()))
|
||||
{
|
||||
const QRect geometry = m_platformOutput->geometry();
|
||||
m_xdgOutputV1->setName(output->name());
|
||||
m_xdgOutputV1->setDescription(output->description());
|
||||
m_xdgOutputV1->setLogicalPosition(geometry.topLeft());
|
||||
m_xdgOutputV1->setLogicalSize(geometry.size());
|
||||
|
||||
m_xdgOutputV1->done();
|
||||
m_waylandOutput->scheduleDone();
|
||||
|
||||
connect(output, &Output::geometryChanged, this, &WaylandOutput::update);
|
||||
}
|
||||
|
||||
void WaylandOutput::update()
|
||||
{
|
||||
const QRect geometry = m_platformOutput->geometry();
|
||||
|
||||
m_xdgOutputV1->setLogicalPosition(geometry.topLeft());
|
||||
m_xdgOutputV1->setLogicalSize(geometry.size());
|
||||
|
||||
m_xdgOutputV1->done();
|
||||
m_waylandOutput->scheduleDone();
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -21,9 +21,6 @@ class WaylandOutput : public QObject
|
|||
public:
|
||||
explicit WaylandOutput(Output *output, QObject *parent = nullptr);
|
||||
|
||||
private Q_SLOTS:
|
||||
void update();
|
||||
|
||||
private:
|
||||
Output *m_platformOutput;
|
||||
KWaylandServer::ScopedGlobalPointer<KWaylandServer::OutputInterface> m_waylandOutput;
|
||||
|
|
Loading…
Reference in a new issue