Kill Toplevel::screenScale()

Tracking AbstractOutput properties in Toplevel is not extensible. Since
DecorationItem is the only one who needs Toplevel::screenScale(), make
it track the output device pixel ratio.
This commit is contained in:
Vlad Zahorodnii 2021-11-26 11:18:19 +02:00
parent 1f318a2245
commit cbad78a360
6 changed files with 57 additions and 41 deletions

View file

@ -7,6 +7,7 @@
#include "decorationitem.h" #include "decorationitem.h"
#include "abstract_client.h" #include "abstract_client.h"
#include "abstract_output.h"
#include "composite.h" #include "composite.h"
#include "decorations/decoratedclient.h" #include "decorations/decoratedclient.h"
#include "deleted.h" #include "deleted.h"
@ -28,8 +29,6 @@ DecorationRenderer::DecorationRenderer(Decoration::DecoratedClientImpl *client)
connect(client->decoration(), &KDecoration2::Decoration::damaged, connect(client->decoration(), &KDecoration2::Decoration::damaged,
this, &DecorationRenderer::addDamage); this, &DecorationRenderer::addDamage);
connect(client->client(), &AbstractClient::screenScaleChanged,
this, &DecorationRenderer::invalidate);
connect(client->decoration(), &KDecoration2::Decoration::bordersChanged, connect(client->decoration(), &KDecoration2::Decoration::bordersChanged,
this, &DecorationRenderer::invalidate); this, &DecorationRenderer::invalidate);
connect(client->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged, connect(client->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged,
@ -67,10 +66,22 @@ void DecorationRenderer::resetDamage()
m_damage = QRegion(); 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) QImage DecorationRenderer::renderToImage(const QRect &geo)
{ {
Q_ASSERT(m_client); Q_ASSERT(m_client);
auto dpr = client()->client()->screenScale();
// Guess the pixel format of the X pixmap into which the QImage will be copied. // Guess the pixel format of the X pixmap into which the QImage will be copied.
QImage::Format format; QImage::Format format;
@ -89,8 +100,8 @@ QImage DecorationRenderer::renderToImage(const QRect &geo)
break; break;
}; };
QImage image(geo.width() * dpr, geo.height() * dpr, format); QImage image(geo.width() * m_devicePixelRatio, geo.height() * m_devicePixelRatio, format);
image.setDevicePixelRatio(dpr); image.setDevicePixelRatio(m_devicePixelRatio);
image.fill(Qt::transparent); image.fill(Qt::transparent);
QPainter p(&image); QPainter p(&image);
p.setRenderHint(QPainter::Antialiasing); p.setRenderHint(QPainter::Antialiasing);
@ -115,9 +126,9 @@ DecorationItem::DecorationItem(KDecoration2::Decoration *decoration, AbstractCli
this, &DecorationItem::handleFrameGeometryChanged); this, &DecorationItem::handleFrameGeometryChanged);
connect(window, &Toplevel::windowClosed, connect(window, &Toplevel::windowClosed,
this, &DecorationItem::handleWindowClosed); this, &DecorationItem::handleWindowClosed);
connect(window, &Toplevel::screenChanged,
this, &DecorationItem::handleOutputChanged);
connect(window, &Toplevel::screenScaleChanged,
this, &DecorationItem::discardQuads);
connect(decoration, &KDecoration2::Decoration::bordersChanged, connect(decoration, &KDecoration2::Decoration::bordersChanged,
this, &DecorationItem::discardQuads); this, &DecorationItem::discardQuads);
@ -125,6 +136,7 @@ DecorationItem::DecorationItem(KDecoration2::Decoration *decoration, AbstractCli
this, &DecorationItem::scheduleRepaint); this, &DecorationItem::scheduleRepaint);
setSize(window->size()); setSize(window->size());
handleOutputChanged();
} }
void DecorationItem::preprocess() 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() void DecorationItem::handleFrameGeometryChanged()
{ {
setSize(m_window->size()); setSize(m_window->size());
@ -169,7 +204,7 @@ WindowQuadList DecorationItem::buildQuads() const
deleted->layoutDecorationRects(rects[0], rects[1], rects[2], rects[3]); 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 int padding = 1;
const QPoint topSpritePosition(padding, padding); const QPoint topSpritePosition(padding, padding);

View file

@ -38,6 +38,9 @@ public:
void addDamage(const QRegion &region); void addDamage(const QRegion &region);
void resetDamage(); void resetDamage();
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal dpr);
Q_SIGNALS: Q_SIGNALS:
void damaged(const QRegion &region); void damaged(const QRegion &region);
@ -58,6 +61,7 @@ protected:
private: private:
QPointer<Decoration::DecoratedClientImpl> m_client; QPointer<Decoration::DecoratedClientImpl> m_client;
QRegion m_damage; QRegion m_damage;
qreal m_devicePixelRatio = 1;
bool m_imageSizesDirty; bool m_imageSizesDirty;
}; };
@ -76,6 +80,8 @@ public:
private Q_SLOTS: private Q_SLOTS:
void handleFrameGeometryChanged(); void handleFrameGeometryChanged();
void handleWindowClosed(Toplevel *original, Deleted *deleted); void handleWindowClosed(Toplevel *original, Deleted *deleted);
void handleOutputChanged();
void handleOutputScaleChanged();
protected: protected:
void preprocess() override; void preprocess() override;
@ -83,6 +89,7 @@ protected:
private: private:
Toplevel *m_window; Toplevel *m_window;
QPointer<AbstractOutput> m_output;
QPointer<KDecoration2::Decoration> m_decoration; QPointer<KDecoration2::Decoration> m_decoration;
QScopedPointer<DecorationRenderer> m_renderer; QScopedPointer<DecorationRenderer> m_renderer;
}; };

View file

@ -1661,22 +1661,21 @@ void SceneOpenGLDecorationRenderer::render(const QRegion &region)
} }
QRect viewport = geo.translated(-rect.x(), -rect.y()); QRect viewport = geo.translated(-rect.x(), -rect.y());
const qreal devicePixelRatio = client()->client()->screenScale();
QImage image(rect.size() * devicePixelRatio, QImage::Format_ARGB32_Premultiplied); QImage image(rect.size() * devicePixelRatio(), QImage::Format_ARGB32_Premultiplied);
image.setDevicePixelRatio(devicePixelRatio); image.setDevicePixelRatio(devicePixelRatio());
image.fill(Qt::transparent); image.fill(Qt::transparent);
QPainter painter(&image); QPainter painter(&image);
painter.setRenderHint(QPainter::Antialiasing); 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.setWindow(QRect(geo.topLeft(), geo.size() * qPainterEffectiveDevicePixelRatio(&painter)));
painter.setClipRect(geo); painter.setClipRect(geo);
renderToPainter(&painter, geo); renderToPainter(&painter, geo);
painter.end(); painter.end();
const QRect viewportScaled(viewport.topLeft() * devicePixelRatio, viewport.size() * devicePixelRatio); const QRect viewportScaled(viewport.topLeft() * devicePixelRatio(), viewport.size() * devicePixelRatio());
const bool isIntegerScaling = qFuzzyCompare(devicePixelRatio, std::ceil(devicePixelRatio)); const bool isIntegerScaling = qFuzzyCompare(devicePixelRatio(), std::ceil(devicePixelRatio()));
clamp(image, isIntegerScaling ? viewportScaled : viewportScaled.marginsRemoved({1, 1, 1, 1})); clamp(image, isIntegerScaling ? viewportScaled : viewportScaled.marginsRemoved({1, 1, 1, 1}));
if (rotated) { if (rotated) {
@ -1725,7 +1724,7 @@ void SceneOpenGLDecorationRenderer::resizeTexture()
size.rwidth() = align(size.width(), 128); size.rwidth() = align(size.width(), 128);
size *= client()->client()->screenScale(); size *= devicePixelRatio();
if (m_texture && m_texture->size() == size) if (m_texture && m_texture->size() == size)
return; return;

View file

@ -466,7 +466,7 @@ void SceneQPainterDecorationRenderer::resizeImages()
client()->client()->layoutDecorationRects(left, top, right, bottom); client()->client()->layoutDecorationRects(left, top, right, bottom);
auto checkAndCreate = [this](int index, const QSize &size) { auto checkAndCreate = [this](int index, const QSize &size) {
auto dpr = client()->client()->screenScale(); auto dpr = devicePixelRatio();
if (m_images[index].size() != size * dpr || if (m_images[index].size() != size * dpr ||
m_images[index].devicePixelRatio() != dpr) m_images[index].devicePixelRatio() != dpr)
{ {

View file

@ -411,17 +411,6 @@ void Toplevel::setOutput(AbstractOutput *output)
m_output = output; m_output = output;
Q_EMIT screenChanged(); 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 bool Toplevel::isOnActiveOutput() const

View file

@ -344,12 +344,6 @@ public:
int screen() const; // the screen where the center is int screen() const; // the screen where the center is
AbstractOutput *output() const; AbstractOutput *output() const;
void setOutput(AbstractOutput *output); 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() virtual QPoint clientPos() const = 0; // inside of geometry()
QSize clientSize() const; QSize clientSize() const;
/** /**
@ -616,13 +610,6 @@ Q_SIGNALS:
*/ */
void surfaceChanged(); 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. * Emitted whenever the client's shadow changes.
* @since 5.15 * @since 5.15
@ -717,7 +704,6 @@ private:
quint32 m_pendingSurfaceId = 0; quint32 m_pendingSurfaceId = 0;
QPointer<KWaylandServer::SurfaceInterface> m_surface; QPointer<KWaylandServer::SurfaceInterface> m_surface;
// when adding new data members, check also copyToDeleted() // when adding new data members, check also copyToDeleted()
qreal m_screenScale = 1.0;
qreal m_opacity = 1.0; qreal m_opacity = 1.0;
int m_stackingOrder = 0; int m_stackingOrder = 0;
}; };