diff --git a/src/decorationitem.cpp b/src/decorationitem.cpp index 3d1df393f8..73aa4313d9 100644 --- a/src/decorationitem.cpp +++ b/src/decorationitem.cpp @@ -7,6 +7,7 @@ #include "decorationitem.h" #include "abstract_client.h" +#include "abstract_output.h" #include "composite.h" #include "decorations/decoratedclient.h" #include "deleted.h" @@ -28,8 +29,6 @@ DecorationRenderer::DecorationRenderer(Decoration::DecoratedClientImpl *client) connect(client->decoration(), &KDecoration2::Decoration::damaged, this, &DecorationRenderer::addDamage); - connect(client->client(), &AbstractClient::screenScaleChanged, - this, &DecorationRenderer::invalidate); connect(client->decoration(), &KDecoration2::Decoration::bordersChanged, this, &DecorationRenderer::invalidate); connect(client->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged, @@ -67,10 +66,22 @@ void DecorationRenderer::resetDamage() m_damage = QRegion(); } +qreal DecorationRenderer::devicePixelRatio() const +{ + return m_devicePixelRatio; +} + +void DecorationRenderer::setDevicePixelRatio(qreal dpr) +{ + if (m_devicePixelRatio != dpr) { + m_devicePixelRatio = dpr; + invalidate(); + } +} + QImage DecorationRenderer::renderToImage(const QRect &geo) { Q_ASSERT(m_client); - auto dpr = client()->client()->screenScale(); // Guess the pixel format of the X pixmap into which the QImage will be copied. QImage::Format format; @@ -89,8 +100,8 @@ QImage DecorationRenderer::renderToImage(const QRect &geo) break; }; - QImage image(geo.width() * dpr, geo.height() * dpr, format); - image.setDevicePixelRatio(dpr); + QImage image(geo.width() * m_devicePixelRatio, geo.height() * m_devicePixelRatio, format); + image.setDevicePixelRatio(m_devicePixelRatio); image.fill(Qt::transparent); QPainter p(&image); p.setRenderHint(QPainter::Antialiasing); @@ -115,9 +126,9 @@ DecorationItem::DecorationItem(KDecoration2::Decoration *decoration, AbstractCli this, &DecorationItem::handleFrameGeometryChanged); connect(window, &Toplevel::windowClosed, this, &DecorationItem::handleWindowClosed); + connect(window, &Toplevel::screenChanged, + this, &DecorationItem::handleOutputChanged); - connect(window, &Toplevel::screenScaleChanged, - this, &DecorationItem::discardQuads); connect(decoration, &KDecoration2::Decoration::bordersChanged, this, &DecorationItem::discardQuads); @@ -125,6 +136,7 @@ DecorationItem::DecorationItem(KDecoration2::Decoration *decoration, AbstractCli this, &DecorationItem::scheduleRepaint); setSize(window->size()); + handleOutputChanged(); } void DecorationItem::preprocess() @@ -136,6 +148,29 @@ void DecorationItem::preprocess() } } +void DecorationItem::handleOutputChanged() +{ + if (m_output) { + disconnect(m_output, &AbstractOutput::scaleChanged, this, &DecorationItem::handleOutputScaleChanged); + } + + m_output = m_window->output(); + + if (m_output) { + handleOutputScaleChanged(); + connect(m_output, &AbstractOutput::scaleChanged, this, &DecorationItem::handleOutputScaleChanged); + } +} + +void DecorationItem::handleOutputScaleChanged() +{ + const qreal dpr = m_output->scale(); + if (m_renderer->devicePixelRatio() != dpr) { + m_renderer->setDevicePixelRatio(dpr); + discardQuads(); + } +} + void DecorationItem::handleFrameGeometryChanged() { setSize(m_window->size()); @@ -169,7 +204,7 @@ WindowQuadList DecorationItem::buildQuads() const deleted->layoutDecorationRects(rects[0], rects[1], rects[2], rects[3]); } - const qreal textureScale = m_window->screenScale(); + const qreal textureScale = m_renderer->devicePixelRatio(); const int padding = 1; const QPoint topSpritePosition(padding, padding); diff --git a/src/decorationitem.h b/src/decorationitem.h index 3adc05f7f6..24ed389734 100644 --- a/src/decorationitem.h +++ b/src/decorationitem.h @@ -38,6 +38,9 @@ public: void addDamage(const QRegion ®ion); void resetDamage(); + qreal devicePixelRatio() const; + void setDevicePixelRatio(qreal dpr); + Q_SIGNALS: void damaged(const QRegion ®ion); @@ -58,6 +61,7 @@ protected: private: QPointer m_client; QRegion m_damage; + qreal m_devicePixelRatio = 1; bool m_imageSizesDirty; }; @@ -76,6 +80,8 @@ public: private Q_SLOTS: void handleFrameGeometryChanged(); void handleWindowClosed(Toplevel *original, Deleted *deleted); + void handleOutputChanged(); + void handleOutputScaleChanged(); protected: void preprocess() override; @@ -83,6 +89,7 @@ protected: private: Toplevel *m_window; + QPointer m_output; QPointer m_decoration; QScopedPointer m_renderer; }; diff --git a/src/scenes/opengl/scene_opengl.cpp b/src/scenes/opengl/scene_opengl.cpp index 98c1776606..1a86f1d9e2 100644 --- a/src/scenes/opengl/scene_opengl.cpp +++ b/src/scenes/opengl/scene_opengl.cpp @@ -1661,22 +1661,21 @@ void SceneOpenGLDecorationRenderer::render(const QRegion ®ion) } QRect viewport = geo.translated(-rect.x(), -rect.y()); - const qreal devicePixelRatio = client()->client()->screenScale(); - QImage image(rect.size() * devicePixelRatio, QImage::Format_ARGB32_Premultiplied); - image.setDevicePixelRatio(devicePixelRatio); + QImage image(rect.size() * devicePixelRatio(), QImage::Format_ARGB32_Premultiplied); + image.setDevicePixelRatio(devicePixelRatio()); image.fill(Qt::transparent); QPainter painter(&image); painter.setRenderHint(QPainter::Antialiasing); - painter.setViewport(QRect(viewport.topLeft(), viewport.size() * devicePixelRatio)); + painter.setViewport(QRect(viewport.topLeft(), viewport.size() * devicePixelRatio())); painter.setWindow(QRect(geo.topLeft(), geo.size() * qPainterEffectiveDevicePixelRatio(&painter))); painter.setClipRect(geo); renderToPainter(&painter, geo); painter.end(); - const QRect viewportScaled(viewport.topLeft() * devicePixelRatio, viewport.size() * devicePixelRatio); - const bool isIntegerScaling = qFuzzyCompare(devicePixelRatio, std::ceil(devicePixelRatio)); + const QRect viewportScaled(viewport.topLeft() * devicePixelRatio(), viewport.size() * devicePixelRatio()); + const bool isIntegerScaling = qFuzzyCompare(devicePixelRatio(), std::ceil(devicePixelRatio())); clamp(image, isIntegerScaling ? viewportScaled : viewportScaled.marginsRemoved({1, 1, 1, 1})); if (rotated) { @@ -1725,7 +1724,7 @@ void SceneOpenGLDecorationRenderer::resizeTexture() size.rwidth() = align(size.width(), 128); - size *= client()->client()->screenScale(); + size *= devicePixelRatio(); if (m_texture && m_texture->size() == size) return; diff --git a/src/scenes/qpainter/scene_qpainter.cpp b/src/scenes/qpainter/scene_qpainter.cpp index 520bc31b4d..ebca131187 100644 --- a/src/scenes/qpainter/scene_qpainter.cpp +++ b/src/scenes/qpainter/scene_qpainter.cpp @@ -466,7 +466,7 @@ void SceneQPainterDecorationRenderer::resizeImages() client()->client()->layoutDecorationRects(left, top, right, bottom); auto checkAndCreate = [this](int index, const QSize &size) { - auto dpr = client()->client()->screenScale(); + auto dpr = devicePixelRatio(); if (m_images[index].size() != size * dpr || m_images[index].devicePixelRatio() != dpr) { diff --git a/src/toplevel.cpp b/src/toplevel.cpp index d4768db966..698f6998e5 100644 --- a/src/toplevel.cpp +++ b/src/toplevel.cpp @@ -411,17 +411,6 @@ void Toplevel::setOutput(AbstractOutput *output) m_output = output; Q_EMIT screenChanged(); } - - qreal newScale = m_output->scale(); - if (newScale != m_screenScale) { - m_screenScale = newScale; - Q_EMIT screenScaleChanged(); - } -} - -qreal Toplevel::screenScale() const -{ - return m_screenScale; } bool Toplevel::isOnActiveOutput() const diff --git a/src/toplevel.h b/src/toplevel.h index ced4132048..8ea1f96a2a 100644 --- a/src/toplevel.h +++ b/src/toplevel.h @@ -344,12 +344,6 @@ public: int screen() const; // the screen where the center is AbstractOutput *output() const; void setOutput(AbstractOutput *output); - /** - * The scale of the screen this window is currently on - * @note The buffer scale can be different. - * @since 5.12 - */ - qreal screenScale() const; // virtual QPoint clientPos() const = 0; // inside of geometry() QSize clientSize() const; /** @@ -616,13 +610,6 @@ Q_SIGNALS: */ void surfaceChanged(); - /* - * Emitted when the client's screen changes onto a screen of a different scale - * or the screen we're on changes - * @since 5.12 - */ - void screenScaleChanged(); - /** * Emitted whenever the client's shadow changes. * @since 5.15 @@ -717,7 +704,6 @@ private: quint32 m_pendingSurfaceId = 0; QPointer m_surface; // when adding new data members, check also copyToDeleted() - qreal m_screenScale = 1.0; qreal m_opacity = 1.0; int m_stackingOrder = 0; };