diff --git a/decorations/decoratedclient.cpp b/decorations/decoratedclient.cpp --- a/decorations/decoratedclient.cpp +++ b/decorations/decoratedclient.cpp @@ -24,7 +24,7 @@ #include "composite.h" #include "cursor.h" #include "options.h" -#include "scene.h" +#include "platform.h" #include "workspace.h" #include @@ -290,11 +290,7 @@ void DecoratedClientImpl::createRenderer() { - if (Compositor::self()->hasScene()) { - m_renderer = Compositor::self()->scene()->createDecorationRenderer(this); - } else { - m_renderer = new X11Renderer(this); - } + m_renderer = kwinApp()->platform()->createDecorationRenderer(this); } void DecoratedClientImpl::destroyRenderer() diff --git a/decorations/decorationrenderer.h b/decorations/decorationrenderer.h --- a/decorations/decorationrenderer.h +++ b/decorations/decorationrenderer.h @@ -23,12 +23,8 @@ #include #include -#include - #include -class QTimer; - namespace KWin { @@ -84,23 +80,6 @@ bool m_imageSizesDirty; }; -class X11Renderer : public Renderer -{ - Q_OBJECT -public: - explicit X11Renderer(DecoratedClientImpl *client); - virtual ~X11Renderer(); - - void reparent(Deleted *deleted) override; - -protected: - void render() override; - -private: - QTimer *m_scheduleTimer; - xcb_gcontext_t m_gc; -}; - } } diff --git a/decorations/decorationrenderer.cpp b/decorations/decorationrenderer.cpp --- a/decorations/decorationrenderer.cpp +++ b/decorations/decorationrenderer.cpp @@ -19,17 +19,13 @@ *********************************************************************/ #include "decorationrenderer.h" #include "decoratedclient.h" -#include "client.h" #include "deleted.h" -#include - #include #include #include #include -#include namespace KWin { @@ -81,76 +77,5 @@ m_client = nullptr; } -X11Renderer::X11Renderer(DecoratedClientImpl *client) - : Renderer(client) - , m_scheduleTimer(new QTimer(this)) - , m_gc(XCB_NONE) -{ - // delay any rendering to end of event cycle to catch multiple updates per cycle - m_scheduleTimer->setSingleShot(true); - m_scheduleTimer->setInterval(0); - connect(m_scheduleTimer, &QTimer::timeout, this, &X11Renderer::render); - connect(this, &Renderer::renderScheduled, m_scheduleTimer, static_cast(&QTimer::start)); -} - -X11Renderer::~X11Renderer() -{ - if (m_gc != XCB_NONE) { - xcb_free_gc(connection(), m_gc); - } -} - -void X11Renderer::reparent(Deleted *deleted) -{ - if (m_scheduleTimer->isActive()) { - m_scheduleTimer->stop(); - } - disconnect(m_scheduleTimer, &QTimer::timeout, this, &X11Renderer::render); - disconnect(this, &Renderer::renderScheduled, m_scheduleTimer, static_cast(&QTimer::start)); - Renderer::reparent(deleted); -} - -void X11Renderer::render() -{ - if (!client()) { - return; - } - const QRegion scheduled = getScheduled(); - if (scheduled.isEmpty()) { - return; - } - xcb_connection_t *c = connection(); - if (m_gc == XCB_NONE) { - m_gc = xcb_generate_id(c); - xcb_create_gc(c, m_gc, client()->client()->frameId(), 0, nullptr); - } - - QRect left, top, right, bottom; - client()->client()->layoutDecorationRects(left, top, right, bottom); - - const QRect geometry = scheduled.boundingRect(); - left = left.intersected(geometry); - top = top.intersected(geometry); - right = right.intersected(geometry); - bottom = bottom.intersected(geometry); - - auto renderPart = [this, c](const QRect &geo) { - if (geo.isNull()) { - return; - } - QImage image = renderToImage(geo); - xcb_put_image(c, XCB_IMAGE_FORMAT_Z_PIXMAP, client()->client()->frameId(), m_gc, - image.width(), image.height(), geo.x(), geo.y(), 0, client()->client()->depth(), - image.byteCount(), image.constBits()); - }; - renderPart(left); - renderPart(top); - renderPart(right); - renderPart(bottom); - - xcb_flush(c); - resetImageSizesDirty(); -} - } } diff --git a/platform.h b/platform.h --- a/platform.h +++ b/platform.h @@ -50,6 +50,12 @@ class Toplevel; class WaylandCursorTheme; +namespace Decoration +{ +class Renderer; +class DecoratedClientImpl; +} + class KWIN_EXPORT Platform : public QObject { Q_OBJECT @@ -325,6 +331,13 @@ **/ virtual OutlineVisual *createOutline(Outline *outline); + /** + * Creates the Decoration::Renderer for the given @p client. + * + * The default implementation creates a Renderer suited for the Compositor, @c nullptr if there is no Compositor. + **/ + virtual Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client); + public Q_SLOTS: void pointerMotion(const QPointF &position, quint32 time); void pointerButtonPressed(quint32 button, quint32 time); diff --git a/platform.cpp b/platform.cpp --- a/platform.cpp +++ b/platform.cpp @@ -479,4 +479,12 @@ return nullptr; } +Decoration::Renderer *Platform::createDecorationRenderer(Decoration::DecoratedClientImpl *client) +{ + if (Compositor::self()->hasScene()) { + Compositor::self()->scene()->createDecorationRenderer(client); + } + return nullptr; +} + } diff --git a/plugins/platforms/x11/standalone/CMakeLists.txt b/plugins/platforms/x11/standalone/CMakeLists.txt --- a/plugins/platforms/x11/standalone/CMakeLists.txt +++ b/plugins/platforms/x11/standalone/CMakeLists.txt @@ -8,6 +8,7 @@ overlaywindow_x11.cpp screenedges_filter.cpp non_composited_outline.cpp + x11_decoration_renderer.cpp ) if(X11_Xinput_FOUND) diff --git a/decorations/decorationrenderer.h b/plugins/platforms/x11/standalone/x11_decoration_renderer.h copy from decorations/decorationrenderer.h copy to plugins/platforms/x11/standalone/x11_decoration_renderer.h --- a/decorations/decorationrenderer.h +++ b/plugins/platforms/x11/standalone/x11_decoration_renderer.h @@ -17,73 +17,21 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ -#ifndef KWIN_DECORATION_RENDERER_H -#define KWIN_DECORATION_RENDERER_H +#ifndef KWIN_DECORATION_X11_RENDERER_H +#define KWIN_DECORATION_X11_RENDERER_H -#include -#include +#include "decorations/decorationrenderer.h" #include -#include - class QTimer; namespace KWin { -class Deleted; - namespace Decoration { -class DecoratedClientImpl; - -class KWIN_EXPORT Renderer : public QObject -{ - Q_OBJECT -public: - virtual ~Renderer(); - - 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); - -protected: - explicit Renderer(DecoratedClientImpl *client); - /** - * @returns the scheduled paint region and resets - **/ - QRegion getScheduled(); - - virtual void render() = 0; - - DecoratedClientImpl *client() { - return m_client; - } - - bool areImageSizesDirty() const { - return m_imageSizesDirty; - } - void resetImageSizesDirty() { - m_imageSizesDirty = false; - } - QImage renderToImage(const QRect &geo); - -private: - DecoratedClientImpl *m_client; - QRegion m_scheduled; - bool m_imageSizesDirty; -}; - class X11Renderer : public Renderer { Q_OBJECT diff --git a/decorations/decorationrenderer.cpp b/plugins/platforms/x11/standalone/x11_decoration_renderer.cpp copy from decorations/decorationrenderer.cpp copy to plugins/platforms/x11/standalone/x11_decoration_renderer.cpp --- a/decorations/decorationrenderer.cpp +++ b/plugins/platforms/x11/standalone/x11_decoration_renderer.cpp @@ -17,70 +17,23 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ -#include "decorationrenderer.h" -#include "decoratedclient.h" +#include "x11_decoration_renderer.h" +#include "decorations/decoratedclient.h" #include "client.h" #include "deleted.h" #include #include #include -#include -#include #include namespace KWin { namespace Decoration { -Renderer::Renderer(DecoratedClientImpl *client) - : QObject(client) - , m_client(client) - , m_imageSizesDirty(true) -{ - auto markImageSizesDirty = [this]{ m_imageSizesDirty = true; }; - connect(client->decoration(), &KDecoration2::Decoration::bordersChanged, this, markImageSizesDirty); - connect(client->decoratedClient(), &KDecoration2::DecoratedClient::widthChanged, this, markImageSizesDirty); - connect(client->decoratedClient(), &KDecoration2::DecoratedClient::heightChanged, this, markImageSizesDirty); -} - -Renderer::~Renderer() = default; - -void Renderer::schedule(const QRect &rect) -{ - m_scheduled = m_scheduled.united(rect); - emit renderScheduled(rect); -} - -QRegion Renderer::getScheduled() -{ - QRegion region = m_scheduled; - m_scheduled = QRegion(); - return region; -} - -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); - p.setRenderHint(QPainter::Antialiasing); - p.setWindow(geo); - p.setClipRect(geo); - client()->decoration()->paint(&p, 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/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h --- a/plugins/platforms/x11/standalone/x11_platform.h +++ b/plugins/platforms/x11/standalone/x11_platform.h @@ -60,6 +60,7 @@ void updateXTime() override; OutlineVisual *createOutline(Outline *outline) override; + Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client) override; protected: void doHideCursor() override; diff --git a/plugins/platforms/x11/standalone/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp --- a/plugins/platforms/x11/standalone/x11_platform.cpp +++ b/plugins/platforms/x11/standalone/x11_platform.cpp @@ -37,6 +37,7 @@ #include "options.h" #include "overlaywindow_x11.h" #include "non_composited_outline.h" +#include "x11_decoration_renderer.h" #include #include @@ -346,4 +347,13 @@ return ret; } +Decoration::Renderer *X11StandalonePlatform::createDecorationRenderer(Decoration::DecoratedClientImpl *client) +{ + auto renderer = Platform::createDecorationRenderer(client); + if (!renderer) { + renderer = new Decoration::X11Renderer(client); + } + return renderer; +} + }