OutputManagement fractional scaling

Summary:
In order to have fractional scaling in kwin, we need to communicate it with
kscreen, which means changing the data type in our config protocols.

This introduces a new method on outputdevice and outputconfiguration
to set/request scale as a float.

wl_output is and should remain unchanged as an int

No urgent rush for reviewing/merging this as it's useless without other changes.

Test Plan: Attached unit tests

Reviewers: #kwin, romangg

Subscribers: romangg, zzag, kde-frameworks-devel

Tags: #frameworks

Differential Revision: https://phabricator.kde.org/D13601
This commit is contained in:
David Edmundson 2018-07-25 22:14:17 +02:00
parent 2a3b34ae6a
commit 961bcbde08
9 changed files with 152 additions and 15 deletions

View file

@ -44,6 +44,7 @@ private Q_SLOTS:
void testRegistry();
void testModeChanges();
void testScaleChange_legacy();
void testScaleChange();
void testSubPixel_data();
@ -310,7 +311,7 @@ void TestWaylandOutputDevice::testModeChanges()
QCOMPARE(output.pixelSize(), QSize(1280, 1024));
}
void TestWaylandOutputDevice::testScaleChange()
void TestWaylandOutputDevice::testScaleChange_legacy()
{
KWayland::Client::Registry registry;
QSignalSpy interfacesAnnouncedSpy(&registry, &KWayland::Client::Registry::interfacesAnnounced);
@ -336,12 +337,51 @@ void TestWaylandOutputDevice::testScaleChange()
m_serverOutputDevice->setScale(2);
QVERIFY(outputChanged.wait());
QCOMPARE(output.scale(), 2);
QCOMPARE(output.scaleF(), 2.0); //check we're forward compatiable
// change once more
outputChanged.clear();
m_serverOutputDevice->setScale(4);
QVERIFY(outputChanged.wait());
QCOMPARE(output.scale(), 4);
QCOMPARE(output.scaleF(), 4.0);
}
void TestWaylandOutputDevice::testScaleChange()
{
KWayland::Client::Registry registry;
QSignalSpy interfacesAnnouncedSpy(&registry, &KWayland::Client::Registry::interfacesAnnounced);
QVERIFY(interfacesAnnouncedSpy.isValid());
QSignalSpy announced(&registry, &KWayland::Client::Registry::outputDeviceAnnounced);
registry.setEventQueue(m_queue);
registry.create(m_connection->display());
QVERIFY(registry.isValid());
registry.setup();
wl_display_flush(m_connection->display());
QVERIFY(interfacesAnnouncedSpy.wait());
KWayland::Client::OutputDevice output;
QSignalSpy outputChanged(&output, &KWayland::Client::OutputDevice::done);
QVERIFY(outputChanged.isValid());
output.setup(registry.bindOutputDevice(announced.first().first().value<quint32>(), announced.first().last().value<quint32>()));
wl_display_flush(m_connection->display());
QVERIFY(outputChanged.wait());
QCOMPARE(output.scaleF(), 1.0);
// change the scale
outputChanged.clear();
m_serverOutputDevice->setScaleF(2.2);
QVERIFY(outputChanged.wait());
QCOMPARE(output.scale(), 2); //check backwards compatibility works
QCOMPARE(wl_fixed_from_double(output.scaleF()), wl_fixed_from_double(2.2));
// change once more
outputChanged.clear();
m_serverOutputDevice->setScaleF(4.9);
QVERIFY(outputChanged.wait());
QCOMPARE(output.scale(), 5);
QCOMPARE(wl_fixed_from_double(output.scaleF()), wl_fixed_from_double(4.9));
}
void TestWaylandOutputDevice::testSubPixel_data()

View file

@ -60,6 +60,7 @@ private Q_SLOTS:
void testFailed();
void testExampleConfig();
void testScale();
void testRemoval();
@ -229,7 +230,7 @@ void TestWaylandOutputManagement::applyPendingChanges()
outputdevice->setGlobalPosition(c->position());
}
if (c->scaleChanged()) {
outputdevice->setScale(c->scale());
outputdevice->setScaleF(c->scaleF());
}
}
}
@ -472,5 +473,34 @@ void TestWaylandOutputManagement::testExampleConfig()
QVERIFY(configAppliedSpy.wait(200));
}
void TestWaylandOutputManagement::testScale()
{
createConfig();
auto config = m_outputConfiguration;
KWayland::Client::OutputDevice *output = m_clientOutputs.first();
config->setScaleF(output, 2.3);
config->apply();
QSignalSpy configAppliedSpy(config, &OutputConfiguration::applied);
m_outputConfigurationInterface->setApplied();
QVERIFY(configAppliedSpy.isValid());
QVERIFY(configAppliedSpy.wait(200));
QCOMPARE(output->scale(), 2); //test backwards compatibility
QCOMPARE(wl_fixed_from_double(output->scaleF()), wl_fixed_from_double(2.3));
config->setScale(output, 3);
config->apply();
m_outputConfigurationInterface->setApplied();
QVERIFY(configAppliedSpy.isValid());
QVERIFY(configAppliedSpy.wait(200));
QCOMPARE(output->scale(), 3);
QCOMPARE(output->scaleF(), 3.0); //test fowards compatibility
}
QTEST_GUILESS_MAIN(TestWaylandOutputManagement)
#include "test_wayland_outputmanagement.moc"

View file

@ -102,10 +102,16 @@ QPoint OutputChangeSet::position() const
bool OutputChangeSet::scaleChanged() const
{
Q_D();
return d->scale != d->o->scale();
return !qFuzzyCompare(d->scale, d->o->scaleF());
}
int OutputChangeSet::scale() const
{
Q_D();
return qRound(d->scale);
}
qreal OutputChangeSet::scaleF() const
{
Q_D();
return d->scale;

View file

@ -78,8 +78,14 @@ public:
OutputDeviceInterface::Transform transform() const;
/** The new value for globalPosition. */
QPoint position() const;
/** The new value for scale. */
/** The new value for scale.
@deprecated see scaleF
*/
int scale() const;
/** The new value for scale.
* @since 5.XX
*/
qreal scaleF() const;
private:
friend class OutputConfigurationInterface;

View file

@ -40,9 +40,9 @@ namespace KWayland
int modeId;
OutputDeviceInterface::Transform transform;
QPoint position;
int scale;
qreal scale;
};
}
}
#endif
#endif

View file

@ -55,7 +55,7 @@ public:
OutputManagementInterface *outputManagement;
QHash<OutputDeviceInterface*, OutputChangeSet*> changes;
static const quint32 s_version = 1;
static const quint32 s_version = 2;
private:
static void enableCallback(wl_client *client, wl_resource *resource,
@ -69,6 +69,8 @@ private:
static void scaleCallback(wl_client *client, wl_resource *resource,
wl_resource * outputdevice, int32_t scale);
static void applyCallback(wl_client *client, wl_resource *resource);
static void scaleFCallback(wl_client *client, wl_resource *resource,
wl_resource * outputdevice, wl_fixed_t scale);
OutputConfigurationInterface *q_func() {
return reinterpret_cast<OutputConfigurationInterface *>(q);
@ -83,7 +85,8 @@ const struct org_kde_kwin_outputconfiguration_interface OutputConfigurationInter
transformCallback,
positionCallback,
scaleCallback,
applyCallback
applyCallback,
scaleFCallback
};
OutputConfigurationInterface::OutputConfigurationInterface(OutputManagementInterface* parent, wl_resource* parentResource): Resource(new Private(this, parent, parentResource))
@ -185,6 +188,22 @@ void OutputConfigurationInterface::Private::scaleCallback(wl_client *client, wl_
s->pendingChanges(o)->d_func()->scale = scale;
}
void OutputConfigurationInterface::Private::scaleFCallback(wl_client *client, wl_resource *resource, wl_resource * outputdevice, wl_fixed_t scale_fixed)
{
Q_UNUSED(client);
const qreal scale = wl_fixed_to_double(scale_fixed);
if (scale <= 0) {
qCWarning(KWAYLAND_SERVER) << "Requested to scale output device to" << scale << ", but I can't do that.";
return;
}
OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice);
auto s = cast<Private>(resource);
Q_ASSERT(s);
s->pendingChanges(o)->d_func()->scale = scale;
}
void OutputConfigurationInterface::Private::applyCallback(wl_client *client, wl_resource *resource)
{
Q_UNUSED(client);

View file

@ -54,7 +54,7 @@ public:
QPoint globalPosition;
QString manufacturer = QStringLiteral("org.kde.kwin");
QString model = QStringLiteral("none");
int scale = 1;
qreal scale = 1.0;
SubPixel subPixel = SubPixel::Unknown;
Transform transform = Transform::Normal;
QList<Mode> modes;
@ -80,7 +80,7 @@ private:
static QVector<Private*> s_privates;
};
const quint32 OutputDeviceInterface::Private::s_version = 1;
const quint32 OutputDeviceInterface::Private::s_version = 2;
QVector<OutputDeviceInterface::Private*> OutputDeviceInterface::Private::s_privates;
@ -138,7 +138,7 @@ OutputDeviceInterface::OutputDeviceInterface(Display *display, QObject *parent)
connect(this, &OutputDeviceInterface::globalPositionChanged, this, [this, d] { d->updateGeometry(); });
connect(this, &OutputDeviceInterface::modelChanged, this, [this, d] { d->updateGeometry(); });
connect(this, &OutputDeviceInterface::manufacturerChanged, this, [this, d] { d->updateGeometry(); });
connect(this, &OutputDeviceInterface::scaleChanged, this, [this, d] { d->updateScale(); });
connect(this, &OutputDeviceInterface::scaleFChanged, this, [this, d] { d->updateScale(); });
}
OutputDeviceInterface::~OutputDeviceInterface() = default;
@ -402,7 +402,11 @@ void OutputDeviceInterface::Private::sendGeometry(wl_resource *resource)
void OutputDeviceInterface::Private::sendScale(const ResourceData &data)
{
org_kde_kwin_outputdevice_send_scale(data.resource, scale);
if (wl_resource_get_version(data.resource) < ORG_KDE_KWIN_OUTPUTDEVICE_SCALEF_SINCE_VERSION) {
org_kde_kwin_outputdevice_send_scale(data.resource, qRound(scale));
} else {
org_kde_kwin_outputdevice_send_scalef(data.resource, wl_fixed_from_double(scale));
}
}
void OutputDeviceInterface::Private::sendDone(const ResourceData &data)
@ -441,12 +445,33 @@ SETTER(setPhysicalSize, const QSize&, physicalSize)
SETTER(setGlobalPosition, const QPoint&, globalPosition)
SETTER(setManufacturer, const QString&, manufacturer)
SETTER(setModel, const QString&, model)
SETTER(setScale, int, scale)
SETTER(setSubPixel, SubPixel, subPixel)
SETTER(setTransform, Transform, transform)
#undef SETTER
void OutputDeviceInterface::setScale(int scale)
{
Q_D();
if (d->scale == scale) {
return;
}
d->scale = scale;
emit scaleChanged(d->scale);
emit scaleFChanged(d->scale);
}
void OutputDeviceInterface::setScaleF(qreal scale)
{
Q_D();
if (qFuzzyCompare(d->scale, scale)) {
return;
}
d->scale = scale;
emit scaleChanged(qRound(d->scale));
emit scaleFChanged(d->scale);
}
QSize OutputDeviceInterface::physicalSize() const
{
Q_D();
@ -472,11 +497,18 @@ QString OutputDeviceInterface::model() const
}
int OutputDeviceInterface::scale() const
{
Q_D();
return qRound(d->scale);
}
qreal OutputDeviceInterface::scaleF() const
{
Q_D();
return d->scale;
}
OutputDeviceInterface::SubPixel OutputDeviceInterface::subPixel() const
{
Q_D();

View file

@ -53,7 +53,7 @@ class KWAYLANDSERVER_EXPORT OutputDeviceInterface : public Global
Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged)
Q_PROPERTY(QSize pixelSize READ pixelSize NOTIFY pixelSizeChanged)
Q_PROPERTY(int refreshRate READ refreshRate NOTIFY refreshRateChanged)
Q_PROPERTY(int scale READ scale WRITE setScale NOTIFY scaleChanged)
Q_PROPERTY(qreal scale READ scaleF WRITE setScaleF NOTIFY scaleFChanged)
Q_PROPERTY(QByteArray edid READ edid WRITE setEdid NOTIFY edidChanged)
Q_PROPERTY(OutputDeviceInterface::Enablement enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(QByteArray uuid READ uuid WRITE setUuid NOTIFY uuidChanged)
@ -100,6 +100,7 @@ public:
QSize pixelSize() const;
int refreshRate() const;
int scale() const;
qreal scaleF() const;
SubPixel subPixel() const;
Transform transform() const;
QList<Mode> modes() const;
@ -114,6 +115,7 @@ public:
void setManufacturer(const QString &manufacturer);
void setModel(const QString &model);
void setScale(int scale);
void setScaleF(qreal scale);
void setSubPixel(SubPixel subPixel);
void setTransform(Transform transform);
void addMode(Mode &mode);
@ -133,7 +135,9 @@ Q_SIGNALS:
void modelChanged(const QString&);
void pixelSizeChanged(const QSize&);
void refreshRateChanged(int);
//@deprecated see scaleChanged(real)
void scaleChanged(int);
void scaleFChanged(qreal);
void subPixelChanged(SubPixel);
void transformChanged(Transform);
void modesChanged();

View file

@ -57,7 +57,7 @@ private:
QHash<wl_resource*, OutputConfigurationInterface*> configurationInterfaces;
};
const quint32 OutputManagementInterface::Private::s_version = 1;
const quint32 OutputManagementInterface::Private::s_version = 2;
const struct org_kde_kwin_outputmanagement_interface OutputManagementInterface::Private::s_interface = {
createConfigurationCallback