diff --git a/plugins/scenes/qpainter/scene_qpainter.cpp b/plugins/scenes/qpainter/scene_qpainter.cpp index ed8a9d32d8..98dca03e34 100644 --- a/plugins/scenes/qpainter/scene_qpainter.cpp +++ b/plugins/scenes/qpainter/scene_qpainter.cpp @@ -19,7 +19,7 @@ along with this program. If not, see . *********************************************************************/ #include "scene_qpainter.h" // KWin -#include "x11client.h" +#include "abstract_client.h" #include "composite.h" #include "cursor.h" #include "deleted.h" @@ -228,37 +228,6 @@ SceneQPainter::Window::~Window() { } -static void paintSubSurface(QPainter *painter, const QPoint &pos, QPainterWindowPixmap *pixmap) -{ - QPoint p = pos; - if (!pixmap->subSurface().isNull()) { - p += pixmap->subSurface()->position(); - } - - painter->drawImage(QRect(pos, pixmap->size()), pixmap->image()); - const auto &children = pixmap->children(); - for (auto it = children.begin(); it != children.end(); ++it) { - auto pixmap = static_cast(*it); - if (pixmap->subSurface().isNull() || pixmap->subSurface()->surface().isNull() || !pixmap->subSurface()->surface()->isMapped()) { - continue; - } - paintSubSurface(painter, p, pixmap); - } -} - -static bool isXwaylandClient(Toplevel *toplevel) -{ - X11Client *client = qobject_cast(toplevel); - if (client) { - return true; - } - Deleted *deleted = qobject_cast(toplevel); - if (deleted) { - return deleted->wasX11Client(); - } - return false; -} - void SceneQPainter::Window::performPaint(int mask, const QRegion &_region, const WindowPaintData &data) { QRegion region = _region; @@ -299,28 +268,7 @@ void SceneQPainter::Window::performPaint(int mask, const QRegion &_region, const } renderShadow(painter); renderWindowDecorations(painter); - - // render content - QRect source; - QRect target; - if (isXwaylandClient(toplevel)) { - // special case for XWayland windows - source = QRect(toplevel->clientPos(), toplevel->clientSize()); - target = source; - } else { - source = pixmap->image().rect(); - target = toplevel->bufferGeometry().translated(-pos()); - } - painter->drawImage(target, pixmap->image(), source); - - // render subsurfaces - const auto &children = pixmap->children(); - for (auto pixmap : children) { - if (pixmap->subSurface().isNull() || pixmap->subSurface()->surface().isNull() || !pixmap->subSurface()->surface()->isMapped()) { - continue; - } - paintSubSurface(painter, bufferOffset(), static_cast(pixmap)); - } + renderWindowPixmap(painter, pixmap); if (!opaque) { tempPainter.restore(); @@ -336,6 +284,30 @@ void SceneQPainter::Window::performPaint(int mask, const QRegion &_region, const painter->restore(); } +void SceneQPainter::Window::renderWindowPixmap(QPainter *painter, QPainterWindowPixmap *windowPixmap) +{ + const QRegion shape = windowPixmap->shape(); + for (const QRectF &rect : shape) { + const QPointF windowTopLeft = windowPixmap->mapToWindow(rect.topLeft()); + const QPointF windowBottomRight = windowPixmap->mapToWindow(rect.bottomRight()); + + const QPointF bufferTopLeft = windowPixmap->mapToBuffer(rect.topLeft()); + const QPointF bufferBottomRight = windowPixmap->mapToBuffer(rect.bottomRight()); + + painter->drawImage(QRectF(windowTopLeft, windowBottomRight), + windowPixmap->image(), + QRectF(bufferTopLeft, bufferBottomRight)); + } + + const QVector children = windowPixmap->children(); + for (WindowPixmap *child : children) { + QPainterWindowPixmap *scenePixmap = static_cast(child); + if (scenePixmap->isValid()) { + renderWindowPixmap(painter, scenePixmap); + } + } +} + void SceneQPainter::Window::renderShadow(QPainter* painter) { if (!toplevel->shadow()) { diff --git a/plugins/scenes/qpainter/scene_qpainter.h b/plugins/scenes/qpainter/scene_qpainter.h index 88354e505c..18400162d4 100644 --- a/plugins/scenes/qpainter/scene_qpainter.h +++ b/plugins/scenes/qpainter/scene_qpainter.h @@ -71,20 +71,6 @@ private: class Window; }; -class SceneQPainter::Window : public Scene::Window -{ -public: - Window(SceneQPainter *scene, Toplevel *c); - ~Window() override; - void performPaint(int mask, const QRegion ®ion, const WindowPaintData &data) override; -protected: - WindowPixmap *createWindowPixmap() override; -private: - void renderShadow(QPainter *painter); - void renderWindowDecorations(QPainter *painter); - SceneQPainter *m_scene; -}; - class QPainterWindowPixmap : public WindowPixmap { public: @@ -103,6 +89,21 @@ private: QImage m_image; }; +class SceneQPainter::Window : public Scene::Window +{ +public: + Window(SceneQPainter *scene, Toplevel *c); + ~Window() override; + void performPaint(int mask, const QRegion ®ion, const WindowPaintData &data) override; +protected: + WindowPixmap *createWindowPixmap() override; +private: + void renderWindowPixmap(QPainter *painter, QPainterWindowPixmap *windowPixmap); + void renderShadow(QPainter *painter); + void renderWindowDecorations(QPainter *painter); + SceneQPainter *m_scene; +}; + class QPainterEffectFrame : public Scene::EffectFrame { public: diff --git a/scene.cpp b/scene.cpp index d798998092..4ae814e209 100644 --- a/scene.cpp +++ b/scene.cpp @@ -1028,30 +1028,28 @@ WindowQuadList Scene::Window::makeContentsQuads() const continue; const QRegion region = windowPixmap->shape(); - const QPoint position = windowPixmap->framePosition(); - const qreal scale = windowPixmap->scale(); const int quadId = id++; - for (const QRect &rect : region) { + for (const QRectF &rect : region) { // Note that the window quad id is not unique if the window is shaped, i.e. the // region contains more than just one rectangle. We assume that the "source" quad // had been subdivided. WindowQuad quad(WindowQuadContents, quadId); - const qreal x0 = rect.x() + position.x(); - const qreal y0 = rect.y() + position.y(); - const qreal x1 = rect.x() + rect.width() + position.x(); - const qreal y1 = rect.y() + rect.height() + position.y(); + const QPointF windowTopLeft = windowPixmap->mapToWindow(rect.topLeft()); + const QPointF windowTopRight = windowPixmap->mapToWindow(rect.topRight()); + const QPointF windowBottomRight = windowPixmap->mapToWindow(rect.bottomRight()); + const QPointF windowBottomLeft = windowPixmap->mapToWindow(rect.bottomLeft()); - const qreal u0 = rect.x() * scale; - const qreal v0 = rect.y() * scale; - const qreal u1 = (rect.x() + rect.width()) * scale; - const qreal v1 = (rect.y() + rect.height()) * scale; + const QPointF bufferTopLeft = windowPixmap->mapToBuffer(rect.topLeft()); + const QPointF bufferTopRight = windowPixmap->mapToBuffer(rect.topRight()); + const QPointF bufferBottomRight = windowPixmap->mapToBuffer(rect.bottomRight()); + const QPointF bufferBottomLeft = windowPixmap->mapToBuffer(rect.bottomLeft()); - quad[0] = WindowVertex(QPointF(x0, y0), QPointF(u0, v0)); - quad[1] = WindowVertex(QPointF(x1, y0), QPointF(u1, v0)); - quad[2] = WindowVertex(QPointF(x1, y1), QPointF(u1, v1)); - quad[3] = WindowVertex(QPointF(x0, y1), QPointF(u0, v1)); + quad[0] = WindowVertex(windowTopLeft, bufferTopLeft); + quad[1] = WindowVertex(windowTopRight, bufferTopRight); + quad[2] = WindowVertex(windowBottomRight, bufferBottomRight); + quad[3] = WindowVertex(windowBottomLeft, bufferBottomLeft); quads << quad; } @@ -1288,6 +1286,16 @@ bool WindowPixmap::hasAlphaChannel() const return toplevel()->hasAlpha(); } +QPointF WindowPixmap::mapToWindow(const QPointF &point) const +{ + return point + framePosition(); +} + +QPointF WindowPixmap::mapToBuffer(const QPointF &point) const +{ + return point * scale(); +} + //**************************************** // Scene::EffectFrame //**************************************** diff --git a/scene.h b/scene.h index fdeb10e304..e9a9171ee5 100644 --- a/scene.h +++ b/scene.h @@ -502,6 +502,14 @@ public: * Returns @c true if the attached buffer has an alpha channel; otherwise returns @c false. */ bool hasAlphaChannel() const; + /** + * Maps the specified @a point from the window pixmap coordinates to the window local coordinates. + */ + QPointF mapToWindow(const QPointF &point) const; + /** + * Maps the specified @a point from the window pixmap coordinates to the buffer pixel coordinates. + */ + QPointF mapToBuffer(const QPointF &point) const; /** * @returns the parent WindowPixmap in the sub-surface tree