diff --git a/decorations/decorationrenderer.cpp b/decorations/decorationrenderer.cpp index 7a451afacd..7280f67617 100644 --- a/decorations/decorationrenderer.cpp +++ b/decorations/decorationrenderer.cpp @@ -20,6 +20,7 @@ along with this program. If not, see . #include "decorationrenderer.h" #include "decoratedclient.h" #include "client.h" +#include "deleted.h" #include @@ -63,6 +64,7 @@ QRegion Renderer::getScheduled() QImage Renderer::renderToImage(const QRect &geo) { + Q_ASSERT(m_client); QImage image(geo.width(), geo.height(), QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QPainter p(&image); @@ -73,6 +75,12 @@ QImage Renderer::renderToImage(const QRect &geo) return image; } +void Renderer::reparent(Deleted *deleted) +{ + setParent(deleted); + m_client = nullptr; +} + X11Renderer::X11Renderer(DecoratedClientImpl *client) : Renderer(client) , m_scheduleTimer(new QTimer(this)) diff --git a/decorations/decorationrenderer.h b/decorations/decorationrenderer.h index 8242a05095..4b842d71f8 100644 --- a/decorations/decorationrenderer.h +++ b/decorations/decorationrenderer.h @@ -30,6 +30,8 @@ class QTimer; namespace KWin { +class Deleted; + namespace Decoration { @@ -43,6 +45,13 @@ public: void schedule(const QRect &rect); + /** + * Reparents this Renderer to the @p deleted. + * After this call the Renderer is no longer able to render + * anything, client() returns a nullptr. + **/ + virtual void reparent(Deleted *deleted); + Q_SIGNALS: void renderScheduled(const QRect &geo); diff --git a/deleted.cpp b/deleted.cpp index a092ccb71e..4c349c9c20 100644 --- a/deleted.cpp +++ b/deleted.cpp @@ -24,6 +24,8 @@ along with this program. If not, see . #include "client.h" #include "netinfo.h" #include "shadow.h" +#include "decorations/decoratedclient.h" +#include "decorations/decorationrenderer.h" #include @@ -35,14 +37,11 @@ Deleted::Deleted() , delete_refcount(1) , m_frame(XCB_WINDOW_NONE) , no_border(true) - , padding_left(0) - , padding_top(0) - , padding_right(0) - , padding_bottom(0) , m_layer(UnknownLayer) , m_minimized(false) , m_modal(false) , m_wasClient(false) + , m_decorationRenderer(nullptr) { } @@ -86,18 +85,18 @@ void Deleted::copyToDeleted(Toplevel* c) if (client) { m_wasClient = true; no_border = client->noBorder(); -#if 0 - padding_left = client->paddingLeft(); - padding_right = client->paddingRight(); - padding_bottom = client->paddingBottom(); - padding_top = client->paddingTop(); -#endif if (!no_border) { client->layoutDecorationRects(decoration_left, decoration_top, decoration_right, decoration_bottom, Client::WindowRelative); + if (Decoration::DecoratedClientImpl *decoClient = client->decoratedClient()) { + if (Decoration::Renderer *renderer = decoClient->renderer()) { + m_decorationRenderer = renderer; + m_decorationRenderer->reparent(this); + } + } } m_minimized = client->isMinimized(); m_modal = client->isModal(); @@ -154,7 +153,7 @@ void Deleted::layoutDecorationRects(QRect& left, QRect& top, QRect& right, QRect QRect Deleted::decorationRect() const { - return rect().adjusted(-padding_left, -padding_top, padding_top, padding_bottom); + return rect(); } QRect Deleted::transparentRect() const diff --git a/deleted.h b/deleted.h index 79b631100e..0a667b1cc7 100644 --- a/deleted.h +++ b/deleted.h @@ -26,6 +26,11 @@ along with this program. If not, see . namespace KWin { +namespace Decoration +{ +class Renderer; +} + class Deleted : public Toplevel { @@ -66,6 +71,10 @@ public: bool wasClient() const { return m_wasClient; } + + const Decoration::Renderer *decorationRenderer() const { + return m_decorationRenderer; + } protected: virtual void debug(QDebug& stream) const; virtual bool shouldUnredirect() const; @@ -88,12 +97,12 @@ private: QRect decoration_right; QRect decoration_top; QRect decoration_bottom; - int padding_left, padding_top, padding_right, padding_bottom; Layer m_layer; bool m_minimized; bool m_modal; ClientList m_mainClients; bool m_wasClient; + Decoration::Renderer *m_decorationRenderer; }; inline void Deleted::refWindow() diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 16fdcd8fce..bc5cd8a0eb 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -970,7 +970,6 @@ void SceneOpenGL::Window::endRenderWindow() GLTexture *SceneOpenGL::Window::getDecorationTexture() const { - // TODO: deleted if (toplevel->isClient()) { Client *client = static_cast(toplevel); if (client->noBorder()) { @@ -983,6 +982,14 @@ GLTexture *SceneOpenGL::Window::getDecorationTexture() const return renderer->texture(); } } + } else if (toplevel->isDeleted()) { + Deleted *deleted = static_cast(toplevel); + if (!deleted->wasClient() || deleted->noBorder()) { + return nullptr; + } + if (const SceneOpenGLDecorationRenderer *renderer = static_cast(deleted->decorationRenderer())) { + return renderer->texture(); + } } return nullptr; } @@ -2098,4 +2105,10 @@ void SceneOpenGLDecorationRenderer::resizeTexture() } } +void SceneOpenGLDecorationRenderer::reparent(Deleted *deleted) +{ + render(); + Renderer::reparent(deleted); +} + } // namespace diff --git a/scene_opengl.h b/scene_opengl.h index d1b2a4fc64..b9347704c7 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -631,10 +631,14 @@ public: virtual ~SceneOpenGLDecorationRenderer(); void render() override; + void reparent(Deleted *deleted) override; GLTexture *texture() { return m_texture.data(); } + GLTexture *texture() const { + return m_texture.data(); + } private: void resizeTexture(); diff --git a/scene_qpainter.cpp b/scene_qpainter.cpp index 493381cd8b..ec98c402fd 100644 --- a/scene_qpainter.cpp +++ b/scene_qpainter.cpp @@ -443,11 +443,12 @@ void SceneQPainter::Window::renderWindowDecorations(QPainter *painter) } bool noBorder = true; - SceneQPainterDecorationRenderer *renderer = nullptr; + const SceneQPainterDecorationRenderer *renderer = nullptr; QRect dtr, dlr, drr, dbr; if (client && !client->noBorder()) { if (Decoration::DecoratedClientImpl *impl = client->decoratedClient()) { if (SceneQPainterDecorationRenderer *r = static_cast(impl->renderer())) { + r->render(); renderer = r; } } @@ -455,15 +456,13 @@ void SceneQPainter::Window::renderWindowDecorations(QPainter *painter) noBorder = false; } else if (deleted && !deleted->noBorder()) { noBorder = false; - // TODO: renderer deleted->layoutDecorationRects(dlr, dtr, drr, dbr); + renderer = static_cast(deleted->decorationRenderer()); } if (noBorder || !renderer) { return; } - renderer->render(); - painter->drawImage(dtr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Top)); painter->drawImage(dlr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Left)); painter->drawImage(drr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Right)); @@ -692,4 +691,10 @@ void SceneQPainterDecorationRenderer::resizeImages() checkAndCreate(int(DecorationPart::Bottom), bottom.size()); } +void SceneQPainterDecorationRenderer::reparent(Deleted *deleted) +{ + render(); + Renderer::reparent(deleted); +} + } // KWin diff --git a/scene_qpainter.h b/scene_qpainter.h index c5103667f5..7b59cfc4df 100644 --- a/scene_qpainter.h +++ b/scene_qpainter.h @@ -245,6 +245,7 @@ public: virtual ~SceneQPainterDecorationRenderer(); void render() override; + void reparent(Deleted *deleted) override; QImage image(DecorationPart part) const; diff --git a/scene_xrender.cpp b/scene_xrender.cpp index 2871cc3f3c..7df55ec878 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -722,19 +722,26 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat xcb_render_picture_t right = XCB_RENDER_PICTURE_NONE; xcb_render_picture_t bottom = XCB_RENDER_PICTURE_NONE; QRect dtr, dlr, drr, dbr; - SceneXRenderDecorationRenderer *renderer = nullptr; - // TODO: deleted + const SceneXRenderDecorationRenderer *renderer = nullptr; if (client) { if (client && !client->noBorder()) { if (Decoration::DecoratedClientImpl *impl = client->decoratedClient()) { - renderer = static_cast(impl->renderer()); + SceneXRenderDecorationRenderer *r = static_cast(impl->renderer()); + if (r) { + r->render(); + renderer = r; + } } noBorder = client->noBorder(); client->layoutDecorationRects(dlr, dtr, drr, dbr, Client::WindowRelative); } } + if (deleted && !deleted->noBorder()) { + renderer = static_cast(deleted->decorationRenderer()); + noBorder = deleted->noBorder(); + deleted->layoutDecorationRects(dlr, dtr, drr, dbr, Client::WindowRelative); + } if (renderer) { - renderer->render(); left = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Left); top = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Top); right = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Right); @@ -1415,6 +1422,12 @@ xcb_render_picture_t SceneXRenderDecorationRenderer::picture(SceneXRenderDecorat return *picture; } +void SceneXRenderDecorationRenderer::reparent(Deleted *deleted) +{ + render(); + Renderer::reparent(deleted); +} + #undef DOUBLE_TO_FIXED #undef FIXED_TO_DOUBLE diff --git a/scene_xrender.h b/scene_xrender.h index fe0e5a1a0c..74472945ac 100644 --- a/scene_xrender.h +++ b/scene_xrender.h @@ -354,6 +354,7 @@ public: virtual ~SceneXRenderDecorationRenderer(); void render() override; + void reparent(Deleted *deleted) override; xcb_render_picture_t picture(DecorationPart part) const;