diff --git a/src/abstract_wayland_output.cpp b/src/abstract_wayland_output.cpp index 1dd219d219..dcd9e6ee3e 100644 --- a/src/abstract_wayland_output.cpp +++ b/src/abstract_wayland_output.cpp @@ -37,7 +37,10 @@ AbstractWaylandOutput::Capabilities AbstractWaylandOutput::capabilities() const void AbstractWaylandOutput::setCapabilityInternal(Capability capability, bool on) { - m_capabilities.setFlag(capability, on); + if (static_cast(m_capabilities & capability) != on) { + m_capabilities.setFlag(capability, on); + emit capabilitiesChanged(); + } } QString AbstractWaylandOutput::name() const @@ -172,6 +175,10 @@ void AbstractWaylandOutput::applyChanges(const KWaylandServer::OutputChangeSet * setScale(changeSet->scaleF()); emitModeChanged = true; } + if (changeSet->overscanChanged()) { + qCDebug(KWIN_CORE) << "Setting overscan:" << changeSet->overscan(); + setOverscan(changeSet->overscan()); + } overallSizeCheckNeeded |= emitModeChanged; if (overallSizeCheckNeeded) { @@ -343,4 +350,22 @@ bool AbstractWaylandOutput::isBeingRecorded() return m_recorders; } +void AbstractWaylandOutput::setOverscanInternal(uint32_t overscan) +{ + if (m_overscan != overscan) { + m_overscan = overscan; + emit overscanChanged(); + } +} + +uint32_t AbstractWaylandOutput::overscan() const +{ + return m_overscan; +} + +void AbstractWaylandOutput::setOverscan(uint32_t overscan) +{ + Q_UNUSED(overscan); +} + } diff --git a/src/abstract_wayland_output.h b/src/abstract_wayland_output.h index b8e69807c7..00365b98b5 100644 --- a/src/abstract_wayland_output.h +++ b/src/abstract_wayland_output.h @@ -65,6 +65,7 @@ public: enum class Capability : uint { Dpms = 0x1, + Overscan = 0x2, }; Q_DECLARE_FLAGS(Capabilities, Capability) @@ -128,6 +129,9 @@ public: DpmsMode dpmsMode() const; virtual void setDpmsMode(DpmsMode mode); + uint32_t overscan() const; + virtual void setOverscan(uint32_t overscan); + /** * Returns a matrix that can translate into the display's coordinates system */ @@ -144,6 +148,8 @@ Q_SIGNALS: void scaleChanged(); void transformChanged(); void dpmsModeChanged(); + void capabilitiesChanged(); + void overscanChanged(); protected: void initialize(const QString &model, const QString &manufacturer, @@ -178,6 +184,7 @@ protected: void setDpmsModeInternal(DpmsMode dpmsMode); void setCapabilityInternal(Capability capability, bool on = true); void setSubPixelInternal(SubPixel subPixel); + void setOverscanInternal(uint32_t overscan); QSize orientateSize(const QSize &size) const; @@ -202,6 +209,7 @@ private: int m_recorders = 0; bool m_isEnabled = true; bool m_internal = false; + uint32_t m_overscan = 0; }; } diff --git a/src/plugins/platforms/drm/drm_object_connector.cpp b/src/plugins/platforms/drm/drm_object_connector.cpp index 16623d3f49..30062f3d97 100644 --- a/src/plugins/platforms/drm/drm_object_connector.cpp +++ b/src/plugins/platforms/drm/drm_object_connector.cpp @@ -62,6 +62,7 @@ bool DrmConnector::init() PropertyDefinition(QByteArrayLiteral("non-desktop")), PropertyDefinition(QByteArrayLiteral("DPMS")), PropertyDefinition(QByteArrayLiteral("EDID")), + PropertyDefinition(QByteArrayLiteral("overscan")), }, DRM_MODE_OBJECT_CONNECTOR)) { return false; } @@ -206,6 +207,22 @@ AbstractWaylandOutput::SubPixel DrmConnector::subpixel() const } } +bool DrmConnector::hasOverscan() const +{ + return m_props[static_cast(PropertyIndex::Overscan)]; +} +uint32_t DrmConnector::overscan() const +{ + if (const auto &prop = m_props[static_cast(PropertyIndex::Overscan)]) { + return prop->value(); + } + return 0; +} + +void DrmConnector::setOverscan(uint32_t overscan) +{ + setValue(PropertyIndex::Overscan, overscan); +} } diff --git a/src/plugins/platforms/drm/drm_object_connector.h b/src/plugins/platforms/drm/drm_object_connector.h index a69ed34611..6587d12f13 100644 --- a/src/plugins/platforms/drm/drm_object_connector.h +++ b/src/plugins/platforms/drm/drm_object_connector.h @@ -35,6 +35,7 @@ public: NonDesktop = 1, Dpms = 2, Edid = 3, + Overscan = 4, Count }; @@ -82,6 +83,10 @@ public: AbstractWaylandOutput::SubPixel subpixel() const; + bool hasOverscan() const; + uint32_t overscan() const; + void setOverscan(uint32_t overscan); + private: DrmScopedPointer m_conn; QVector m_encoders; diff --git a/src/plugins/platforms/drm/drm_output.cpp b/src/plugins/platforms/drm/drm_output.cpp index 4e4132c9d9..58baa9e094 100644 --- a/src/plugins/platforms/drm/drm_output.cpp +++ b/src/plugins/platforms/drm/drm_output.cpp @@ -158,6 +158,10 @@ bool DrmOutput::init() setSubPixelInternal(m_conn->subpixel()); setInternal(m_conn->isInternal()); setCapabilityInternal(Capability::Dpms); + if (m_conn->hasOverscan()) { + setCapabilityInternal(Capability::Overscan); + setOverscanInternal(m_conn->overscan()); + } initOutputDevice(); m_pipeline = new DrmPipeline(this, m_gpu, m_conn, m_crtc, m_primaryPlane, m_cursorPlane); @@ -417,4 +421,12 @@ bool DrmOutput::setGammaRamp(const GammaRamp &gamma) return m_pipeline->setGammaRamp(gamma); } +void DrmOutput::setOverscan(uint32_t overscan) +{ + if (m_conn->hasOverscan() && overscan <= 100) { + m_conn->setOverscan(overscan); + setOverscanInternal(overscan); + } +} + } diff --git a/src/plugins/platforms/drm/drm_output.h b/src/plugins/platforms/drm/drm_output.h index 8e01239d33..a6d927103e 100644 --- a/src/plugins/platforms/drm/drm_output.h +++ b/src/plugins/platforms/drm/drm_output.h @@ -102,6 +102,7 @@ private: int gammaRampSize() const override; bool setGammaRamp(const GammaRamp &gamma) override; + void setOverscan(uint32_t overscan) override; DrmBackend *m_backend; DrmGpu *m_gpu; diff --git a/src/waylandoutputdevice.cpp b/src/waylandoutputdevice.cpp index 355f82890f..d589a30dfa 100644 --- a/src/waylandoutputdevice.cpp +++ b/src/waylandoutputdevice.cpp @@ -20,6 +20,15 @@ static KWaylandServer::OutputDeviceInterface::SubPixel kwinSubPixelToOutputDevic return static_cast(subPixel); } +static KWaylandServer::OutputDeviceInterface::Capabilities kwinCapabilitiesToOutputDeviceCapabilities(AbstractWaylandOutput::Capabilities caps) +{ + KWaylandServer::OutputDeviceInterface::Capabilities ret; + if (caps & AbstractWaylandOutput::Capability::Overscan) { + ret |= KWaylandServer::OutputDeviceInterface::Capability::Overscan; + } + return ret; +} + WaylandOutputDevice::WaylandOutputDevice(AbstractWaylandOutput *output, QObject *parent) : QObject(parent) , m_platformOutput(output) @@ -36,6 +45,8 @@ WaylandOutputDevice::WaylandOutputDevice(AbstractWaylandOutput *output, QObject m_outputDevice->setEisaId(output->eisaId()); m_outputDevice->setSerialNumber(output->serialNumber()); m_outputDevice->setSubPixel(kwinSubPixelToOutputDeviceSubPixel(output->subPixel())); + m_outputDevice->setOverscan(output->overscan()); + m_outputDevice->setCapabilities(kwinCapabilitiesToOutputDeviceCapabilities(output->capabilities())); const auto modes = output->modes(); for (const AbstractWaylandOutput::Mode &mode : modes) { @@ -64,6 +75,10 @@ WaylandOutputDevice::WaylandOutputDevice(AbstractWaylandOutput *output, QObject this, &WaylandOutputDevice::handleTransformChanged); connect(output, &AbstractWaylandOutput::modeChanged, this, &WaylandOutputDevice::handleModeChanged); + connect(output, &AbstractWaylandOutput::capabilitiesChanged, + this, &WaylandOutputDevice::handleCapabilitiesChanged); + connect(output, &AbstractWaylandOutput::overscanChanged, + this, &WaylandOutputDevice::handleOverscanChanged); } void WaylandOutputDevice::handleGeometryChanged() @@ -95,4 +110,14 @@ void WaylandOutputDevice::handleModeChanged() m_outputDevice->setCurrentMode(m_platformOutput->modeSize(), m_platformOutput->refreshRate()); } +void WaylandOutputDevice::handleCapabilitiesChanged() +{ + m_outputDevice->setCapabilities(kwinCapabilitiesToOutputDeviceCapabilities(m_platformOutput->capabilities())); +} + +void WaylandOutputDevice::handleOverscanChanged() +{ + m_outputDevice->setOverscan(m_platformOutput->overscan()); +} + } // namespace KWin diff --git a/src/waylandoutputdevice.h b/src/waylandoutputdevice.h index 2e38157fb9..13725e67bb 100644 --- a/src/waylandoutputdevice.h +++ b/src/waylandoutputdevice.h @@ -26,6 +26,8 @@ private Q_SLOTS: void handleEnabledChanged(); void handleTransformChanged(); void handleModeChanged(); + void handleCapabilitiesChanged(); + void handleOverscanChanged(); private: AbstractWaylandOutput *m_platformOutput;