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 "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);

View file

@ -38,6 +38,9 @@ public:
void addDamage(const QRegion &region);
void resetDamage();
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal dpr);
Q_SIGNALS:
void damaged(const QRegion &region);
@ -58,6 +61,7 @@ protected:
private:
QPointer<Decoration::DecoratedClientImpl> 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<AbstractOutput> m_output;
QPointer<KDecoration2::Decoration> m_decoration;
QScopedPointer<DecorationRenderer> m_renderer;
};

View file

@ -1661,22 +1661,21 @@ void SceneOpenGLDecorationRenderer::render(const QRegion &region)
}
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;

View file

@ -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)
{

View file

@ -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

View file

@ -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<KWaylandServer::SurfaceInterface> m_surface;
// when adding new data members, check also copyToDeleted()
qreal m_screenScale = 1.0;
qreal m_opacity = 1.0;
int m_stackingOrder = 0;
};