From c12199a8e0a9f59b6ff8fc5db501439d5b1c2808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 23 Jul 2014 09:20:28 +0200 Subject: [PATCH] Pass Decoration::Renderer to Deleted and use it in the Scenes The Renderer gets reparented to the Deleted. While passing it to the Deleted the Scene's implementation can ensure that the buffers are up to date. After passing to Deleted it's no longer allowed to call the render method. --- decorations/decorationrenderer.cpp | 8 ++++++++ decorations/decorationrenderer.h | 9 +++++++++ deleted.cpp | 21 ++++++++++----------- deleted.h | 11 ++++++++++- scene_opengl.cpp | 15 ++++++++++++++- scene_opengl.h | 4 ++++ scene_qpainter.cpp | 13 +++++++++---- scene_qpainter.h | 1 + scene_xrender.cpp | 21 +++++++++++++++++---- scene_xrender.h | 1 + 10 files changed, 83 insertions(+), 21 deletions(-) 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;