Commit 7e6721ec authored by David Edmundson's avatar David Edmundson

Scaled decorations in QPainter mode

Under wayland we support high DPI putting by putting a separation
between the logical co-ordinate system and the resolution of rendered

I didn't include window decorations in the previous wayland scaling
patchset. They were drawn them at a standard resolution, which is
implicitly scaled up.

This uses the Qt scaling, meaning oxygen and breeze (and others) get
perfect high DPI support with zero client changes.

Like the window scaling this handles any combination of a 2x scaled
decoration being rendered on a 1x screen or vice versa.

CCBUG: 384765

Test Plan:
Had two screens of different scales
It was the right size on both (as before)
Was super-sharp on the fancy screen

Reviewers: #plasma, hetzenecker, graesslin

Reviewed By: #plasma, graesslin

Subscribers: ngraham, graesslin, plasma-devel, kwin, #kwin

Tags: #plasma

Differential Revision:
parent 2e371f96
......@@ -20,6 +20,7 @@ along with this program. If not, see <>.
#include "decorationrenderer.h"
#include "decoratedclient.h"
#include "deleted.h"
#include "abstract_client.h"
#include <KDecoration2/Decoration>
#include <KDecoration2/DecoratedClient>
......@@ -38,6 +39,9 @@ Renderer::Renderer(DecoratedClientImpl *client)
, m_imageSizesDirty(true)
auto markImageSizesDirty = [this]{ m_imageSizesDirty = true; };
if (kwinApp()->operationMode() != Application::OperationModeX11) {
connect(client->client(), &AbstractClient::screenChanged, this, markImageSizesDirty);
connect(client->decoration(), &KDecoration2::Decoration::bordersChanged, this, markImageSizesDirty);
connect(client->decoratedClient(), &KDecoration2::DecoratedClient::widthChanged, this, markImageSizesDirty);
connect(client->decoratedClient(), &KDecoration2::DecoratedClient::heightChanged, this, markImageSizesDirty);
......@@ -594,10 +594,14 @@ void SceneQPainterDecorationRenderer::render()
const QRect top(QPoint(0, 0), m_images[int(DecorationPart::Top)].size());
const QRect left(QPoint(0, top.height()), m_images[int(DecorationPart::Left)].size());
const QRect right(QPoint(top.width() - m_images[int(DecorationPart::Right)].size().width(), top.height()), m_images[int(DecorationPart::Right)].size());
const QRect bottom(QPoint(0, left.y() + left.height()), m_images[int(DecorationPart::Bottom)].size());
auto imageSize = [this](DecorationPart part) {
return m_images[int(part)].size() / m_images[int(part)].devicePixelRatio();
const QRect top(QPoint(0, 0), imageSize(DecorationPart::Top));
const QRect left(QPoint(0, top.height()), imageSize(DecorationPart::Left));
const QRect right(QPoint(top.width() - imageSize(DecorationPart::Right).width(), top.height()), imageSize(DecorationPart::Right));
const QRect bottom(QPoint(0, left.y() + left.height()), imageSize(DecorationPart::Bottom));
const QRect geometry = scheduled.boundingRect();
auto renderPart = [this](const QRect &rect, const QRect &partRect, int index) {
......@@ -606,7 +610,7 @@ void SceneQPainterDecorationRenderer::render()
QPainter painter(&m_images[index]);
painter.setWindow(QRect(partRect.topLeft(), partRect.size() * m_images[index].devicePixelRatio()));
// clear existing part
......@@ -628,8 +632,12 @@ void SceneQPainterDecorationRenderer::resizeImages()
client()->client()->layoutDecorationRects(left, top, right, bottom);
auto checkAndCreate = [this](int index, const QSize &size) {
if (m_images[index].size() != size) {
m_images[index] = QImage(size, QImage::Format_ARGB32_Premultiplied);
auto dpr = screens()->scale(client()->client()->screen());
if (m_images[index].size() != size * dpr ||
m_images[index].devicePixelRatio() != dpr)
m_images[index] = QImage(size * dpr, QImage::Format_ARGB32_Premultiplied);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment