From bd52b6791e8b75690a4bfa9fa89d8dc88fe3c925 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sun, 26 Jan 2020 15:08:52 +0200 Subject: [PATCH] Schedule a decoration repaint when client is resized Summary: If a client has been resized, it doesn't necessarily mean that the decoration theme will schedule full repaint of the window frame. In OpenGL and Xrender scene, we have a little hack that forces a full repaint of window borders. However, we don't have one in QPainter scene which causes all sorts of weird looking artifacts when resizing a server-side decorated client. We could add yet another hack in the QPainter scene, but a better approach to tackle this problem would be to make DecoratedClient schedule a full repaint of the decoration. It makes code in scene plugins more straightforward and prevents us from repeating the same mistake again. Test Plan: No longer able to see invisible decoration borders when using QPainter render backend. Reviewers: #kwin, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: davidedmundson, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D26927 --- decorations/decorationrenderer.cpp | 4 ++-- plugins/scenes/opengl/scene_opengl.cpp | 9 ++++----- plugins/scenes/xrender/scene_xrender.cpp | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/decorations/decorationrenderer.cpp b/decorations/decorationrenderer.cpp index ef753f27c4..5e28e40b71 100644 --- a/decorations/decorationrenderer.cpp +++ b/decorations/decorationrenderer.cpp @@ -40,12 +40,12 @@ Renderer::Renderer(DecoratedClientImpl *client) , m_imageSizesDirty(true) { auto markImageSizesDirty = [this]{ + schedule(m_client->client()->rect()); m_imageSizesDirty = true; }; connect(client->client(), &AbstractClient::screenScaleChanged, 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); + connect(client->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged, this, markImageSizesDirty); } Renderer::~Renderer() = default; diff --git a/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp index 3b5d2432d0..d15e503174 100644 --- a/plugins/scenes/opengl/scene_opengl.cpp +++ b/plugins/scenes/opengl/scene_opengl.cpp @@ -2562,11 +2562,10 @@ static void clamp(QImage &image, const QRect &viewport) void SceneOpenGLDecorationRenderer::render() { const QRegion scheduled = getScheduled(); - const bool dirty = areImageSizesDirty(); - if (scheduled.isEmpty() && !dirty) { + if (scheduled.isEmpty()) { return; } - if (dirty) { + if (areImageSizesDirty()) { resizeTexture(); resetImageSizesDirty(); } @@ -2579,8 +2578,6 @@ void SceneOpenGLDecorationRenderer::render() QRect left, top, right, bottom; client()->client()->layoutDecorationRects(left, top, right, bottom); - const QRect geometry = dirty ? QRect(QPoint(0, 0), client()->client()->size()) : scheduled.boundingRect(); - // We pad each part in the decoration atlas in order to avoid texture bleeding. const int padding = 1; @@ -2634,6 +2631,8 @@ void SceneOpenGLDecorationRenderer::render() m_texture->update(image, (position + dirtyOffset - viewport.topLeft()) * image.devicePixelRatio()); }; + const QRect geometry = scheduled.boundingRect(); + const QPoint topPosition(padding, padding); const QPoint bottomPosition(padding, topPosition.y() + top.height() + 2 * padding); const QPoint leftPosition(padding, bottomPosition.y() + bottom.height() + 2 * padding); diff --git a/plugins/scenes/xrender/scene_xrender.cpp b/plugins/scenes/xrender/scene_xrender.cpp index 1afeeedcb2..acab174a56 100644 --- a/plugins/scenes/xrender/scene_xrender.cpp +++ b/plugins/scenes/xrender/scene_xrender.cpp @@ -1229,7 +1229,6 @@ void SceneXRenderDecorationRenderer::render() if (areImageSizesDirty()) { resizePixmaps(); resetImageSizesDirty(); - scheduled = client()->client()->decorationRect(); } const QRect top(QPoint(0, 0), m_sizes[int(DecorationPart::Top)]);