diff --git a/src/client/outputconfiguration.h b/src/client/outputconfiguration.h --- a/src/client/outputconfiguration.h +++ b/src/client/outputconfiguration.h @@ -228,6 +228,18 @@ */ void setColorCurves(OutputDevice *outputdevice, QVector red, QVector green, QVector blue); + + /** + * Logical size of this output. + * The changes done in this call will be recorded in the + * OutputDevice and only applied after apply() has been called. + * + * @param size the logical size for this output device. + * @param outputdevice the OutputDevice this change applies to. + * @since 5.66 + */ + void setLogicalSize(OutputDevice *outputdevice, const QSizeF &size); + /** * Ask the compositor to apply the changes. * This results in the compositor looking at all outputdevices and if they have diff --git a/src/client/outputconfiguration.cpp b/src/client/outputconfiguration.cpp --- a/src/client/outputconfiguration.cpp +++ b/src/client/outputconfiguration.cpp @@ -201,6 +201,14 @@ wl_array_release(&wlBlue); } +void OutputConfiguration::setLogicalSize(OutputDevice *outputdevice, const QSizeF &size) +{ + org_kde_kwin_outputdevice *od = outputdevice->output(); + org_kde_kwin_outputconfiguration_logical_size(d->outputconfiguration, od, + wl_fixed_from_double(size.width()), + wl_fixed_from_double(size.height())); +} + void OutputConfiguration::apply() { org_kde_kwin_outputconfiguration_apply(d->outputconfiguration); diff --git a/src/client/outputdevice.h b/src/client/outputdevice.h --- a/src/client/outputdevice.h +++ b/src/client/outputdevice.h @@ -95,6 +95,7 @@ Disabled = 0, Enabled = 1 }; + struct Mode { enum class Flag { None = 0, @@ -179,6 +180,12 @@ * Size in the current mode. **/ QSize pixelSize() const; + /** + * Size in compositor space. + **/ + QSizeF logicalSize() const; + + // TODO KF6: in geometry() replace pixel size with the logical size /** * The geometry of this OutputDevice in pixels. * Convenient for QRect(globalPosition(), pixelSize()). diff --git a/src/client/outputdevice.cpp b/src/client/outputdevice.cpp --- a/src/client/outputdevice.cpp +++ b/src/client/outputdevice.cpp @@ -48,6 +48,7 @@ EventQueue *queue = nullptr; QSize physicalSize; QPoint globalPosition; + QSizeF logicalSize = QSizeF(); QString manufacturer; QString model; qreal scale = 1.0; @@ -84,9 +85,12 @@ static void serialNumberCallback(void *data, org_kde_kwin_outputdevice *output, const char *serialNumber); static void eisaIdCallback(void *data, org_kde_kwin_outputdevice *output, const char *eisa); + static void logicalSizeCallback(void *data, org_kde_kwin_outputdevice *output, + wl_fixed_t width, wl_fixed_t height); void setPhysicalSize(const QSize &size); void setGlobalPosition(const QPoint &pos); + void setLogicalSize(const QSizeF &size); void setManufacturer(const QString &manufacturer); void setModel(const QString &model); void setScale(qreal scale); @@ -151,7 +155,8 @@ scaleFCallback, colorcurvesCallback, serialNumberCallback, - eisaIdCallback + eisaIdCallback, + logicalSizeCallback }; void OutputDevice::Private::geometryCallback(void *data, org_kde_kwin_outputdevice *output, @@ -313,6 +318,14 @@ } } +void OutputDevice::Private::logicalSizeCallback(void *data, org_kde_kwin_outputdevice *output, + wl_fixed_t width, wl_fixed_t height) +{ + auto o = reinterpret_cast(data); + Q_ASSERT(o->output == output); + o->setLogicalSize(QSizeF(wl_fixed_to_double(width), wl_fixed_to_double(height))); +} + void OutputDevice::Private::uuidCallback(void* data, org_kde_kwin_outputdevice* output, const char *uuid) { Q_UNUSED(output); @@ -417,6 +430,11 @@ scale = s; } +void OutputDevice::Private::setLogicalSize(const QSizeF &size) +{ + logicalSize = size; +} + QRect OutputDevice::geometry() const { if (d->currentMode == d->modes.end()) { @@ -545,6 +563,11 @@ return d->colorCurves; } +QSizeF OutputDevice::logicalSize() const +{ + return d->logicalSize; +} + void OutputDevice::destroy() { d->output.destroy(); diff --git a/src/client/protocols/output-management.xml b/src/client/protocols/output-management.xml --- a/src/client/protocols/output-management.xml +++ b/src/client/protocols/output-management.xml @@ -28,7 +28,7 @@ THIS SOFTWARE. ]]> - + This interface enables clients to set properties of output devices for screen configuration purposes via the server. To this end output devices are referenced @@ -80,7 +80,7 @@ - + outputconfiguration is a client-specific resource that can be used to ask the server to apply changes to available output devices. @@ -190,6 +190,26 @@ + + + This requests sets the logcial size the output is depicting explicitly. When using this + request changes to mode or scale will not influence the logical size. + + Arguments width and height must be positive, or both equal 0 or both equal -1. + + If both arguments are 0 the compositor should temporarily ignore the output as if it has + been switched off or disconnected. + + If both arguments are equal -1 the logical size is unset and the compositor is supposed + to calculate the output representation in the compositor space again from the output's + mode and scale. + + + + + + diff --git a/src/client/protocols/outputdevice.xml b/src/client/protocols/outputdevice.xml --- a/src/client/protocols/outputdevice.xml +++ b/src/client/protocols/outputdevice.xml @@ -29,7 +29,7 @@ ]]> - + An outputdevice describes a display device available to the compositor. outputdevice is similar to wl_output, but focuses on output @@ -280,14 +280,25 @@ + EISA ID of the monitor, sent on startup before the first done event. + + + Returns the logical size in compositor space. This event is always sent after + the logical size is changed and can be triggered by explicit logical size changes + in the configruation interface or implicitly through a scale or mode change. + + + + + diff --git a/src/client/registry.cpp b/src/client/registry.cpp --- a/src/client/registry.cpp +++ b/src/client/registry.cpp @@ -213,14 +213,14 @@ &Registry::fakeInputRemoved }}, {Registry::Interface::OutputManagement, { - 2, + 3, QByteArrayLiteral("org_kde_kwin_outputmanagement"), &org_kde_kwin_outputmanagement_interface, &Registry::outputManagementAnnounced, &Registry::outputManagementRemoved }}, {Registry::Interface::OutputDevice, { - 2, + 3, QByteArrayLiteral("org_kde_kwin_outputdevice"), &org_kde_kwin_outputdevice_interface, &Registry::outputDeviceAnnounced, diff --git a/src/server/outputchangeset.h b/src/server/outputchangeset.h --- a/src/server/outputchangeset.h +++ b/src/server/outputchangeset.h @@ -73,6 +73,11 @@ * @returns @c true if the colorCurves() property of the outputdevice has changed. */ bool colorCurvesChanged() const; + /** Whether the logicalSize() property of the outputdevice changed. + * @returns @c true if the logicalSize() property of the outputdevice has changed. + * @since 5.66 + */ + bool logicalSizeChanged() const; /** The new value for enabled. */ OutputDeviceInterface::Enablement enabled() const; @@ -97,6 +102,10 @@ * @since 5.XX */ OutputDeviceInterface::ColorCurves colorCurves() const; + /** The new value for logicalSize. + * @since 5.66 + */ + QSizeF logicalSize() const; private: friend class OutputConfigurationInterface; diff --git a/src/server/outputchangeset.cpp b/src/server/outputchangeset.cpp --- a/src/server/outputchangeset.cpp +++ b/src/server/outputchangeset.cpp @@ -35,6 +35,7 @@ , position(o->globalPosition()) , scale(o->scaleF()) , colorCurves(o->colorCurves()) + , logicalSize(o->logicalSize()) { } @@ -130,5 +131,17 @@ return d->colorCurves; } +bool OutputChangeSet::logicalSizeChanged() const +{ + Q_D(); + return d->logicalSize != d->o->logicalSize(); +} + +QSizeF OutputChangeSet::logicalSize() const +{ + Q_D(); + return d->logicalSize; +} + } } diff --git a/src/server/outputchangeset_p.h b/src/server/outputchangeset_p.h --- a/src/server/outputchangeset_p.h +++ b/src/server/outputchangeset_p.h @@ -42,6 +42,7 @@ QPoint position; qreal scale; OutputDeviceInterface::ColorCurves colorCurves; + QSizeF logicalSize; }; } } diff --git a/src/server/outputconfiguration_interface.cpp b/src/server/outputconfiguration_interface.cpp --- a/src/server/outputconfiguration_interface.cpp +++ b/src/server/outputconfiguration_interface.cpp @@ -55,7 +55,7 @@ OutputManagementInterface *outputManagement; QHash changes; - static const quint32 s_version = 2; + static const quint32 s_version = 3; private: static void enableCallback(wl_client *client, wl_resource *resource, @@ -74,6 +74,9 @@ static void colorcurvesCallback(wl_client *client, wl_resource *resource, wl_resource * outputdevice, wl_array *red, wl_array *green, wl_array *blue); + static void logicalSizeCallback(wl_client *client, wl_resource *resource, + wl_resource *outputdevice, + wl_fixed_t width, wl_fixed_t height); OutputConfigurationInterface *q_func() { return reinterpret_cast(q); @@ -91,7 +94,8 @@ applyCallback, scaleFCallback, colorcurvesCallback, - resourceDestroyedCallback + resourceDestroyedCallback, + logicalSizeCallback }; OutputConfigurationInterface::OutputConfigurationInterface(OutputManagementInterface* parent, wl_resource* parentResource): Resource(new Private(this, parent, parentResource)) @@ -253,6 +257,19 @@ s->pendingChanges(o)->d_func()->colorCurves = cc; } +void OutputConfigurationInterface::Private::logicalSizeCallback(wl_client *client, + wl_resource *resource, + wl_resource * outputdevice, + wl_fixed_t width, wl_fixed_t height) +{ + Q_UNUSED(client); + const QSizeF size(wl_fixed_to_double(width), wl_fixed_to_double(height)); + OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice); + auto s = cast(resource); + Q_ASSERT(s); + s->pendingChanges(o)->d_func()->logicalSize = size; +} + void OutputConfigurationInterface::Private::emitConfigurationChangeRequested() const { auto configinterface = reinterpret_cast(q); diff --git a/src/server/outputdevice_interface.h b/src/server/outputdevice_interface.h --- a/src/server/outputdevice_interface.h +++ b/src/server/outputdevice_interface.h @@ -83,6 +83,7 @@ Disabled = 0, Enabled = 1 }; + enum class ModeFlag { Current = 1, Preferred = 2 @@ -122,12 +123,35 @@ QList modes() const; int currentModeId() const; + /** + * Current explicitly set size in compositor space. An invalid size is returned in case no size + * was explicitly set. In this case the output siez in compositor space should be computed + * from pixelSize() and scaleF(). + * + * @return explicitly set logical size + * + * @see globalSize + * + * @since 5.66 + */ + QSizeF logicalSize() const; + QByteArray edid() const; OutputDeviceInterface::Enablement enabled() const; QByteArray uuid() const; void setPhysicalSize(const QSize &size); void setGlobalPosition(const QPoint &pos); + + /** + * Explicitly sets the logical size. + * + * @param size the explicitly set logical size + * @see logicalSize + * + * @since 5.66 + */ + void setLogicalSize(const QSizeF &size); void setManufacturer(const QString &manufacturer); void setModel(const QString &model); void setSerialNumber(const QString &serialNumber); @@ -162,6 +186,7 @@ Q_SIGNALS: void physicalSizeChanged(const QSize&); void globalPositionChanged(const QPoint&); + void logicalSizeChanged(); void manufacturerChanged(const QString&); void modelChanged(const QString&); void serialNumberChanged(const QString&); diff --git a/src/server/outputdevice_interface.cpp b/src/server/outputdevice_interface.cpp --- a/src/server/outputdevice_interface.cpp +++ b/src/server/outputdevice_interface.cpp @@ -50,6 +50,7 @@ void updateColorCurves(); void updateEisaId(); void updateSerialNumber(); + void updateLogicalSize(); void sendGeometry(wl_resource *resource); void sendMode(wl_resource *resource, const Mode &mode); @@ -61,9 +62,11 @@ void sendColorCurves(const ResourceData &data); void sendEisaId(const ResourceData &data); void sendSerialNumber(const ResourceData &data); + void sendLogicalSize(const ResourceData &data); QSize physicalSize; QPoint globalPosition; + QSizeF logicalSize; QString manufacturer = QStringLiteral("org.kde.kwin"); QString model = QStringLiteral("none"); qreal scale = 1.0; @@ -94,7 +97,7 @@ static QVector s_privates; }; -const quint32 OutputDeviceInterface::Private::s_version = 2; +const quint32 OutputDeviceInterface::Private::s_version = 3; QVector OutputDeviceInterface::Private::s_privates; @@ -152,6 +155,8 @@ connect(this, &OutputDeviceInterface::scaleFChanged, this, [d] { d->updateScale(); }); connect(this, &OutputDeviceInterface::scaleChanged, this, [d] { d->updateScale(); }); connect(this, &OutputDeviceInterface::colorCurvesChanged, this, [d] { d->updateColorCurves(); }); + connect(this, &OutputDeviceInterface::logicalSizeChanged, + this, [d] { d->updateLogicalSize(); }); } OutputDeviceInterface::~OutputDeviceInterface() = default; @@ -341,6 +346,7 @@ sendGeometry(resource); sendScale(r); + sendLogicalSize(r); sendColorCurves(r); sendEisaId(r); sendSerialNumber(r); @@ -420,6 +426,17 @@ } } +void OutputDeviceInterface::Private::sendLogicalSize(const ResourceData &data) +{ + if (wl_resource_get_version(data.resource) < + ORG_KDE_KWIN_OUTPUTDEVICE_LOGICAL_SIZE_SINCE_VERSION) { + return; + } + org_kde_kwin_outputdevice_send_logical_size(data.resource, + wl_fixed_from_double(logicalSize.width()), + wl_fixed_from_double(logicalSize.height())); +} + void OutputDeviceInterface::Private::sendColorCurves(const ResourceData &data) { if (data.version < ORG_KDE_KWIN_OUTPUTDEVICE_COLORCURVES_SINCE_VERSION) { @@ -483,6 +500,14 @@ } } +void OutputDeviceInterface::Private::updateLogicalSize() +{ + for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) { + sendLogicalSize(*it); + sendDone(*it); + } +} + void OutputDeviceInterface::Private::updateColorCurves() { for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) { @@ -543,6 +568,16 @@ emit scaleFChanged(d->scale); } +void OutputDeviceInterface::setLogicalSize(const QSizeF &size) +{ + Q_D(); + if (d->logicalSize == size) { + return; + } + d->logicalSize = size; + emit logicalSizeChanged(); +} + QSize OutputDeviceInterface::physicalSize() const { Q_D(); @@ -591,6 +626,11 @@ return d->scale; } +QSizeF OutputDeviceInterface::logicalSize() const +{ + Q_D(); + return d->logicalSize; +} OutputDeviceInterface::SubPixel OutputDeviceInterface::subPixel() const { diff --git a/src/server/outputmanagement_interface.cpp b/src/server/outputmanagement_interface.cpp --- a/src/server/outputmanagement_interface.cpp +++ b/src/server/outputmanagement_interface.cpp @@ -56,7 +56,7 @@ QHash configurationInterfaces; }; -const quint32 OutputManagementInterface::Private::s_version = 2; +const quint32 OutputManagementInterface::Private::s_version = 3; const struct org_kde_kwin_outputmanagement_interface OutputManagementInterface::Private::s_interface = { createConfigurationCallback