[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kwin/graesslin/kdecoration2] /: Initial import of support for new KDecoration2 based decorations
From:       Martin_Gräßlin <mgraesslin () kde ! org>
Date:       2014-07-25 12:08:02
Message-ID: E1XAeI6-0001Zu-Ir () scm ! kde ! org
[Download RAW message or body]

Git commit 0030eb7f84d36fc12ffc12159cb5da49f5dd66f3 by Martin Gräßlin.
Committed on 22/07/2014 at 11:11.
Pushed by graesslin into branch 'graesslin/kdecoration2'.

Initial import of support for new KDecoration2 based decorations

NOTE: this is not working completely yet, lots of code is still ifdefed
other parts are still broken.

The main difference for the new decoration API is that it is neither
QWidget nor QWindow based. It's just a QObject which processes input
events and has a paint method to render the decoration. This means all
the workarounds for the QWidget interception are removed. Also the paint
redirector is removed. Instead each compositor has now its own renderer
which can be optimized for the specific case. E.g. the OpenGL compositor
renders to a scratch image which gets copied into the combined texture,
the XRender compositor copies into the XPixmaps.

Input events are also changed. The events are composed into QMouseEvents
and passed through the decoration, which might accept them. If they are
not accpted we assume that it's a press on the decoration area allowing
us to resize/move the window. Input events are not completely working
yet, e.g. wheel events are not yet processed and double click on deco
is not yet working.

Overall KDecoration2 is way more stateful and KWin core needs more
adjustments for it. E.g. borders are allowed to be disabled at any time.

M  +8    -3    CMakeLists.txt
D  +0    -380  bridge.cpp
D  +0    -113  bridge.h
M  +99   -188  client.cpp
M  +20   -42   client.h
M  +1    -6    composite.cpp
D  +0    -183  decorations.cpp
D  +0    -72   decorations.h
A  +201  -0    decorations/decoratedclient.cpp     [License: GPL (v2)]
A  +97   -0    decorations/decoratedclient.h     [License: GPL (v2)]
A  +113  -0    decorations/decorationbridge.cpp     [License: GPL (v2)]
A  +58   -0    decorations/decorationbridge.h     [License: GPL (v2)]
A  +134  -0    decorations/decorationrenderer.cpp     [License: GPL (v2)]
A  +94   -0    decorations/decorationrenderer.h     [License: GPL (v2)]
A  +77   -0    decorations/settings.cpp     [License: GPL (v2)]
A  +46   -0    decorations/settings.h     [License: GPL (v2)]
M  +2    -7    deleted.cpp
M  +0    -5    deleted.h
M  +4    -5    effects.cpp
M  +41   -121  events.cpp
M  +59   -43   geometry.cpp
M  +2    -3    manage.cpp
M  +0    -5    netinfo.cpp
D  +0    -561  paintredirector.cpp
D  +0    -290  paintredirector.h
M  +2    -5    scene.cpp
M  +8    -0    scene.h
M  +118  -29   scene_opengl.cpp
M  +28   -4    scene_opengl.h
M  +93   -16   scene_qpainter.cpp
M  +26   -0    scene_qpainter.h
M  +135  -27   scene_xrender.cpp
M  +28   -0    scene_xrender.h
M  +1    -2    tabgroup.cpp
M  +0    -6    toplevel.h
M  +2    -3    useractions.cpp
M  +4    -24   workspace.cpp

http://commits.kde.org/kwin/0030eb7f84d36fc12ffc12159cb5da49f5dd66f3

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e28632f..7950808 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -97,6 +97,8 @@ set_package_properties(KF5DocTools PROPERTIES
          )
 add_feature_info("KF5DocTools" KF5DocTools_FOUND "Enable building documentation")
 
+find_package(KDecoration2 CONFIG REQUIRED)
+
 if(${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")
     find_package(OpenGL)
     set_package_properties(OpenGL PROPERTIES DESCRIPTION "The OpenGL libraries"
@@ -313,7 +315,6 @@ set(kwin_KDEINIT_SRCS
    main.cpp 
    options.cpp 
    outline.cpp
-   decorations.cpp
    events.cpp 
    killwindow.cpp 
    geometrytip.cpp 
@@ -321,7 +322,6 @@ set(kwin_KDEINIT_SRCS
    shadow.cpp
    sm.cpp 
    group.cpp 
-   bridge.cpp 
    manage.cpp 
    overlaywindow.cpp
    activation.cpp 
@@ -342,7 +342,6 @@ set(kwin_KDEINIT_SRCS
    effects.cpp
    effectloader.cpp
    compositingprefs.cpp
-   paintredirector.cpp
    virtualdesktops.cpp
    xcbutils.cpp
     scripting/scripting.cpp
@@ -354,6 +353,10 @@ set(kwin_KDEINIT_SRCS
     scripting/scripting_model.cpp
     scripting/dbuscall.cpp
     scripting/screenedgeitem.cpp
+    decorations/decoratedclient.cpp
+    decorations/decorationbridge.cpp
+    decorations/settings.cpp
+    decorations/decorationrenderer.cpp
    )
 
 if(KWIN_BUILD_TABBOX)
@@ -445,6 +448,8 @@ set(kwin_KDE_LIBS
     KF5::Service
     KF5::Plasma
     KF5::WindowSystem
+    KDecoration2::KDecoration
+    KDecoration2::KDecoration2Private
 )
 
 set(kwin_XLIB_LIBS
diff --git a/bridge.cpp b/bridge.cpp
deleted file mode 100644
index 62ea04f..0000000
--- a/bridge.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-/********************************************************************
- KWin - the KDE window manager
- This file is part of the KDE project.
-
-Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*********************************************************************/
-
-#include "bridge.h"
-
-#include "client.h"
-#include "cursor.h"
-#include "options.h"
-
-#include <kconfiggroup.h>
-#include "composite.h"
-#include "paintredirector.h"
-#include "virtualdesktops.h"
-#include "workspace.h"
-
-#include <QDebug>
-
-namespace KWin
-{
-
-Bridge::Bridge(Client* cl)
-    : c(cl)
-{
-}
-
-#define BRIDGE_HELPER( rettype, prototype, args1, args2, cst ) \
-    rettype Bridge::prototype ( args1 ) cst \
-    { \
-        return c->prototype( args2 ); \
-    }
-
-BRIDGE_HELPER(bool, isCloseable, , , const)
-BRIDGE_HELPER(bool, isMaximizable, , , const)
-BRIDGE_HELPER(Bridge::MaximizeMode, maximizeMode, , , const)
-BRIDGE_HELPER(Bridge::QuickTileMode, quickTileMode, , , const)
-BRIDGE_HELPER(bool, isMinimizable, , , const)
-BRIDGE_HELPER(bool, providesContextHelp, , , const)
-BRIDGE_HELPER(int, desktop, , , const)
-BRIDGE_HELPER(bool, isModal, , , const)
-BRIDGE_HELPER(bool, isShadeable, , , const)
-BRIDGE_HELPER(bool, isShade, , , const)
-BRIDGE_HELPER(bool, keepAbove, , , const)
-BRIDGE_HELPER(bool, keepBelow, , , const)
-BRIDGE_HELPER(bool, isMovable, , , const)
-BRIDGE_HELPER(bool, isResizable, , , const)
-BRIDGE_HELPER(void, processMousePressEvent, QMouseEvent* e, e,)
-BRIDGE_HELPER(QRect, geometry, , , const)
-BRIDGE_HELPER(void, closeWindow, , ,)
-BRIDGE_HELPER(void, maximize, MaximizeMode m, m,)
-BRIDGE_HELPER(void, minimize, , ,)
-BRIDGE_HELPER(void, showContextHelp, , ,)
-BRIDGE_HELPER(void, setDesktop, int desktop, desktop,)
-BRIDGE_HELPER(QPalette, palette, , , const)
-
-bool Bridge::isActive() const
-{
-    return c->isActive() || (c->tabGroup() && c->tabGroup()->isActive());
-}
-
-void Bridge::setKeepAbove(bool set)
-{
-    if (c->keepAbove() != set)
-        workspace()->performWindowOperation(c, KeepAboveOp);
-}
-
-void Bridge::setKeepBelow(bool set)
-{
-    if (c->keepBelow() != set)
-        workspace()->performWindowOperation(c, KeepBelowOp);
-}
-
-NET::WindowType Bridge::windowType(unsigned long supported_types) const
-{
-    return c->windowType(false, supported_types);
-}
-
-QIcon Bridge::icon() const
-{
-    return c->icon();
-}
-
-bool Bridge::isSetShade() const
-{
-    return c->shadeMode() != ShadeNone;
-}
-
-void Bridge::showWindowMenu(const QPoint &p)
-{
-    workspace()->showWindowMenu(QRect(p,p), c);
-}
-
-void Bridge::showWindowMenu(const QPoint &p, long id)
-{
-    Client *cc = clientForId(id);
-    if (!cc)
-        cc = c;
-    workspace()->showWindowMenu(QRect(p,p), cc);
-}
-
-void Bridge::showWindowMenu(const QRect &p)
-{
-    workspace()->showWindowMenu(p, c);
-}
-
-void Bridge::showApplicationMenu(const QPoint &p)
-{
-#ifdef KWIN_BUILD_KAPPMENU
-    c->showApplicationMenu(p);
-#else
-    Q_UNUSED(p)
-#endif
-}
-
-bool Bridge::menuAvailable() const
-{
-#ifdef KWIN_BUILD_KAPPMENU
-    return c->menuAvailable();
-#else
-    return false;
-#endif
-}
-
-void Bridge::performWindowOperation(WindowOperation op)
-{
-    workspace()->performWindowOperation(c, op);
-}
-
-void Bridge::setMask(const QRegion& r, int mode)
-{
-    c->setMask(r, mode);
-}
-
-bool Bridge::isPreview() const
-{
-    return false;
-}
-
-QRect Bridge::iconGeometry() const
-{
-    NETRect r = c->info->iconGeometry();
-    return QRect(r.pos.x, r.pos.y, r.size.width, r.size.height);
-}
-
-WId Bridge::windowId() const
-{
-    return c->window();
-}
-
-void Bridge::titlebarDblClickOperation()
-{
-    workspace()->performWindowOperation(c, options->operationTitlebarDblClick());
-    c->dontMoveResize();
-}
-
-void Bridge::titlebarMouseWheelOperation(int delta)
-{
-    c->performMouseCommand(options->operationTitlebarMouseWheel(delta), \
                Cursor::pos());
-}
-
-void Bridge::setShade(bool set)
-{
-    c->setShade(set ? ShadeNormal : ShadeNone);
-}
-
-int Bridge::currentDesktop() const
-{
-    return VirtualDesktopManager::self()->current();
-}
-
-Qt::WindowFlags Bridge::initialWFlags() const
-{
-    return Qt::WindowDoesNotAcceptFocus;
-}
-
-QRegion Bridge::unobscuredRegion(const QRegion& r) const
-{
-    QRegion reg(r);
-    const ToplevelList stacking_order = workspace()->stackingOrder();
-    int pos = stacking_order.indexOf(c);
-    ++pos;
-    for (; pos < stacking_order.count(); ++pos) {
-        Client *client = qobject_cast<Client*>(stacking_order[pos]);
-        if (!client) {
-            continue;
-        }
-        if (!client->isShown(true))
-            continue; // these don't obscure the window
-        if (c->isOnAllDesktops()) {
-            if (!client->isOnCurrentDesktop())
-                continue;
-        } else {
-            if (!client->isOnDesktop(c->desktop()))
-                continue;
-        }
-        /* the clients all have their mask-regions in local coords
-           so we have to translate them to a shared coord system
-           we choose ours */
-        int dx = client->x() - c->x();
-        int dy = client->y() - c->y();
-        QRegion creg = client->mask();
-        creg.translate(dx, dy);
-        reg -= creg;
-        if (reg.isEmpty()) {
-            // early out, we are completely obscured
-            break;
-        }
-    }
-    return reg;
-}
-
-void Bridge::grabXServer(bool grab)
-{
-    if (grab)
-        KWin::grabXServer();
-    else
-        KWin::ungrabXServer();
-}
-
-bool Bridge::compositingActive() const
-{
-    return Compositor::compositing();
-}
-
-QRect Bridge::transparentRect() const
-{
-    return c->transparentRect().translated(-c->decorationRect().topLeft());
-}
-
-void Bridge::update(const QRegion &region)
-{
-    if (c->paintRedirector) {
-        c->paintRedirector->addRepaint(region);
-    }
-}
-
-//BEGIN TABBING
-
-Client *Bridge::clientForId(long id) const
-{
-    Client* client = reinterpret_cast<Client*>(id);
-    if (!workspace()->hasClient(client)) {
-        qWarning() << "****** ARBITRARY CODE EXECUTION ATTEMPT DETECTED ******" << \
                id;
-        return 0;
-    }
-    return client;
-}
-
-int Bridge::tabCount() const
-{
-    if (c->tabGroup())
-        return c->tabGroup()->count();
-    return 1;
-}
-
-long Bridge::tabId(int idx) const
-{
-    if (c->tabGroup())
-        return tabIdOf(c->tabGroup()->clients().at(idx));
-    return tabIdOf(c);
-}
-
-QIcon Bridge::icon(int idx) const
-{
-    if (c->tabGroup()) {
-        return c->tabGroup()->clients().at(idx)->icon();
-    }
-    return icon();
-}
-
-QString Bridge::caption() const
-{
-    return c->caption(true, true);
-}
-
-QString Bridge::caption(int idx) const
-{
-    if (c->tabGroup())
-        return c->tabGroup()->clients().at(idx)->caption(true, true);
-    return c->caption(true, true);
-}
-
-long Bridge::currentTabId() const
-{
-    if (c->tabGroup())
-        return tabIdOf(c->tabGroup()->current());
-    return 0;
-}
-
-void Bridge::setCurrentTab(long id)
-{
-    if (c->tabGroup())
-        c->tabGroup()->setCurrent(clientForId(id));
-}
-
-void Bridge::tab_A_before_B(long A, long B)
-{
-    if (!B) {
-        if (c->tabGroup()) {
-            if (Client *a = clientForId(A))
-                a->untab();
-        }
-        return;
-    }
-
-    if (Client *a = clientForId(A))
-    if (Client *b = clientForId(B))
-    if (a != b)
-        a->tabBefore(b, true);
-}
-
-void Bridge::tab_A_behind_B(long A, long B)
-{
-    if (!B) {
-        if (c->tabGroup()) {
-            if (Client *a = clientForId(A))
-            a->untab();
-        }
-        return;
-    }
-
-    if (Client *a = clientForId(A))
-    if (Client *b = clientForId(B))
-    if (a != b)
-        a->tabBehind(b, true);
-}
-
-
-void Bridge::untab(long id, const QRect& newGeom)
-{
-    if (c->tabGroup())
-    if (Client* client = clientForId(id))
-    if (client->untab(newGeom)) {
-        if (options->focusPolicyIsReasonable())
-            workspace()->takeActivity(client, Workspace::ActivityFocus | \
                Workspace::ActivityRaise);
-        workspace()->raiseClient(client);
-    }
-}
-
-void Bridge::closeTab(long id)
-{
-    if (Client* client = clientForId(id))
-        client->closeWindow();
-}
-
-void Bridge::closeTabGroup()
-{
-    if (c->tabGroup())
-        c->tabGroup()->closeAll();
-}
-
-//END TABBING
-
-bool Bridge::isOnAllDesktopsAvailable() const
-{
-    return VirtualDesktopManager::self()->count() > 1;
-}
-
-KDecoration::WindowOperation Bridge::buttonToWindowOperation(Qt::MouseButtons \
                button)
-{
-    return c->mouseButtonToWindowOperation(button);
-}
-
-} // namespace
diff --git a/bridge.h b/bridge.h
deleted file mode 100644
index dbed9d1..0000000
--- a/bridge.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/********************************************************************
- KWin - the KDE window manager
- This file is part of the KDE project.
-
-Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*********************************************************************/
-
-#ifndef KWIN_BRIDGE_H
-#define KWIN_BRIDGE_H
-
-#include <kdecorationbridge.h>
-
-namespace KWin
-{
-
-class Client;
-
-class Bridge : public KDecorationBridge
-{
-public:
-    explicit Bridge(Client* cl);
-    virtual bool isActive() const override;
-    virtual bool isCloseable() const override;
-    virtual bool isMaximizable() const override;
-    virtual MaximizeMode maximizeMode() const override;
-    virtual QuickTileMode quickTileMode() const override;
-    virtual bool isMinimizable() const override;
-    virtual bool providesContextHelp() const override;
-    virtual int desktop() const override;
-    bool isOnAllDesktopsAvailable() const override;
-    virtual bool isModal() const override;
-    virtual bool isShadeable() const override;
-    virtual bool isShade() const override;
-    virtual bool isSetShade() const override;
-    virtual bool keepAbove() const override;
-    virtual bool keepBelow() const override;
-    virtual bool isMovable() const override;
-    virtual bool isResizable() const override;
-    virtual NET::WindowType windowType(unsigned long supported_types) const \
                override;
-    virtual QIcon icon() const override;
-    virtual QString caption() const override;
-    virtual void processMousePressEvent(QMouseEvent*) override;
-    virtual void showWindowMenu(const QPoint &) override;
-    virtual void showWindowMenu(const QRect &) override;
-    virtual void showApplicationMenu(const QPoint &) override;
-    virtual bool menuAvailable() const override;
-    virtual void performWindowOperation(WindowOperation) override;
-    virtual void setMask(const QRegion&, int) override;
-    virtual bool isPreview() const override;
-    virtual QRect geometry() const override;
-    virtual QRect iconGeometry() const override;
-    virtual QRegion unobscuredRegion(const QRegion& r) const override;
-    virtual WId windowId() const override;
-    virtual void closeWindow() override;
-    virtual void maximize(MaximizeMode mode) override;
-    virtual void minimize() override;
-    virtual void showContextHelp() override;
-    virtual void setDesktop(int desktop) override;
-    virtual void titlebarDblClickOperation() override;
-    virtual void titlebarMouseWheelOperation(int delta) override;
-    virtual void setShade(bool set) override;
-    virtual void setKeepAbove(bool) override;
-    virtual void setKeepBelow(bool) override;
-    virtual int currentDesktop() const override;
-    virtual Qt::WindowFlags initialWFlags() const override;
-    virtual void grabXServer(bool grab) override;
-
-    virtual bool compositingActive() const override;
-    virtual QRect transparentRect() const override;
-
-    virtual void update(const QRegion &region) override;
-    virtual QPalette palette() const override;
-
-    // Window tabbing
-    virtual QString caption(int idx) const override;
-    virtual void closeTab(long id) override;
-    virtual void closeTabGroup() override;
-    virtual long currentTabId() const override;
-    virtual QIcon icon(int idx) const override;
-    virtual void setCurrentTab(long id) override;
-    virtual void showWindowMenu(const QPoint &, long id) override;
-    virtual void tab_A_before_B(long A, long B) override;
-    virtual void tab_A_behind_B(long A, long B) override;
-    virtual int tabCount() const override;
-    virtual long tabId(int idx) const override;
-    virtual void untab(long id, const QRect& newGeom) override;
-
-    virtual WindowOperation buttonToWindowOperation(Qt::MouseButtons button) \
                override;
-
-private:
-    Client *clientForId(long id) const;
-    static inline long tabIdOf(Client *c) {
-        return reinterpret_cast<long>(c);
-    }
-    Client* c;
-};
-
-} // namespace
-
-#endif
diff --git a/client.cpp b/client.cpp
index 68fe122..63a0200 100644
--- a/client.cpp
+++ b/client.cpp
@@ -28,21 +28,22 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "appmenu.h"
 #endif
 #include "atoms.h"
-#include "bridge.h"
 #include "client_machine.h"
 #include "composite.h"
 #include "cursor.h"
-#include "decorations.h"
 #include "deleted.h"
 #include "focuschain.h"
 #include "group.h"
-#include "paintredirector.h"
 #include "shadow.h"
 #ifdef KWIN_BUILD_TABBOX
 #include "tabbox.h"
 #endif
 #include "workspace.h"
 #include "screenedge.h"
+#include "decorations/decorationbridge.h"
+#include "decorations/decoratedclient.h"
+#include <KDecoration2/Decoration>
+#include <KDecoration2/DecoratedClient>
 // KDE
 #include <KWindowSystem>
 #include <KColorScheme>
@@ -181,8 +182,7 @@ Client::Client()
     , m_client()
     , m_wrapper()
     , m_frame()
-    , decoration(NULL)
-    , bridge(new Bridge(this))
+    , m_decoration(nullptr)
     , m_activityUpdatesBlocked(false)
     , m_blockedActivityUpdatesRequireTransients(false)
     , m_moveResizeGrabWindow()
@@ -211,16 +211,7 @@ Client::Client()
     , block_geometry_updates(0)
     , pending_geometry_update(PendingGeometryNone)
     , shade_geometry_change(false)
-    , border_left(0)
-    , border_right(0)
-    , border_top(0)
-    , border_bottom(0)
-    , padding_left(0)
-    , padding_right(0)
-    , padding_top(0)
-    , padding_bottom(0)
     , sm_stacking_order(-1)
-    , paintRedirector(0)
     , m_firstInTabBox(false)
     , electricMaximizing(false)
     , activitiesDefined(false)
@@ -306,12 +297,6 @@ Client::Client()
     connect(clientMachine(), &ClientMachine::localhostChanged, this, \
                &Client::updateCaption);
     connect(options, &Options::condensedTitleChanged, this, &Client::updateCaption);
 
-    m_connections << connect(VirtualDesktopManager::self(), \
                &VirtualDesktopManager::countChanged, [this]() {
-        if (decoration) {
-            decoration->onAllDesktopsAvailableChanged();
-        }
-    });
-
     // SELI TODO: Initialize xsizehints??
 }
 
@@ -331,10 +316,9 @@ Client::~Client()
     assert(m_client == XCB_WINDOW_NONE);
     assert(m_wrapper == XCB_WINDOW_NONE);
     //assert( frameId() == None );
-    assert(decoration == NULL);
+    Q_ASSERT(m_decoration == nullptr);
     assert(block_geometry_updates == 0);
     assert(!check_active_modal);
-    delete bridge;
     for (auto it = m_connections.constBegin(); it != m_connections.constEnd(); ++it) \
{  disconnect(*it);
     }
@@ -461,6 +445,7 @@ void Client::updateInputWindow()
 
     QRegion region;
 
+#if 0
     if (!noBorder()) {
         // This function is implemented as a slot to avoid breaking binary
         // compatibility
@@ -468,6 +453,7 @@ void Client::updateInputWindow()
                 Q_RETURN_ARG(QRegion, region),
                 Q_ARG(KDecorationDefines::Region, \
KDecorationDefines::ExtendedBorderRegion));  }
+#endif
 
     if (region.isEmpty()) {
         m_decoInputExtent.reset();
@@ -507,7 +493,7 @@ void Client::updateInputWindow()
 void Client::updateDecoration(bool check_workspace_pos, bool force)
 {
     if (!force &&
-            ((decoration == NULL && noBorder()) || (decoration != NULL && \
!noBorder()))) +            ((m_decoration == NULL && noBorder()) || (m_decoration != \
NULL && !noBorder())))  return;
     QRect oldgeom = geometry();
     blockGeometryUpdates(true);
@@ -521,55 +507,19 @@ void Client::updateDecoration(bool check_workspace_pos, bool \
force)  checkWorkspacePosition(oldgeom);
     updateInputWindow();
     blockGeometryUpdates(false);
-    if (!noBorder())
-        decoration->show();
     updateFrameExtents();
 }
 
 void Client::createDecoration(const QRect& oldgeom)
 {
-    setMask(QRegion());  // Reset shape mask
-    if (decorationPlugin()->isDisabled()) {
-        decoration = NULL;
-        return;
-    } else {
-        decoration = decorationPlugin()->createDecoration(bridge);
-    }
-    connect(this, &Client::iconChanged, decoration, &KDecoration::iconChanged);
-    connect(this, &Client::shadeChanged, decoration, &KDecoration::shadeChanged);
-    connect(this, &Client::desktopChanged, decoration, \
                &KDecoration::desktopChanged);
-    connect(this, &Client::captionChanged, decoration, \
                &KDecoration::captionChanged);
-    connect(this, &Client::activeChanged, decoration, &KDecoration::activeChanged);
-    auto signalMaximizeChanged = static_cast<void (Client::*)(Client*, \
                KDecorationDefines::MaximizeMode)>(&Client::clientMaximizedStateChanged);
                
-    connect(this, signalMaximizeChanged, decoration, &KDecoration::maximizeChanged);
-    auto slotKeepAbove = \
                static_cast<void(KDecoration::*)(bool)>(&KDecoration::keepAboveChanged);
                
-    connect(this, &Client::keepAboveChanged, decoration, slotKeepAbove);
-    auto slotKeepBelow = \
                static_cast<void(KDecoration::*)(bool)>(&KDecoration::keepBelowChanged);
                
-    connect(this, &Client::keepBelowChanged, decoration, slotKeepBelow);
-#ifdef KWIN_BUILD_KAPPMENU
-    connect(this, SIGNAL(showRequest()), decoration, SIGNAL(showRequest()));
-    connect(this, SIGNAL(appMenuAvailable()), decoration, \
                SIGNAL(appMenuAvailable()));
-    connect(this, SIGNAL(appMenuUnavailable()), decoration, \
                SIGNAL(appMenuUnavailable()));
-    connect(this, SIGNAL(menuHidden()), decoration, SIGNAL(menuHidden()));
-#endif
-    // TODO: Check decoration's minimum size?
-    decoration->init();
-    if (decoration->widget()) {
-        decoration->widget()->installEventFilter(this);
-        decoration->window()->setParent(m_frameWrapper.data());
-    } else if (decoration->window()) {
-        decoration->window()->installEventFilter(this);
-        xcb_reparent_window(connection(), decoration->window()->winId(), frameId(), \
                0, 0);
-    }
-    decoration->window()->lower();
-    decoration->borders(border_left, border_right, border_top, border_bottom);
-    padding_left = padding_right = padding_top = padding_bottom = 0;
-    decoration->padding(padding_left, padding_right, padding_top, padding_bottom);
-    Xcb::moveWindow(decoration->window()->winId(), -padding_left, -padding_top);
+    m_decoration = Decoration::DecorationBridge::self()->createDecoration(this);
+    if (m_decoration) {
+        m_decoration->update();
+    }
+
     move(calculateGravitation(false));
     plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
     if (Compositor::compositing()) {
-        paintRedirector = PaintRedirector::create(this, decoration);
         discardWindowPixmap();
     }
     emit geometryShapeChanged(this, oldgeom);
@@ -578,13 +528,10 @@ void Client::createDecoration(const QRect& oldgeom)
 void Client::destroyDecoration()
 {
     QRect oldgeom = geometry();
-    if (decoration != NULL) {
-        delete decoration;
-        decoration = NULL;
-        paintRedirector = NULL;
+    if (m_decoration) {
+        delete m_decoration;
+        m_decoration = nullptr;
         QPoint grav = calculateGravitation(true);
-        border_left = border_right = border_top = border_bottom = 0;
-        setMask(QRegion());  // Reset shape mask
         plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
         move(grav);
         if (compositing())
@@ -598,6 +545,7 @@ void Client::destroyDecoration()
 
 bool Client::checkBorderSizes(bool also_resize)
 {
+#if 0
     if (decoration == NULL)
         return false;
 
@@ -630,25 +578,28 @@ bool Client::checkBorderSizes(bool also_resize)
     QRect oldgeom = geometry();
     plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
     checkWorkspacePosition(oldgeom);
+#endif
     return true;
 }
 
 void Client::triggerDecorationRepaint()
 {
-    if (decoration && decoration->widget())
-        decoration->widget()->update();
+    if (m_decoration) {
+        m_decoration->update();
+    }
 }
 
 void Client::layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect \
&bottom, Client::CoordinateMode mode) const  {
-    QRect r = decoration->rect();
-    if (mode == WindowRelative)
-        r.translate(-padding_left, -padding_top);
+    if (!m_decoration) {
+        return;
+    }
+    QRect r = m_decoration->rect();
 
     NETStrut strut = info->frameOverlap();
 
     // Ignore the overlap strut when compositing is disabled
-    if (!compositing() || !decorationPlugin()->supportsFrameOverlap())
+    if (!compositing())
         strut.left = strut.top = strut.right = strut.bottom = 0;
     else if (strut.left == -1 && strut.top == -1 && strut.right == -1 && \
strut.bottom == -1) {  top = QRect(r.x(), r.y(), r.width(), r.height() / 3);
@@ -658,20 +609,13 @@ void Client::layoutDecorationRects(QRect &left, QRect &top, \
QRect &right, QRect  return;
     }
 
-    top = QRect(r.x(), r.y(), r.width(), padding_top + border_top + strut.top);
-    bottom = QRect(r.x(), r.y() + r.height() - padding_bottom - border_bottom - \
                strut.bottom,
-                   r.width(), padding_bottom + border_bottom + strut.bottom);
+    top = QRect(r.x(), r.y(), r.width(), borderTop() + strut.top);
+    bottom = QRect(r.x(), r.y() + r.height() - borderBottom() - strut.bottom,
+                   r.width(), borderBottom() + strut.bottom);
     left = QRect(r.x(), r.y() + top.height(),
-                 padding_left + border_left + strut.left, r.height() - top.height() \
                - bottom.height());
-    right = QRect(r.x() + r.width() - padding_right - border_right - strut.right, \
                r.y() + top.height(),
-                  padding_right + border_right + strut.right, r.height() - \
                top.height() - bottom.height());
-}
-
-QRegion Client::decorationPendingRegion() const
-{
-    if (!paintRedirector)
-        return QRegion();
-    return paintRedirector->scheduledRepaintRegion().translated(x() - padding_left, \
y() - padding_top); +                 borderLeft() + strut.left, r.height() - \
top.height() - bottom.height()); +    right = QRect(r.x() + r.width() - borderRight() \
- strut.right, r.y() + top.height(), +                  borderRight() + strut.right, \
r.height() - top.height() - bottom.height());  }
 
 QRect Client::transparentRect() const
@@ -681,7 +625,7 @@ QRect Client::transparentRect() const
 
     NETStrut strut = info->frameOverlap();
     // Ignore the strut when compositing is disabled or the decoration doesn't \
                support it
-    if (!compositing() || !decorationPlugin()->supportsFrameOverlap())
+    if (!compositing())
         strut.left = strut.top = strut.right = strut.bottom = 0;
     else if (strut.left == -1 && strut.top == -1 && strut.right == -1 && \
strut.bottom == -1)  return QRect();
@@ -733,10 +677,10 @@ void Client::detectNoBorder()
 void Client::updateFrameExtents()
 {
     NETStrut strut;
-    strut.left = border_left;
-    strut.right = border_right;
-    strut.top = border_top;
-    strut.bottom = border_bottom;
+    strut.left = borderLeft();
+    strut.right = borderRight();
+    strut.top = borderTop();
+    strut.bottom = borderBottom();
     info->setFrameExtents(strut);
 }
 
@@ -756,32 +700,16 @@ void Client::detectGtkFrameExtents()
  */
 void Client::resizeDecoration(const QSize& s)
 {
-    if (decoration == NULL)
-        return;
-    QSize newSize = s + QSize(padding_left + padding_right, padding_top + \
                padding_bottom);
-    QSize oldSize = decoration->window()->size();
-    decoration->resize(newSize);
-    if (oldSize == newSize) {
-        QResizeEvent e(newSize, oldSize);
-        QObject *receiver = nullptr;
-        if (decoration->widget()) {
-            receiver = decoration->widget();
-        } else {
-            receiver = decoration->window();
-        }
-        QApplication::sendEvent(receiver, &e);
-    } else if (paintRedirector) { // oldSize != newSize
-        paintRedirector->resizePixmaps();
-    } else {
-        triggerDecorationRepaint();
+    if (m_decoration) {
+        m_decoration->update();
+        updateInputWindow();
     }
-    Xcb::moveWindow(decoration->window()->winId(), -padding_left, -padding_top);
     updateInputWindow();
 }
 
 bool Client::noBorder() const
 {
-    return decorationPlugin()->isDisabled() || noborder || isFullScreen();
+    return noborder || isFullScreen();
 }
 
 bool Client::userCanSetNoBorder() const
@@ -870,59 +798,6 @@ void Client::updateInputShape()
     }
 }
 
-void Client::setMask(const QRegion& reg, int mode)
-{
-    QRegion r = reg.translated(-padding_left, -padding_right) & QRect(0, 0, width(), \
                height());
-    if (_mask == r)
-        return;
-    _mask = r;
-    xcb_connection_t *c = connection();
-    xcb_window_t shape_window = frameId();
-    if (shape()) {
-        // The same way of applying a shape without strange intermediate states like \
                above
-        if (!shape_helper_window.isValid())
-            shape_helper_window.create(QRect(0, 0, 1, 1));
-        shape_window = shape_helper_window;
-    }
-    if (_mask.isEmpty()) {
-        xcb_shape_mask(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, shape_window, 0, \
                0, XCB_PIXMAP_NONE);
-    } else {
-        const QVector< QRect > rects = _mask.rects();
-        QVector< xcb_rectangle_t > xrects(rects.count());
-        for (int i = 0; i < rects.count(); ++i) {
-            const QRect &rect = rects.at(i);
-            xcb_rectangle_t xrect;
-            xrect.x = rect.x();
-            xrect.y = rect.y();
-            xrect.width = rect.width();
-            xrect.height = rect.height();
-            xrects[i] = xrect;
-        }
-        xcb_shape_rectangles(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, mode, \
                shape_window,
-                             0, 0, xrects.count(), xrects.constData());
-    }
-    if (shape()) {
-        // The rest of the applying using a temporary window
-        xcb_rectangle_t rec = { 0, 0, static_cast<uint16_t>(clientSize().width()),
-                           static_cast<uint16_t>(clientSize().height()) };
-        xcb_shape_rectangles(c, XCB_SHAPE_SO_SUBTRACT, XCB_SHAPE_SK_BOUNDING, \
                XCB_CLIP_ORDERING_UNSORTED,
-                             shape_helper_window, clientPos().x(), clientPos().y(), \
                1, &rec);
-        xcb_shape_combine(c, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, \
                XCB_SHAPE_SK_BOUNDING,
-                          shape_helper_window, clientPos().x(), clientPos().y(), \
                window());
-        xcb_shape_combine(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, \
                XCB_SHAPE_SK_BOUNDING,
-                          frameId(), 0, 0, shape_helper_window);
-    }
-    emit geometryShapeChanged(this, geometry());
-    updateShape();
-}
-
-QRegion Client::mask() const
-{
-    if (_mask.isEmpty())
-        return QRegion(0, 0, width(), height());
-    return _mask;
-}
-
 void Client::hideClient(bool hide)
 {
     if (hidden == hide)
@@ -1066,8 +941,10 @@ void Client::setShade(ShadeMode mode)
 
     // Decorations may turn off some borders when shaded
     // this has to happen _before_ the tab alignment since it will restrict the \
minimum geometry +#if 0
     if (decoration)
         decoration->borders(border_left, border_right, border_top, border_bottom);
+#endif
 
     // Update states of all other windows in this group
     if (tabGroup())
@@ -1079,7 +956,7 @@ void Client::setShade(ShadeMode mode)
         return; // No real change in shaded state
     }
 
-    assert(decoration != NULL);   // noborder windows can't be shaded
+    assert(m_decoration != NULL);   // noborder windows can't be shaded
     GeometryUpdatesBlocker blocker(this);
 
     // TODO: All this unmapping, resizing etc. feels too much duplicated from \
elsewhere @@ -1089,7 +966,7 @@ void Client::setShade(ShadeMode mode)
         // Shade
         shade_geometry_change = true;
         QSize s(sizeForClientSize(QSize(clientSize())));
-        s.setHeight(border_top + border_bottom);
+        s.setHeight(borderTop() + borderBottom());
         m_wrapper.selectInput(ClientWinMask);   // Avoid getting UnmapNotify
         m_wrapper.unmap();
         m_client.unmap();
@@ -1314,8 +1191,6 @@ void Client::map()
     // for use in effects, but now we want to have access to the new pixmap
     if (compositing())
         discardWindowPixmap();
-    if (decoration != NULL)
-        decoration->show(); // Not really necessary, but let it know the state
     m_frame.map();
     if (!isShade()) {
         m_wrapper.map();
@@ -1343,8 +1218,6 @@ void Client::unmap()
     m_client.unmap();
     m_decoInputExtent.unmap();
     m_wrapper.selectInput(ClientWinMask | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY);
-    if (decoration != NULL)
-        decoration->hide(); // Not really necessary, but let it know the state
     exportMappingState(IconicState);
 }
 
@@ -2093,8 +1966,10 @@ void Client::getMotifHints()
     motif_may_close = mclose; // Motif apps like to crash when they set this hint \
and WM closes them anyway  if (isManaged())
         updateDecoration(true);   // Check if noborder state has changed
+#if 0
     if (decoration && closabilityChanged)
         emit decoration->decorationButtonsChanged();
+#endif
 }
 
 void Client::getIcons()
@@ -2302,8 +2177,6 @@ void Client::updateCursor()
     if (c == m_cursor)
         return;
     m_cursor = c;
-    if (decoration != NULL)
-        decoration->window()->setCursor(m_cursor);
     xcb_cursor_t nativeCursor = Cursor::x11Cursor(m_cursor);
     m_frame.defineCursor(nativeCursor);
     if (m_decoInputExtent.isValid())
@@ -2326,8 +2199,29 @@ void Client::setBlockingCompositing(bool block)
 
 Client::Position Client::mousePosition(const QPoint& p) const
 {
-    if (decoration != NULL)
-        return decoration->mousePosition(p);
+    Q_UNUSED(p)
+    if (m_decoration) {
+        switch (m_decoration->windowFrameSection()) {
+            case Qt::BottomLeftSection:
+                return KDecorationDefines::PositionBottomLeft;
+            case Qt::BottomRightSection:
+                return KDecorationDefines::PositionBottomRight;
+            case Qt::BottomSection:
+                return KDecorationDefines::PositionBottom;
+            case Qt::LeftSection:
+                return KDecorationDefines::PositionLeft;
+            case Qt::RightSection:
+                return KDecorationDefines::PositionRight;
+            case Qt::TopSection:
+                return KDecorationDefines::PositionTop;
+            case Qt::TopLeftSection:
+                return KDecorationDefines::PositionTopLeft;
+            case Qt::TopRightSection:
+                return KDecorationDefines::PositionTopRight;
+            default:
+                return KDecorationDefines::PositionCenter;
+        }
+    }
     return PositionCenter;
 }
 
@@ -2360,8 +2254,10 @@ void Client::updateAllowedActions(bool force)
 
     // ONLY if relevant features have changed (and the window didn't just get/loose \
moveresize for maximization state changes)  const NET::Actions relevant = \
~(NET::ActionMove|NET::ActionResize); +#if 0
     if (decoration && (allowed_actions & relevant) != (old_allowed_actions & \
relevant))  emit decoration->decorationButtonsChanged();
+#endif
 }
 
 void Client::autoRaise()
@@ -2433,21 +2329,13 @@ void Client::setSessionInteract(bool needed)
 
 QRect Client::decorationRect() const
 {
-    if (decoration) {
-        return decoration->rect().translated(-padding_left, -padding_top);
-    } else {
-        return QRect(0, 0, width(), height());
-    }
+    return QRect(0, 0, width(), height());
 }
 
 KDecorationDefines::Position Client::titlebarPosition() const
 {
-    Position titlePos = PositionCenter; // PositionTop is returned by the default \
                implementation
-                                        // this will hint errors in the metaobject \
                usage ;-)
-    if (decoration)
-        QMetaObject::invokeMethod(decoration, "titlebarPosition", \
                Qt::DirectConnection,
-                                            \
                Q_RETURN_ARG(KDecorationDefines::Position, titlePos));
-    return titlePos;
+    // TODO: still needed, remove?
+    return PositionTop;
 }
 
 void Client::updateFirstInTabBox()
@@ -2518,6 +2406,7 @@ NET::WindowType Client::windowType(bool direct, int \
supportedTypes) const  
 bool Client::decorationHasAlpha() const
 {
+#if 0
     if (!decoration || !decorationPlugin()->hasAlpha()) {
         // either no decoration or decoration has alpha disabled
         return false;
@@ -2528,6 +2417,8 @@ bool Client::decorationHasAlpha() const
         // decoration has alpha enabled and does not support alpha announcement
         return true;
     }
+#endif
+    return true;
 }
 
 void Client::cancelFocusOutTimer()
@@ -2616,6 +2507,26 @@ void Client::sendKeybordKeyEvent(uint32_t key, \
                InputRedirection::KeyboardKeyStat
     xcb_test_fake_input(connection(), type, key + 8, XCB_TIME_CURRENT_TIME, \
frameId(), 0, 0, 0);  }
 
+#define BORDER(which) \
+    int Client::border##which() const \
+    { \
+        return m_decoration ? m_decoration->border##which() : 0; \
+    }
+
+BORDER(Bottom)
+BORDER(Left)
+BORDER(Right)
+BORDER(Top)
+#undef BORDER
+
+Decoration::DecoratedClientImpl *Client::decoratedClient()
+{
+    if (!m_decoration) {
+        return nullptr;
+    }
+    return static_cast<Decoration::DecoratedClientImpl*>(m_decoration->client()->handle());
 +}
+
 } // namespace
 
 #include "client.moc"
diff --git a/client.h b/client.h
index 3a15cbb..1fe2a56 100644
--- a/client.h
+++ b/client.h
@@ -44,6 +44,11 @@ class KStartupInfoId;
 
 struct xcb_sync_alarm_notify_event_t;
 
+namespace KDecoration2
+{
+class Decoration;
+}
+
 namespace KWin
 {
 namespace TabBox
@@ -52,8 +57,10 @@ namespace TabBox
 class TabBoxClientImpl;
 }
 
-class Bridge;
-class PaintRedirector;
+namespace Decoration
+{
+class DecoratedClientImpl;
+}
 
 
 /**
@@ -286,7 +293,6 @@ class Client
 public:
     explicit Client();
     xcb_window_t wrapperId() const;
-    xcb_window_t decorationId() const;
     xcb_window_t inputId() const { return m_decoInputExtent; }
     virtual xcb_window_t frameId() const override;
 
@@ -329,7 +335,6 @@ public:
     QPoint inputPos() const { return input_offset; } // Inside of geometry()
 
     bool windowEvent(xcb_generic_event_t *e);
-    virtual bool eventFilter(QObject* o, QEvent* e);
     void syncEvent(xcb_sync_alarm_notify_event_t* e);
     NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
 
@@ -438,9 +443,6 @@ public:
     }
     void demandAttention(bool set = true);
 
-    void setMask(const QRegion& r, int mode = XCB_CLIP_ORDERING_UNSORTED);
-    QRegion mask() const;
-
     void updateDecoration(bool check_workspace_pos, bool force = false);
     bool checkBorderSizes(bool also_resize);
     void triggerDecorationRepaint();
@@ -589,29 +591,18 @@ public:
     }
 
     // Decorations <-> Effects
-    PaintRedirector *decorationPaintRedirector() {
-        return paintRedirector;
-    }
-
-    int paddingLeft() const {
-        return padding_left;
-    }
-    int paddingRight() const {
-        return padding_right;
+    KDecoration2::Decoration *decoration() {
+        return m_decoration;
     }
-    int paddingTop() const {
-        return padding_top;
-    }
-    int paddingBottom() const {
-        return padding_bottom;
+    const KDecoration2::Decoration *decoration() const {
+        return m_decoration;
     }
+    Decoration::DecoratedClientImpl *decoratedClient();
 
     QRect decorationRect() const;
 
     QRect transparentRect() const;
 
-    QRegion decorationPendingRegion() const;
-
     bool decorationHasAlpha() const;
     bool isClientSideDecorated() const;
 
@@ -684,10 +675,6 @@ private Q_SLOTS:
     void shadeUnhover();
 
 private:
-    friend class Bridge; // FRAME
-    virtual void processMousePressEvent(QMouseEvent* e);
-
-private:
     // Use Workspace::createClient()
     virtual ~Client(); ///< Use destroyClient() or releaseWindow()
 
@@ -789,6 +776,10 @@ Q_SIGNALS:
     void clientSideDecoratedChanged();
 
 private:
+    int borderLeft() const;
+    int borderRight() const;
+    int borderTop() const;
+    int borderBottom() const;
     void exportMappingState(int s);   // ICCCM 4.1.3.1, 4.1.4, NETWM 2.5.1
     bool isManaged() const; ///< Returns false if this client is not yet managed
     void updateAllowedActions(bool force = false);
@@ -869,8 +860,7 @@ private:
     Xcb::Window m_frame;
     // wrapper around m_frame to use as a parent for the decoration
     QScopedPointer<QWindow> m_frameWrapper;
-    KDecoration* decoration;
-    Bridge* bridge;
+    KDecoration2::Decoration *m_decoration;
     int desk;
     QStringList activityList;
     int m_activityUpdatesBlocked;
@@ -991,15 +981,11 @@ private:
         QTimer *timeout, *failsafeTimeout;
         bool isPending;
     } syncRequest;
-    int border_left, border_right, border_top, border_bottom;
-    int padding_left, padding_right, padding_top, padding_bottom;
-    QRegion _mask;
     static bool check_active_modal; ///< \see Client::checkActiveModal()
     QKeySequence _shortcut;
     int sm_stacking_order;
     friend struct ResetupRulesProcedure;
     friend class GeometryUpdatesBlocker;
-    PaintRedirector* paintRedirector;
     QSharedPointer<TabBox::TabBoxClientImpl> m_tabBoxClient;
     bool m_firstInTabBox;
 
@@ -1050,14 +1036,6 @@ inline xcb_window_t Client::wrapperId() const
     return m_wrapper;
 }
 
-inline xcb_window_t Client::decorationId() const
-{
-    if (decoration) {
-        return decoration->window()->winId();
-    }
-    return XCB_WINDOW_NONE;
-}
-
 inline bool Client::isClientSideDecorated() const
 {
     return m_clientSideDecorated;
@@ -1223,7 +1201,7 @@ inline bool Client::isManaged() const
 
 inline QPoint Client::clientPos() const
 {
-    return QPoint(border_left, border_top);
+    return QPoint(borderLeft(), borderTop());
 }
 
 inline QSize Client::clientSize() const
diff --git a/composite.cpp b/composite.cpp
index 1913d1f..5408077 100644
--- a/composite.cpp
+++ b/composite.cpp
@@ -1106,10 +1106,6 @@ bool Client::setupCompositing()
         return false;
     }
     updateVisibility(); // for internalKeep()
-    if (isManaged()) {
-        // only create the decoration when a client is managed
-        updateDecoration(true, true);
-    }
     return true;
 }
 
@@ -1118,8 +1114,7 @@ void Client::finishCompositing(ReleaseReason releaseReason)
     Toplevel::finishCompositing(releaseReason);
     updateVisibility();
     if (!deleting) {
-        // only recreate the decoration if we are not shutting down completely
-        updateDecoration(true, true);
+        triggerDecorationRepaint();
     }
     // for safety in case KWin is just resizing the window
     s_haveResizeEffect = false;
diff --git a/decorations.cpp b/decorations.cpp
deleted file mode 100644
index 2e66f18..0000000
--- a/decorations.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/********************************************************************
- KWin - the KDE window manager
- This file is part of the KDE project.
-
-Copyright (C) 1999, 2000    Daniel M. Duley <mosfet@kde.org>
-Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*********************************************************************/
-
-#include "decorations.h"
-#include "config-kwin.h"
-#include "client.h"
-#include "workspace.h"
-#include <kdecorationfactory.h>
-
-#include <KLocalizedString>
-#include <stdlib.h>
-#include <QPixmap>
-
-namespace KWin
-{
-
-KWIN_SINGLETON_FACTORY(DecorationPlugin)
-
-DecorationPlugin::DecorationPlugin(QObject *parent)
-    : QObject(parent)
-    , KDecorationPlugins(KSharedConfig::openConfig())
-    , m_disabled(false)
-{
-    defaultPlugin = QStringLiteral("Oxygen");
-#ifdef KWIN_BUILD_DECORATIONS
-    loadPlugin(QString());   // load the plugin specified in cfg file
-    connect(factory(), &KDecorationFactory::recreateDecorations, this, \
                &DecorationPlugin::recreateDecorations);
-    connect(this, &DecorationPlugin::compositingToggled, options, \
                &KDecorationOptions::compositingChanged);
-#else
-    setDisabled(true);
-#endif
-}
-
-DecorationPlugin::~DecorationPlugin()
-{
-    s_self = NULL;
-}
-
-void DecorationPlugin::error(const QString &error_msg)
-{
-    qWarning("%s", QString(i18n("KWin: ") + error_msg).toLocal8Bit().data());
-
-    setDisabled(true);
-}
-
-bool DecorationPlugin::provides(Requirement)
-{
-    return false;
-}
-
-void DecorationPlugin::setDisabled(bool disabled)
-{
-    m_disabled = disabled;
-}
-
-bool DecorationPlugin::isDisabled() const
-{
-    return m_disabled;
-}
-
-bool DecorationPlugin::hasShadows() const
-{
-    if (m_disabled) {
-        return false;
-    }
-    return factory()->supports(AbilityProvidesShadow);
-}
-
-bool DecorationPlugin::hasAlpha() const
-{
-    if (m_disabled) {
-        return false;
-    }
-    return factory()->supports(AbilityUsesAlphaChannel);
-}
-
-bool DecorationPlugin::supportsAnnounceAlpha() const
-{
-    if (m_disabled) {
-        return false;
-    }
-    return factory()->supports(AbilityAnnounceAlphaChannel);
-}
-
-bool DecorationPlugin::supportsTabbing() const
-{
-    if (m_disabled) {
-        return false;
-    }
-    return factory()->supports(AbilityTabbing);
-}
-
-bool DecorationPlugin::supportsFrameOverlap() const
-{
-    if (m_disabled) {
-        return false;
-    }
-    return factory()->supports(AbilityExtendIntoClientArea);
-}
-
-bool DecorationPlugin::supportsBlurBehind() const
-{
-    if (m_disabled) {
-        return false;
-    }
-    return factory()->supports(AbilityUsesBlurBehind);
-}
-
-Qt::Corner DecorationPlugin::closeButtonCorner()
-{
-    if (m_disabled) {
-        return Qt::TopRightCorner;
-    }
-    return factory()->closeButtonCorner();
-}
-
-QString DecorationPlugin::supportInformation()
-{
-    if (m_disabled) {
-        return QStringLiteral("Decoration Plugin disabled\n");
-    }
-    QString support;
-    support.append(QStringLiteral("Current Plugin: "));
-    support.append(currentPlugin());
-    support.append(QStringLiteral("\n"));
-
-    support.append(QStringLiteral("Shadows: "));
-    support.append(hasShadows() ? QStringLiteral("yes\n") : QStringLiteral("no\n"));
-
-    support.append(QStringLiteral("Alpha: "));
-    support.append(hasAlpha() ? QStringLiteral("yes\n") : QStringLiteral("no\n"));
-
-    support.append(QStringLiteral("Announces Alpha: "));
-    support.append(supportsAnnounceAlpha() ? QStringLiteral("yes\n") : \
                QStringLiteral("no\n"));
-
-    support.append(QStringLiteral("Tabbing: "));
-    support.append(supportsTabbing() ? QStringLiteral("yes\n") : \
                QStringLiteral("no\n"));
-
-    support.append(QStringLiteral("Frame Overlap: "));
-    support.append(supportsFrameOverlap() ? QStringLiteral("yes\n") : \
                QStringLiteral("no\n"));
-
-    support.append(QStringLiteral("Blur Behind: "));
-    support.append(supportsBlurBehind() ? QStringLiteral("yes\n") : \
                QStringLiteral("no\n"));
-    // TODO: Qt5 - read support information from Factory
-    return support;
-}
-
-void DecorationPlugin::recreateDecorations()
-{
-    if (m_disabled) {
-        return;
-    }
-    // Decorations need to be recreated
-    workspace()->forEachClient([](Client *c) {
-        c->updateDecoration(true, true);
-    });
-    // If the new decoration doesn't supports tabs then ungroup clients
-    if (!supportsTabbing()) {
-        workspace()->forEachClient([](Client *c) {
-            c->untab();
-        });
-    }
-}
-
-} // namespace
diff --git a/decorations.h b/decorations.h
deleted file mode 100644
index 694c2ca..0000000
--- a/decorations.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/********************************************************************
- KWin - the KDE window manager
- This file is part of the KDE project.
-
-Copyright (C) 1999, 2000    Daniel M. Duley <mosfet@kde.org>
-Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*********************************************************************/
-
-#ifndef KWIN_PLUGINS_H
-#define KWIN_PLUGINS_H
-
-#include <kdecoration_plugins_p.h>
-#include <kwinglobals.h>
-
-namespace KWin
-{
-
-class DecorationPlugin
-    : public QObject, public KDecorationPlugins
-{
-    Q_OBJECT
-public:
-    virtual ~DecorationPlugin();
-    virtual bool provides(Requirement);
-    /**
-     * @returns @c true if there is no decoration plugin.
-     **/
-    bool isDisabled() const;
-
-    bool hasShadows() const;
-    bool hasAlpha() const;
-    bool supportsAnnounceAlpha() const;
-    bool supportsTabbing() const;
-    bool supportsFrameOverlap() const;
-    bool supportsBlurBehind() const;
-    Qt::Corner closeButtonCorner();
-
-    QString supportInformation();
-
-Q_SIGNALS:
-    void compositingToggled();
-
-public Q_SLOTS:
-    void recreateDecorations();
-protected:
-    virtual void error(const QString& error_msg);
-private:
-    void setDisabled(bool noDecoration);
-    bool m_disabled;
-    KWIN_SINGLETON(DecorationPlugin)
-};
-
-inline DecorationPlugin *decorationPlugin() {
-    return DecorationPlugin::self();
-}
-
-} // namespace
-
-#endif
diff --git a/decorations/decoratedclient.cpp b/decorations/decoratedclient.cpp
new file mode 100644
index 0000000..d69177c
--- /dev/null
+++ b/decorations/decoratedclient.cpp
@@ -0,0 +1,201 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#include "decoratedclient.h"
+#include "decorationrenderer.h"
+#include "client.h"
+#include "composite.h"
+#include "cursor.h"
+#include "options.h"
+#include "scene.h"
+#include "workspace.h"
+
+#include <KDecoration2/DecoratedClient>
+#include <KDecoration2/Decoration>
+
+#include <QDebug>
+
+namespace KWin
+{
+namespace Decoration
+{
+
+DecoratedClientImpl::DecoratedClientImpl(Client *client, \
KDecoration2::DecoratedClient *decoratedClient, KDecoration2::Decoration *decoration) \
+    : QObject() +    , DecoratedClientPrivate(decoratedClient, decoration)
+    , m_client(client)
+    , m_renderer(nullptr)
+{
+    createRenderer();
+    connect(client, &Client::activeChanged, this,
+        [decoratedClient, client]() {
+            emit decoratedClient->activeChanged(client->isActive());
+        }
+    );
+    connect(client, &Client::geometryChanged, this,
+        [decoratedClient, client]() {
+            emit decoratedClient->widthChanged(client->clientSize().width());
+            emit decoratedClient->heightChanged(client->clientSize().height());
+        }
+    );
+    connect(client, &Client::desktopChanged, this,
+        [decoratedClient, client]() {
+            emit decoratedClient->onAllDesktopsChanged(client->isOnAllDesktops());
+        }
+    );
+    connect(client, &Client::captionChanged, this,
+        [decoratedClient, client]() {
+            emit decoratedClient->captionChanged(client->caption());
+        }
+    );
+    connect(client, &Client::iconChanged, this,
+        [decoratedClient, client]() {
+            emit decoratedClient->iconChanged(client->icon());
+        }
+    );
+    connect(client, &Client::shadeChanged, this,
+        [decoratedClient, client]() {
+            // TODO: geometry is wrong
+            emit decoratedClient->shadedChanged(client->isShade());
+        }
+    );
+    connect(client, &Client::keepAboveChanged, decoratedClient, \
&KDecoration2::DecoratedClient::keepAboveChanged); +    connect(client, \
&Client::keepBelowChanged, decoratedClient, \
&KDecoration2::DecoratedClient::keepBelowChanged); +    // closeable, etc.
+    connect(Compositor::self(), &Compositor::compositingToggled, this,
+        [this, decoration]() {
+            delete m_renderer;
+            m_renderer = nullptr;
+            createRenderer();
+            decoration->update();
+        }
+    );
+}
+
+DecoratedClientImpl::~DecoratedClientImpl() = default;
+
+#define DELEGATE(type, name) \
+    type DecoratedClientImpl::name() const \
+    { \
+        return m_client->name(); \
+    }
+
+DELEGATE(QString, caption)
+DELEGATE(bool, isActive)
+DELEGATE(bool, isCloseable)
+DELEGATE(bool, isMaximizable)
+DELEGATE(bool, isMinimizable)
+DELEGATE(bool, isModal)
+DELEGATE(bool, isMovable)
+DELEGATE(bool, isResizable)
+DELEGATE(bool, isShadeable)
+DELEGATE(bool, providesContextHelp)
+DELEGATE(int, desktop)
+DELEGATE(bool, isOnAllDesktops)
+DELEGATE(QPalette, palette)
+DELEGATE(QIcon, icon)
+
+#undef DELEGATE
+
+#define DELEGATE(type, name, clientName) \
+    type DecoratedClientImpl::name() const \
+    { \
+        return m_client->clientName(); \
+    }
+
+DELEGATE(bool, isKeepAbove, keepAbove)
+DELEGATE(bool, isKeepBelow, keepBelow)
+DELEGATE(bool, isShaded, isShade)
+DELEGATE(WId, windowId, window)
+DELEGATE(WId, decorationId, frameId)
+
+#undef DELEGATE
+
+#define DELEGATE(name, op) \
+    void DecoratedClientImpl::name() \
+    { \
+        Workspace::self()->performWindowOperation(m_client, KDecorationDefines::op); \
\ +    }
+
+DELEGATE(requestToggleShade, ShadeOp)
+DELEGATE(requestToggleOnAllDesktops, OnAllDesktopsOp)
+DELEGATE(requestToggleKeepAbove, KeepAboveOp)
+DELEGATE(requestToggleKeepBelow, KeepBelowOp)
+
+#undef DELEGATE
+
+#define DELEGATE(name, clientName) \
+    void DecoratedClientImpl::name() \
+    { \
+        m_client->clientName(); \
+    }
+
+DELEGATE(requestContextHelp, showContextHelp)
+DELEGATE(requestMinimize, minimize)
+DELEGATE(requestClose, closeWindow)
+
+#undef DELEGATE
+
+void DecoratedClientImpl::requestShowWindowMenu()
+{
+    // TODO: add rect to requestShowWindowMenu
+    Workspace::self()->showWindowMenu(QRect(Cursor::pos(), Cursor::pos()), \
m_client); +}
+
+void DecoratedClientImpl::requestMaximize(Qt::MouseButtons buttons)
+{
+    Workspace::self()->performWindowOperation(m_client, \
options->operationMaxButtonClick(buttons)); +}
+
+int DecoratedClientImpl::width() const
+{
+    return m_client->clientSize().width();
+}
+
+int DecoratedClientImpl::height() const
+{
+    return m_client->clientSize().height();
+}
+
+bool DecoratedClientImpl::isMaximizedVertically() const
+{
+    return m_client->maximizeMode() & KDecorationDefines::MaximizeVertical;
+}
+
+bool DecoratedClientImpl::isMaximized() const
+{
+    return isMaximizedHorizontally() && isMaximizedVertically();
+}
+
+bool DecoratedClientImpl::isMaximizedHorizontally() const
+{
+    return m_client->maximizeMode() & KDecorationDefines::MaximizeHorizontal;
+}
+
+void DecoratedClientImpl::createRenderer()
+{
+    if (Compositor::self()->hasScene()) {
+        m_renderer = Compositor::self()->scene()->createDecorationRenderer(this);
+    } else {
+        m_renderer = new X11Renderer(this);
+    }
+}
+
+}
+}
diff --git a/decorations/decoratedclient.h b/decorations/decoratedclient.h
new file mode 100644
index 0000000..482853c
--- /dev/null
+++ b/decorations/decoratedclient.h
@@ -0,0 +1,97 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#ifndef KWIN_DECORATED_CLIENT_H
+#define KWIN_DECORATED_CLIENT_H
+
+#include <KDecoration2/Private/DecoratedClientPrivate>
+
+#include <QObject>
+
+namespace KWin
+{
+
+class Client;
+
+namespace Decoration
+{
+
+class Renderer;
+
+class DecoratedClientImpl : public QObject, public \
KDecoration2::DecoratedClientPrivate +{
+    Q_OBJECT
+public:
+    explicit DecoratedClientImpl(Client *client, KDecoration2::DecoratedClient \
*decoratedClient, KDecoration2::Decoration *decoration); +    virtual \
~DecoratedClientImpl(); +    QString caption() const override;
+    WId decorationId() const override;
+    int desktop() const override;
+    int height() const override;
+    QIcon icon() const override;
+    bool isActive() const override;
+    bool isCloseable() const override;
+    bool isKeepAbove() const override;
+    bool isKeepBelow() const override;
+    bool isMaximizable() const override;
+    bool isMaximized() const override;
+    bool isMaximizedHorizontally() const override;
+    bool isMaximizedVertically() const override;
+    bool isMinimizable() const override;
+    bool isModal() const override;
+    bool isMovable() const override;
+    bool isOnAllDesktops() const override;
+    bool isResizable() const override;
+    bool isShadeable() const override;
+    bool isShaded() const override;
+    QPalette palette() const override;
+    bool providesContextHelp() const override;
+    int width() const override;
+    WId windowId() const override;
+
+    void requestClose() override;
+    void requestContextHelp() override;
+    void requestMaximize(Qt::MouseButtons buttons) override;
+    void requestMinimize() override;
+    void requestShowWindowMenu() override;
+    void requestToggleKeepAbove() override;
+    void requestToggleKeepBelow() override;
+    void requestToggleOnAllDesktops() override;
+    void requestToggleShade() override;
+
+    Client *client() {
+        return m_client;
+    }
+    Renderer *renderer() {
+        return m_renderer;
+    }
+    KDecoration2::DecoratedClient *decoratedClient() {
+        return KDecoration2::DecoratedClientPrivate::client();
+    }
+
+private:
+    void createRenderer();
+    Client *m_client;
+    Renderer *m_renderer;
+};
+
+}
+}
+
+#endif
diff --git a/decorations/decorationbridge.cpp b/decorations/decorationbridge.cpp
new file mode 100644
index 0000000..2d43954
--- /dev/null
+++ b/decorations/decorationbridge.cpp
@@ -0,0 +1,113 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#include "decorationbridge.h"
+#include "decoratedclient.h"
+#include "decorationrenderer.h"
+#include "settings.h"
+// KWin core
+#include "client.h"
+#include "composite.h"
+#include "scene.h"
+
+// KDecoration
+#include <KDecoration2/Decoration>
+#include <KDecoration2/DecoratedClient>
+#include <KDecoration2/DecorationSettings>
+
+// Frameworks
+#include <KPluginTrader>
+#include <KPluginLoader>
+
+// Qt
+#include <QDebug>
+#include <QPainter>
+
+namespace KWin
+{
+namespace Decoration
+{
+
+static const QString s_pluginName = QStringLiteral("org.kde.kdecoration2");
+
+DecorationBridge::DecorationBridge(QObject *parent)
+    : QObject(parent)
+    , KDecoration2::DecorationBridge()
+    , m_factory(nullptr)
+{
+}
+
+DecorationBridge::~DecorationBridge() = default;
+
+DecorationBridge *DecorationBridge::self()
+{
+    return static_cast<KWin::Decoration::DecorationBridge*>(KDecoration2::DecorationBridge::self());
 +}
+
+void DecorationBridge::init()
+{
+    KDecoration2::DecorationSettings::self(this);
+
+    // TODO: configurable plugin
+    const auto offers = KPluginTrader::self()->query(s_pluginName,
+                                                     s_pluginName,
+                                                     \
QStringLiteral("[X-KDE-PluginInfo-Name] == \
'%1'").arg(QStringLiteral("org.kde.breeze"))); +    if (offers.isEmpty()) {
+        qWarning() << "Could not locate decoration plugin";
+        return;
+    }
+    qDebug() << "Trying to load decoration plugin: " << \
offers.first().libraryPath(); +    KPluginLoader \
loader(offers.first().libraryPath()); +    KPluginFactory *factory = \
loader.factory(); +    if (!factory) {
+        qWarning() << "Error loading plugin:" << loader.errorString();
+    } else {
+        m_factory = factory;
+    }
+}
+
+KDecoration2::DecoratedClientPrivate \
*DecorationBridge::createClient(KDecoration2::DecoratedClient *client, \
KDecoration2::Decoration *decoration) +{
+    return new DecoratedClientImpl(static_cast<Client*>(decoration->parent()), \
client, decoration); +}
+
+KDecoration2::DecorationSettingsPrivate \
*DecorationBridge::settings(KDecoration2::DecorationSettings *parent) +{
+    return new SettingsImpl(parent);
+}
+
+void DecorationBridge::update(KDecoration2::Decoration *decoration, const QRect \
&geometry) +{
+    // TODO: remove check once all compositors implement it
+    if (Renderer *renderer = \
static_cast<DecoratedClientImpl*>(decoration->client()->handle())->renderer()) { +    \
renderer->schedule(geometry); +    }
+}
+
+KDecoration2::Decoration *DecorationBridge::createDecoration(Client *client)
+{
+    if (!m_factory) {
+        return nullptr;
+    }
+    return m_factory->create<KDecoration2::Decoration>(client);
+}
+
+
+} // Decoration
+} // KWin
diff --git a/decorations/decorationbridge.h b/decorations/decorationbridge.h
new file mode 100644
index 0000000..c203de2
--- /dev/null
+++ b/decorations/decorationbridge.h
@@ -0,0 +1,58 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#ifndef KWIN_DECORATION_BRIDGE_H
+#define KWIN_DECORATION_BRIDGE_H
+
+#include <KDecoration2/Private/DecorationBridge>
+
+#include <QObject>
+
+class KPluginFactory;
+
+namespace KWin
+{
+
+class Client;
+
+namespace Decoration
+{
+
+class DecorationBridge : public QObject, public KDecoration2::DecorationBridge
+{
+    Q_OBJECT
+public:
+    explicit DecorationBridge(QObject *parent);
+    virtual ~DecorationBridge();
+
+    void init();
+    KDecoration2::Decoration *createDecoration(Client *client);
+
+    KDecoration2::DecoratedClientPrivate *createClient(KDecoration2::DecoratedClient \
*client, KDecoration2::Decoration *decoration) override; +    \
KDecoration2::DecorationSettingsPrivate *settings(KDecoration2::DecorationSettings \
*parent) override; +    void update(KDecoration2::Decoration *decoration, const QRect \
&geometry) override; +
+    static DecorationBridge *self();
+private:
+    KPluginFactory *m_factory;
+};
+} // Decoration
+} // KWin
+
+#endif
diff --git a/decorations/decorationrenderer.cpp b/decorations/decorationrenderer.cpp
new file mode 100644
index 0000000..7a451af
--- /dev/null
+++ b/decorations/decorationrenderer.cpp
@@ -0,0 +1,134 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#include "decorationrenderer.h"
+#include "decoratedclient.h"
+#include "client.h"
+
+#include <kwinglobals.h>
+
+#include <KDecoration2/Decoration>
+#include <KDecoration2/DecoratedClient>
+
+#include <QDebug>
+#include <QPainter>
+#include <QTimer>
+
+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)
+{
+    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);
+    return image;
+}
+
+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<void \
(QTimer::*)()>(&QTimer::start)); +}
+
+X11Renderer::~X11Renderer()
+{
+    if (m_gc != XCB_NONE) {
+        xcb_free_gc(connection(), m_gc);
+    }
+}
+
+void X11Renderer::render()
+{
+    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, \
Client::DecorationRelative); +
+    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, 24, \
image.byteCount(), image.constBits()); +    };
+    renderPart(left);
+    renderPart(top);
+    renderPart(right);
+    renderPart(bottom);
+
+    xcb_flush(c);
+    resetImageSizesDirty();
+}
+
+}
+}
diff --git a/decorations/decorationrenderer.h b/decorations/decorationrenderer.h
new file mode 100644
index 0000000..8242a05
--- /dev/null
+++ b/decorations/decorationrenderer.h
@@ -0,0 +1,94 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#ifndef KWIN_DECORATION_RENDERER_H
+#define KWIN_DECORATION_RENDERER_H
+
+#include <QObject>
+#include <QRegion>
+
+#include <xcb/xcb.h>
+
+class QTimer;
+
+namespace KWin
+{
+
+namespace Decoration
+{
+
+class DecoratedClientImpl;
+
+class Renderer : public QObject
+{
+    Q_OBJECT
+public:
+    virtual ~Renderer();
+
+    void schedule(const QRect &rect);
+
+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
+public:
+    explicit X11Renderer(DecoratedClientImpl *client);
+    virtual ~X11Renderer();
+
+protected:
+    void render() override;
+
+private:
+    QTimer *m_scheduleTimer;
+    xcb_gcontext_t m_gc;
+};
+
+}
+}
+
+#endif
diff --git a/decorations/settings.cpp b/decorations/settings.cpp
new file mode 100644
index 0000000..520e9a0
--- /dev/null
+++ b/decorations/settings.cpp
@@ -0,0 +1,77 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#include "settings.h"
+// KWin
+#include "composite.h"
+#include "virtualdesktops.h"
+
+#include <KDecoration2/DecorationSettings>
+
+namespace KWin
+{
+namespace Decoration
+{
+SettingsImpl::SettingsImpl(KDecoration2::DecorationSettings *parent)
+    : QObject()
+    , DecorationSettingsPrivate(parent)
+{
+    connect(Compositor::self(), &Compositor::compositingToggled,
+            parent, \
&KDecoration2::DecorationSettings::alphaChannelSupportedChanged); +    \
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::countChanged, this, +  \
[parent](uint previous, uint current) { +            if (previous != 1 && current != \
1) { +                return;
+            }
+            emit parent->onAllDesktopsAvailableChanged(current > 1);
+        }
+    );
+}
+
+SettingsImpl::~SettingsImpl() = default;
+
+bool SettingsImpl::isAlphaChannelSupported() const
+{
+    return Compositor::self()->compositing();
+}
+
+bool SettingsImpl::isOnAllDesktopsAvailable() const
+{
+    return VirtualDesktopManager::self()->count() > 1;
+}
+
+QList< KDecoration2::DecorationButtonType > SettingsImpl::decorationButtonsLeft() \
const +{
+    return QList<KDecoration2::DecorationButtonType >({
+        KDecoration2::DecorationButtonType::Menu,
+        KDecoration2::DecorationButtonType::OnAllDesktops
+    });
+}
+
+QList< KDecoration2::DecorationButtonType > SettingsImpl::decorationButtonsRight() \
const +{
+    return QList<KDecoration2::DecorationButtonType >({
+        KDecoration2::DecorationButtonType::Minimize,
+        KDecoration2::DecorationButtonType::Maximize,
+        KDecoration2::DecorationButtonType::Close
+    });
+}
+
+}
+}
diff --git a/decorations/settings.h b/decorations/settings.h
new file mode 100644
index 0000000..51c0604
--- /dev/null
+++ b/decorations/settings.h
@@ -0,0 +1,46 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#ifndef KWIN_DECORATION_SETTINGS_H
+#define KWIN_DECORATION_SETTINGS_H
+
+#include <KDecoration2/Private/DecorationSettingsPrivate>
+
+#include <QObject>
+
+namespace KWin
+{
+namespace Decoration
+{
+
+class SettingsImpl : public QObject, public KDecoration2::DecorationSettingsPrivate
+{
+    Q_OBJECT
+public:
+    explicit SettingsImpl(KDecoration2::DecorationSettings *parent);
+    virtual ~SettingsImpl();
+    bool isAlphaChannelSupported() const override;
+    bool isOnAllDesktopsAvailable() const override;
+    QList< KDecoration2::DecorationButtonType > decorationButtonsLeft() const \
override; +    QList< KDecoration2::DecorationButtonType > decorationButtonsRight() \
const override; +};
+} // Decoration
+} // KWin
+
+#endif
diff --git a/deleted.cpp b/deleted.cpp
index a65aa64..a092ccb 100644
--- a/deleted.cpp
+++ b/deleted.cpp
@@ -23,7 +23,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "workspace.h"
 #include "client.h"
 #include "netinfo.h"
-#include "paintredirector.h"
 #include "shadow.h"
 
 #include <QDebug>
@@ -43,7 +42,6 @@ Deleted::Deleted()
     , m_layer(UnknownLayer)
     , m_minimized(false)
     , m_modal(false)
-    , m_paintRedirector(NULL)
     , m_wasClient(false)
 {
 }
@@ -88,21 +86,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 (PaintRedirector *redirector = client->decorationPaintRedirector()) {
-                redirector->ensurePixmapsPainted();
-                redirector->reparent(this);
-                m_paintRedirector = redirector;
-            }
         }
         m_minimized = client->isMinimized();
         m_modal = client->isModal();
diff --git a/deleted.h b/deleted.h
index acaebe8..79b6311 100644
--- a/deleted.h
+++ b/deleted.h
@@ -25,7 +25,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  
 namespace KWin
 {
-class PaintRedirector;
 
 class Deleted
     : public Toplevel
@@ -64,9 +63,6 @@ public:
         return m_mainClients;
     }
     NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
-    PaintRedirector *decorationPaintRedirector() {
-        return m_paintRedirector;
-    }
     bool wasClient() const {
         return m_wasClient;
     }
@@ -97,7 +93,6 @@ private:
     bool m_minimized;
     bool m_modal;
     ClientList m_mainClients;
-    PaintRedirector *m_paintRedirector;
     bool m_wasClient;
 };
 
diff --git a/effects.cpp b/effects.cpp
index 8680023..bc3c0be 100644
--- a/effects.cpp
+++ b/effects.cpp
@@ -26,7 +26,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #ifdef KWIN_BUILD_ACTIVITIES
 #include "activities.h"
 #endif
-#include "decorations.h"
 #include "deleted.h"
 #include "client.h"
 #include "cursor.h"
@@ -492,17 +491,17 @@ void EffectsHandlerImpl::buildQuads(EffectWindow* w, \
WindowQuadList& quadList)  
 bool EffectsHandlerImpl::hasDecorationShadows() const
 {
-    return decorationPlugin()->hasShadows();
+    return false;
 }
 
 bool EffectsHandlerImpl::decorationsHaveAlpha() const
 {
-    return decorationPlugin()->hasAlpha();
+    return true;
 }
 
 bool EffectsHandlerImpl::decorationSupportsBlurBehind() const
 {
-    return decorationPlugin()->supportsBlurBehind();
+    return true;
 }
 
 // start another painting pass
@@ -1441,7 +1440,7 @@ QVariant EffectsHandlerImpl::kwinOption(KWinOption kwopt)
 {
     switch (kwopt) {
     case CloseButtonCorner:
-        return decorationPlugin()->closeButtonCorner();
+        return Qt::TopRightCorner;
 #ifdef KWIN_BUILD_SCREENEDGES
     case SwitchDesktopOnScreenEdge:
         return ScreenEdges::self()->isDesktopSwitching();
diff --git a/events.cpp b/events.cpp
index 7736e61..63ddddd 100644
--- a/events.cpp
+++ b/events.cpp
@@ -27,7 +27,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  
 #include "client.h"
 #include "cursor.h"
-#include "decorations.h"
 #include "focuschain.h"
 #include "netinfo.h"
 #include "workspace.h"
@@ -47,6 +46,8 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "screens.h"
 #include "xcbutils.h"
 
+#include <KDecoration2/Decoration>
+
 #include <QApplication>
 #include <QDebug>
 #include <QWhatsThis>
@@ -312,25 +313,8 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
         }
     }
     if (movingClient) {
-        if (eventType == XCB_BUTTON_PRESS || eventType == XCB_BUTTON_RELEASE) {
-            Client *c = movingClient;
+        if (eventType == XCB_BUTTON_PRESS || eventType == XCB_BUTTON_RELEASE || \
                eventType == XCB_MOTION_NOTIFY) {
             if (movingClient->moveResizeGrabWindow() == \
reinterpret_cast<xcb_button_press_event_t*>(e)->event && \
                movingClient->windowEvent(e)) {
-                // we need to pass the button release event to the decoration, \
                otherwise Qt still thinks the button is pressed.
-                if (eventType == XCB_BUTTON_RELEASE && c->decorationId() != \
                XCB_WINDOW_NONE) {
-                    // the event is for the moveResizeGrabWindow and Qt doesn't \
                forward that to the decoration
-                    // so we need to send the event to the decoration ourselves
-                    // TODO check whether m_moveResizeWindow can be offscreen and \
                XAllowEvents be sufficient here
-                    xcb_button_release_event_t event = \
                *(reinterpret_cast<xcb_button_release_event_t*>(e));
-                    event.event = c->decorationId();
-                    event.child = XCB_WINDOW_NONE;
-                    event.event_x = event.root_x - c->x() + c->paddingLeft();
-                    event.event_y = event.root_y - c->y() + c->paddingTop();
-                    xcb_send_event(connection(), false, c->decorationId(), \
                XCB_EVENT_MASK_BUTTON_RELEASE, reinterpret_cast<const \
                char*>(&event));
-                }
-                return true;
-            }
-        } else if (eventType == XCB_MOTION_NOTIFY) {
-            if (movingClient->moveResizeGrabWindow() == \
reinterpret_cast<xcb_motion_notify_event_t*>(e)->event && \
movingClient->windowEvent(e)) {  return true;
             }
         }
@@ -686,6 +670,14 @@ bool Client::windowEvent(xcb_generic_event_t *e)
     case XCB_CLIENT_MESSAGE:
         clientMessageEvent(reinterpret_cast<xcb_client_message_event_t*>(e));
         break;
+    case XCB_EXPOSE: {
+        xcb_expose_event_t *event = reinterpret_cast<xcb_expose_event_t*>(e);
+        if (event->window == frameId() && !Compositor::self()->isActive()) {
+            // TODO: only repaint required areas
+            triggerDecorationRepaint();
+        }
+        break;
+    }
     default:
         if (eventType == Xcb::Extensions::self()->shapeNotifyEvent() && \
reinterpret_cast<xcb_shape_notify_event_t*>(e)->affected_window == window()) {  \
detectShape(window());  // workaround for #19644 @@ -1036,65 +1028,6 @@ void \
Client::updateMouseGrab()  }
 }
 
-// Qt propagates mouse events up the widget hierachy, which means events
-// for the decoration window cannot be (easily) intercepted as X11 events
-bool Client::eventFilter(QObject* o, QEvent* e)
-{
-    if (decoration == NULL
-            || (o != decoration->widget() && o != decoration->window()))
-        return false;
-    if (e->type() == QEvent::MouseButtonPress && decoration->widget()) {
-        QMouseEvent* ev = static_cast< QMouseEvent* >(e);
-        return buttonPressEvent(decorationId(), qtToX11Button(ev->button()), \
                qtToX11State(ev->buttons(), ev->modifiers()),
-                                ev->x(), ev->y(), ev->globalX(), ev->globalY());
-    }
-    if (e->type() == QEvent::MouseButtonRelease) {
-        QMouseEvent* ev = static_cast< QMouseEvent* >(e);
-        return buttonReleaseEvent(decorationId(), qtToX11Button(ev->button()), \
                qtToX11State(ev->buttons(), ev->modifiers()),
-                                  ev->x(), ev->y(), ev->globalX(), ev->globalY());
-    }
-    if (e->type() == QEvent::MouseMove) { // FRAME i fake z enter/leave?
-        QMouseEvent* ev = static_cast< QMouseEvent* >(e);
-        return motionNotifyEvent(decorationId(), qtToX11State(ev->buttons(), \
                ev->modifiers()),
-                                 ev->x(), ev->y(), ev->globalX(), ev->globalY());
-    }
-    if (e->type() == QEvent::Wheel) {
-        QWheelEvent* ev = static_cast< QWheelEvent* >(e);
-        bool r = buttonPressEvent(decorationId(), ev->delta() > 0 ? Button4 : \
                Button5, qtToX11State(ev->buttons(), ev->modifiers()),
-                                  ev->x(), ev->y(), ev->globalX(), ev->globalY());
-        r = r || buttonReleaseEvent(decorationId(), ev->delta() > 0 ? Button4 : \
                Button5, qtToX11State(ev->buttons(), ev->modifiers()),
-                                    ev->x(), ev->y(), ev->globalX(), ev->globalY());
-        return r;
-    }
-    if (e->type() == QEvent::Resize && decoration->widget()) {
-        QResizeEvent* ev = static_cast< QResizeEvent* >(e);
-        // Filter out resize events that inform about size different than frame \
                size.
-        // This will ensure that decoration->width() etc. and \
                decoration->widget()->width() will be in sync.
-        // These events only seem to be delayed events from initial resizing before \
                show() was called
-        // on the decoration widget.
-        if (ev->size() != (size() + QSize(padding_left + padding_right, padding_top \
                + padding_bottom)))
-            return true;
-        // HACK: Avoid decoration redraw delays. On resize Qt sets \
                WA_WStateConfigPending
-        // which delays all painting until a matching ConfigureNotify event comes.
-        // But this process itself is the window manager, so it's not needed
-        // to wait for that event, the geometry is known.
-        // Note that if Qt in the future changes how this flag is handled and what \
                it
-        // triggers then this may potentionally break things. See mainly \
                QETWidget::translateConfigEvent().
-        decoration->widget()->setAttribute(Qt::WA_WState_ConfigPending, false);
-        decoration->widget()->update();
-        return false;
-    }
-    if (e->type() == QEvent::ZOrderChange) {
-        // when the user actions menu is closed by clicking on the window decoration \
                (which is not unlikely)
-        // Qt will raise the decoration window and thus the decoration window is \
                above the actual Client
-        // see QWidgetWindow::handleMouseEvent \
                (qtbase/src/widgets/kernel/qwidgetwindow.cpp)
-        // when this happens also a ZOrderChange event is sent, we intercept all of \
                them and make sure that
-        // the window is lowest in stack again.
-        Xcb::lowerWindow(decorationId());
-    }
-    return false;
-}
-
 static bool modKeyDown(int state) {
     const uint keyModX = (options->keyCmdAllModKey() == Qt::Key_Meta) ?
                                                     KKeyServer::modXMeta() : \
KKeyServer::modXAlt(); @@ -1111,7 +1044,7 @@ bool \
Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int  return \
true;  }
 
-    if (w == wrapperId() || w == frameId() || w == decorationId() || w == inputId()) \
{ +    if (w == wrapperId() || w == frameId() || w == inputId()) {
         // FRAME neco s tohohle by se melo zpracovat, nez to dostane dekorace
         updateUserTime(time);
         workspace()->setWasUserInteraction();
@@ -1189,16 +1122,22 @@ bool Client::buttonPressEvent(xcb_window_t w, int button, int \
state, int x, int  return true;
     }
     if (w == inputId()) {
-        x = x_root - geometry().x() + padding_left;
-        y = y_root - geometry().y() + padding_top;
+        x = x_root - geometry().x();
+        y = y_root - geometry().y();
         // New API processes core events FIRST and only passes unused ones to the \
                decoration
         return processDecorationButtonPress(button, state, x, y, x_root, y_root, \
true);  }
-    if (w == decorationId()) {
-        return false;
+    if (w == frameId() && m_decoration) {
+        qDebug() << "Button press on frame";
+        QMouseEvent event(QEvent::MouseButtonPress, QPointF(x, y), QPointF(x_root, \
y_root), +                          x11ToQtMouseButton(button), \
x11ToQtMouseButtons(state), x11ToQtKeyboardModifiers(state)); +        \
event.setAccepted(false); +        QCoreApplication::sendEvent(m_decoration, &event);
+        if (!event.isAccepted()) {
+            processDecorationButtonPress(button, state, x, y, x_root, y_root);
+        }
+        return true;
     }
-    if (w == frameId())
-        processDecorationButtonPress(button, state, x, y, x_root, y_root);
     return true;
 }
 
@@ -1225,7 +1164,7 @@ bool Client::processDecorationButtonPress(int button, int \
/*state*/, int x, int  && com != Options::MouseDragTab) {
         mode = mousePosition(QPoint(x, y));
         buttonDown = true;
-        moveOffset = QPoint(x - padding_left, y - padding_top);
+        moveOffset = QPoint(x/* - padding_left*/, y/* - padding_top*/);
         invertedMoveOffset = rect().bottomRight() - moveOffset;
         unrestrictedMoveResize = false;
         startDelayedMoveResize();
@@ -1246,40 +1185,19 @@ bool Client::processDecorationButtonPress(int button, int \
/*state*/, int x, int  com == Options::MouseNothing);
 }
 
-// called from decoration
-void Client::processMousePressEvent(QMouseEvent* e)
-{
-    if (e->type() != QEvent::MouseButtonPress) {
-        qWarning() << "processMousePressEvent()" ;
-        return;
-    }
-    int button;
-    switch(e->button()) {
-    case Qt::LeftButton:
-        button = XCB_BUTTON_INDEX_1;
-        break;
-    case Qt::MidButton:
-        button = XCB_BUTTON_INDEX_2;
-        break;
-    case Qt::RightButton:
-        button = XCB_BUTTON_INDEX_3;
-        break;
-    default:
-        return;
-    }
-    processDecorationButtonPress(button, e->buttons(), e->x(), e->y(), e->globalX(), \
                e->globalY());
-}
-
 // return value matters only when filtering events before decoration gets them
 bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, \
int x_root, int y_root)  {
-    if (w == decorationId() && !buttonDown)
-        return false;
+    if (w == frameId() && m_decoration) {
+        qDebug() << "Button release on frame";
+        QMouseEvent event(QEvent::MouseButtonRelease, QPointF(x, y), QPointF(x_root, \
y_root), x11ToQtMouseButton(button), x11ToQtMouseButtons(state), \
x11ToQtKeyboardModifiers(state)); +        QCoreApplication::sendEvent(m_decoration, \
&event); +    }
     if (w == wrapperId()) {
         xcb_allow_events(connection(), XCB_ALLOW_SYNC_POINTER, \
XCB_TIME_CURRENT_TIME);  //xTime());  return true;
     }
-    if (w != frameId() && w != decorationId() && w != inputId() && w != \
moveResizeGrabWindow()) +    if (w != frameId() && w != inputId() && w != \
moveResizeGrabWindow())  return true;
     x = this->x(); // translate from grab window to local coords
     y = this->y();
@@ -1299,10 +1217,9 @@ bool Client::buttonReleaseEvent(xcb_window_t w, int button, \
int state, int x, in  if (moveResizeMode) {
             finishMoveResize(false);
             // mouse position is still relative to old Client position, adjust it
-            QPoint mousepos(x_root - x + padding_left, y_root - y + padding_top);
+            QPoint mousepos(x_root - x, y_root - y);
             mode = mousePosition(mousepos);
-        } else if (decorationPlugin()->supportsTabbing())
-            return false;
+        }
         updateCursor();
     }
     return true;
@@ -1342,15 +1259,18 @@ void Client::checkQuickTilingMaximizationZones(int xroot, int \
yroot)  // return value matters only when filtering events before decoration gets \
them  bool Client::motionNotifyEvent(xcb_window_t w, int state, int x, int y, int \
x_root, int y_root)  {
-    if (w != frameId() && w != decorationId() && w != inputId() && w != \
moveResizeGrabWindow()) +    if (w == frameId() && m_decoration) {
+        // TODO Mouse move event dependent on state
+        QHoverEvent event(QEvent::HoverMove, QPointF(x, y), QPointF(x, y));
+        QCoreApplication::instance()->sendEvent(m_decoration, &event);
+    }
+    if (w != frameId() && w != inputId() && w != moveResizeGrabWindow())
         return true; // care only about the whole frame
     if (!buttonDown) {
         QPoint mousePos(x, y);
-        if (w == frameId())
-            mousePos += QPoint(padding_left, padding_top);
         if (w == inputId()) {
-            int x = x_root - geometry().x() + padding_left;
-            int y = y_root - geometry().y() + padding_top;
+            int x = x_root - geometry().x();// + padding_left;
+            int y = y_root - geometry().y();// + padding_top;
             mousePos = QPoint(x, y);
         }
         Position newmode = modKeyDown(state) ? PositionCenter : \
                mousePosition(mousePos);
diff --git a/geometry.cpp b/geometry.cpp
index 8e7e59d..196d1ab 100644
--- a/geometry.cpp
+++ b/geometry.cpp
@@ -48,6 +48,9 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  
 #include "outline.h"
 
+#include <KDecoration2/Decoration>
+#include <KDecoration2/DecoratedClient>
+
 namespace KWin
 {
 
@@ -1239,8 +1242,8 @@ void Client::checkOffscreenPosition(QRect* geom, const QRect& \
screenArea)  QSize Client::adjustedSize(const QSize& frame, Sizemode mode) const
 {
     // first, get the window size for the given frame size s
-    QSize wsize(frame.width() - (border_left + border_right),
-                frame.height() - (border_top + border_bottom));
+    QSize wsize(frame.width() - (borderLeft() + borderRight()),
+                frame.height() - (borderTop() + borderBottom()));
     if (wsize.isEmpty())
         wsize = QSize(1, 1);
 
@@ -1276,9 +1279,9 @@ QSize Client::sizeForClientSize(const QSize& wsize, Sizemode \
mode, bool noframe)  // even if they're not set in flags - see getWmNormalHints()
     QSize min_size = tabGroup() ? tabGroup()->minSize() : minSize();
     QSize max_size = tabGroup() ? tabGroup()->maxSize() : maxSize();
-    if (decoration != NULL) {
-        QSize decominsize = decoration->minimumSize();
-        QSize border_size(border_left + border_right, border_top + border_bottom);
+    if (m_decoration != NULL) {
+        QSize decominsize(0, 0);
+        QSize border_size(borderLeft() + borderRight(), borderTop() + \
borderBottom());  if (border_size.width() > decominsize.width())  // just in case
             decominsize.setWidth(border_size.width());
         if (border_size.height() > decominsize.height())
@@ -1424,8 +1427,8 @@ QSize Client::sizeForClientSize(const QSize& wsize, Sizemode \
mode, bool noframe)  }
 
     if (!noframe) {
-        w += border_left + border_right;
-        h += border_top + border_bottom;
+        w += borderLeft() + borderRight();
+        h += borderTop() + borderBottom();
     }
     return rules()->checkSize(QSize(w, h));
 }
@@ -1556,19 +1559,19 @@ const QPoint Client::calculateGravitation(bool invert, int \
gravity) const  switch(gravity) {
     case NorthWestGravity: // move down right
     default:
-        dx = border_left;
-        dy = border_top;
+        dx = borderLeft();
+        dy = borderTop();
         break;
     case NorthGravity: // move right
         dx = 0;
-        dy = border_top;
+        dy = borderTop();
         break;
     case NorthEastGravity: // move down left
-        dx = -border_right;
-        dy = border_top;
+        dx = -borderRight();
+        dy = borderTop();
         break;
     case WestGravity: // move right
-        dx = border_left;
+        dx = borderLeft();
         dy = 0;
         break;
     case CenterGravity:
@@ -1578,30 +1581,30 @@ const QPoint Client::calculateGravitation(bool invert, int \
gravity) const  dy = 0;
         break;
     case EastGravity: // move left
-        dx = -border_right;
+        dx = -borderRight();
         dy = 0;
         break;
     case SouthWestGravity: // move up right
-        dx = border_left ;
-        dy = -border_bottom;
+        dx = borderLeft() ;
+        dy = -borderBottom();
         break;
     case SouthGravity: // move up
         dx = 0;
-        dy = -border_bottom;
+        dy = -borderBottom();
         break;
     case SouthEastGravity: // move up left
-        dx = -border_right;
-        dy = -border_bottom;
+        dx = -borderRight();
+        dy = -borderBottom();
         break;
     }
     if (gravity != CenterGravity) {
         // translate from client movement to frame movement
-        dx -= border_left;
-        dy -= border_top;
+        dx -= borderLeft();
+        dy -= borderTop();
     } else {
         // center of the frame will be at the same position client center without \
                frame would be
-        dx = - (border_left + border_right) / 2;
-        dy = - (border_top + border_bottom) / 2;
+        dx = - (borderLeft() + borderRight()) / 2;
+        dy = - (borderTop() + borderBottom()) / 2;
     }
     if (!invert)
         return QPoint(x() + dx, y() + dy);
@@ -1740,7 +1743,7 @@ void Client::resizeWithChecks(int w, int h, ForceGeometry_t \
force)  {
     assert(!shade_geometry_change);
     if (isShade()) {
-        if (h == border_top + border_bottom) {
+        if (h == borderTop() + borderBottom()) {
             qWarning() << "Shaded geometry passed for size:" ;
         }
     }
@@ -1892,14 +1895,14 @@ void Client::setGeometry(int x, int y, int w, int h, \
ForceGeometry_t force)  if (shade_geometry_change)
         ; // nothing
     else if (isShade()) {
-        if (h == border_top + border_bottom) {
+        if (h == borderTop() + borderBottom()) {
             qDebug() << "Shaded geometry passed for size:";
         } else {
-            client_size = QSize(w - border_left - border_right, h - border_top - \
                border_bottom);
-            h = border_top + border_bottom;
+            client_size = QSize(w - borderLeft() - borderRight(), h - borderTop() - \
borderBottom()); +            h = borderTop() + borderBottom();
         }
     } else {
-        client_size = QSize(w - border_left - border_right, h - border_top - \
border_bottom); +        client_size = QSize(w - borderLeft() - borderRight(), h - \
borderTop() - borderBottom());  }
     QRect g(x, y, w, h);
     if (block_geometry_updates == 0 && g != rules()->checkGeometry(g)) {
@@ -1980,14 +1983,14 @@ void Client::plainResize(int w, int h, ForceGeometry_t force)
     if (shade_geometry_change)
         ; // nothing
     else if (isShade()) {
-        if (h == border_top + border_bottom) {
+        if (h == borderTop() + borderBottom()) {
             qDebug() << "Shaded geometry passed for size:";
         } else {
-            client_size = QSize(w - border_left - border_right, h - border_top - \
                border_bottom);
-            h = border_top + border_bottom;
+            client_size = QSize(w - borderLeft() - borderRight(), h - borderTop() - \
borderBottom()); +            h = borderTop() + borderBottom();
         }
     } else {
-        client_size = QSize(w - border_left - border_right, h - border_top - \
border_bottom); +        client_size = QSize(w - borderLeft() - borderRight(), h - \
borderTop() - borderBottom());  }
     QSize s(w, h);
     if (block_geometry_updates == 0 && s != rules()->checkSize(s)) {
@@ -2208,6 +2211,19 @@ void Client::changeMaximize(bool vertical, bool horizontal, \
bool adjust)  changeMaximize(false, false, false);   // restore
     }
 
+    // call into decoration update borders
+    if (m_decoration) {
+        if ((max_mode & KDecorationDefines::MaximizeVertical) != (old_mode & \
KDecorationDefines::MaximizeVertical)) { +            emit \
m_decoration->client()->maximizedVerticallyChanged(max_mode & \
KDecorationDefines::MaximizeVertical); +        }
+        if ((max_mode & KDecorationDefines::MaximizeHorizontal) != (old_mode & \
KDecorationDefines::MaximizeHorizontal)) { +            emit \
m_decoration->client()->maximizedHorizontallyChanged(max_mode & \
KDecorationDefines::MaximizeHorizontal); +        }
+        if ((max_mode == KDecorationDefines::MaximizeFull) != (old_mode == \
KDecorationDefines::MaximizeFull)) { +            emit \
m_decoration->client()->maximizedChanged(max_mode & \
KDecorationDefines::MaximizeFull); +        }
+    }
+
     // save sizes for restoring, if maximalizing
     QSize sz;
     if (isShade())
@@ -2234,7 +2250,7 @@ void Client::changeMaximize(bool vertical, bool horizontal, \
bool adjust)  changeMaximizeRecursion = false;
     }
 
-    const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? \
ForceGeometrySet : NormalGeometrySet; +    const ForceGeometry_t geom_mode = \
m_decoration ? ForceGeometrySet : NormalGeometrySet;  
     // Conditional quick tiling exit points
     if (quick_tile_mode != QuickTileNone) {
@@ -2692,12 +2708,12 @@ void Client::checkUnrestrictedMoveResize()
     int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
     // restricted move/resize - keep at least part of the titlebar always visible
     // how much must remain visible when moved away in that direction
-    left_marge = qMin(100 + border_right, moveResizeGeom.width());
-    right_marge = qMin(100 + border_left, moveResizeGeom.width());
+    left_marge = qMin(100 + borderRight(), moveResizeGeom.width());
+    right_marge = qMin(100 + borderLeft(), moveResizeGeom.width());
     // width/height change with opaque resizing, use the initial ones
     titlebar_marge = initialMoveResizeGeom.height();
-    top_marge = border_bottom;
-    bottom_marge = border_top;
+    top_marge = borderBottom();
+    bottom_marge = borderTop();
     if (isResize()) {
         if (moveResizeGeom.bottom() < desktopArea.top() + top_marge)
             unrestrictedMoveResize = true;
@@ -2760,7 +2776,7 @@ void Client::handleMoveResize(int x, int y, int x_root, int \
y_root)  return;
 
     if (!moveResizeMode) {
-        QPoint p(QPoint(x - padding_left, y - padding_top) - moveOffset);
+        QPoint p(QPoint(x/* - padding_left*/, y/* - padding_top*/) - moveOffset);
         if (p.manhattanLength() >= QApplication::startDragDistance()) {
             if (!startMoveResize()) {
                 buttonDown = false;
@@ -2787,7 +2803,7 @@ void Client::handleMoveResize(int x, int y, int x_root, int \
y_root)  
     // When doing a restricted move we must always keep 100px of the titlebar
     // visible to allow the user to be able to move it again.
-    const int frameTop = border_top;
+    const int frameTop = borderTop();
     int titlebarArea = qMin(frameTop * 100, moveResizeGeom.width() * \
moveResizeGeom.height());  
     bool update = false;
@@ -3033,7 +3049,7 @@ void Client::handleMoveResize(int x, int y, int x_root, int \
                y_root)
             syncRequest.isPending = true;   // limit the resizes to 30Hz to take \
                pointless load from X11
             syncRequest.timeout->start(33); // and the client, the mouse is still \
                moved at full speed
         }                                   // and no human can control faster \
                resizes anyway
-        m_client.setGeometry(0, 0, moveResizeGeom.width() - (border_left + \
border_right), moveResizeGeom.height() - (border_top + border_bottom)); +        \
m_client.setGeometry(0, 0, moveResizeGeom.width() - (borderLeft() + borderRight()), \
moveResizeGeom.height() - (borderTop() + borderBottom()));  } else
         performMoveResize();
 
@@ -3156,7 +3172,7 @@ void Client::setQuickTileMode(QuickTileMode mode, bool \
keyboard)  if (mode != QuickTileNone) {
             quick_tile_mode = mode;
             // decorations may turn off some borders when tiled
-            const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) \
? ForceGeometrySet : NormalGeometrySet; +            const ForceGeometry_t geom_mode \
                = m_decoration ? ForceGeometrySet : NormalGeometrySet;
             quick_tile_mode = QuickTileNone; // Temporary, so the maximize code \
                doesn't get all confused
             setGeometry(electricBorderMaximizeGeometry(keyboard ? \
geometry().center() : Cursor::pos(), desktop()), geom_mode);  }
@@ -3220,7 +3236,7 @@ void Client::setQuickTileMode(QuickTileMode mode, bool \
keyboard)  if (mode != QuickTileNone) {
             quick_tile_mode = mode;
             // decorations may turn off some borders when tiled
-            const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) \
? ForceGeometrySet : NormalGeometrySet; +            const ForceGeometry_t geom_mode \
= m_decoration ? ForceGeometrySet : NormalGeometrySet;  // Temporary, so the maximize \
code doesn't get all confused  quick_tile_mode = QuickTileNone;
             setGeometry(electricBorderMaximizeGeometry(whichScreen, desktop()), \
geom_mode); @@ -3238,7 +3254,7 @@ void Client::setQuickTileMode(QuickTileMode mode, \
                bool keyboard)
         if (!geom_restore.isValid()) // invalid if we started maximized and wait for \
placement  geom_restore = geometry();
         // decorations may turn off some borders when tiled
-        const ForceGeometry_t geom_mode = decoration && checkBorderSizes(false) ? \
ForceGeometrySet : NormalGeometrySet; +        const ForceGeometry_t geom_mode = \
m_decoration ? ForceGeometrySet : NormalGeometrySet;  setGeometry(geom_restore, \
geom_mode);  checkWorkspacePosition(); // Just in case it's a different screen
     }
diff --git a/manage.cpp b/manage.cpp
index b8c1454..4763006 100644
--- a/manage.cpp
+++ b/manage.cpp
@@ -29,7 +29,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "activities.h"
 #endif
 #include "cursor.h"
-#include "decorations.h"
 #include <QX11Info>
 #include "rules.h"
 #include "group.h"
@@ -321,7 +320,7 @@ bool Client::manage(xcb_window_t w, bool isMapped)
     // Create client group if the window will have a decoration
     bool dontKeepInArea = false;
     setTabGroup(NULL);
-    if (!noBorder() && DecorationPlugin::self()->supportsTabbing()) {
+    if (!noBorder() && false) {
         const bool autogrouping = \
                rules()->checkAutogrouping(options->isAutogroupSimilarWindows());
         const bool autogroupInFg = \
rules()->checkAutogroupInForeground(options->isAutogroupInForeground());  // \
Automatically add to previous groups on session restore @@ -678,7 +677,7 @@ void \
Client::embedClient(xcb_window_t w, xcb_visualid_t visualid, xcb_colormap_t  \
                XCB_EVENT_MASK_EXPOSURE |
                                        XCB_EVENT_MASK_STRUCTURE_NOTIFY | \
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;  
-    const uint32_t frame_event_mask   = common_event_mask | \
XCB_EVENT_MASK_PROPERTY_CHANGE; +    const uint32_t frame_event_mask   = \
common_event_mask | XCB_EVENT_MASK_PROPERTY_CHANGE | \
                XCB_EVENT_MASK_VISIBILITY_CHANGE;
     const uint32_t wrapper_event_mask = common_event_mask | \
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;  
     const uint32_t client_event_mask = XCB_EVENT_MASK_FOCUS_CHANGE | \
                XCB_EVENT_MASK_PROPERTY_CHANGE |
diff --git a/netinfo.cpp b/netinfo.cpp
index 85983b4..9f4bb9c 100644
--- a/netinfo.cpp
+++ b/netinfo.cpp
@@ -25,7 +25,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include <kdecorationfactory.h>
 // kwin
 #include "client.h"
-#include "decorations.h"
 #include "virtualdesktops.h"
 #include "workspace.h"
 // Qt
@@ -121,10 +120,6 @@ RootInfo *RootInfo::create()
         NET::ActionChangeDesktop |
         NET::ActionClose;
 
-    DecorationPlugin *deco = DecorationPlugin::self();
-    if (!deco->isDisabled() && \
                deco->factory()->supports(KDecorationDefines::AbilityExtendIntoClientArea))
                
-        properties2 |= NET::WM2FrameOverlap;
-
     s_self = new RootInfo(supportWindow, "KWin", properties, types, states, \
properties2, actions, screen_number);  return s_self;
 }
diff --git a/paintredirector.cpp b/paintredirector.cpp
deleted file mode 100644
index 4e1f956..0000000
--- a/paintredirector.cpp
+++ /dev/null
@@ -1,561 +0,0 @@
-/*****************************************************************
-This file is part of the KDE project.
-
-Copyright (C) 2009 Lubos Lunak <l.lunak@kde.org>
-Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-******************************************************************/
-
-#include "paintredirector.h"
-
-#include "client.h"
-#include "deleted.h"
-#include "effects.h"
-#include <kwinglplatform.h>
-#include <kwinglutils.h>
-#include <kwinxrenderutils.h>
-#include <QPaintEngine>
-#include <qevent.h>
-#include <qpainter.h>
-#include <qmath.h>
-
-namespace KWin
-{
-
-PaintRedirector *PaintRedirector::create(Client *c, KDecoration *deco)
-{
-    if (effects->isOpenGLCompositing()) {
-        return new OpenGLPaintRedirector(c, deco);
-    } else if (effects->compositingType() == XRenderCompositing) {
-        return new RasterXRenderPaintRedirector(c, deco);
-    } else if (effects->compositingType() == QPainterCompositing) {
-        return new QImagePaintRedirector(c, deco);
-    }
-    return NULL;
-}
-
-PaintRedirector::PaintRedirector(Client *c, KDecoration *deco)
-    : QObject(deco)
-    , widget(deco->widget())
-    , recursionCheck(false)
-    , m_client(c)
-    , m_decoration(deco)
-    , m_requiresRepaint(false)
-{
-    added(deco->widget());
-}
-
-PaintRedirector::~PaintRedirector()
-{
-}
-
-void PaintRedirector::reparent(Deleted *d)
-{
-    setParent(d);
-    widget = NULL;
-    m_client = NULL;
-    m_decoration = NULL;
-}
-
-static int align(int value, int align)
-{
-    return (value + align - 1) & ~(align - 1);
-}
-
-void PaintRedirector::performPendingPaint()
-{
-    if (!widget && !m_decoration->window()) {
-        return;
-    }
-    //qDebug() << "### performing paint, pending:" << pending.boundingRect();
-    const QSize size = pending.boundingRect().size();
-    QPaintDevice *scratch = this->scratch();
-    if (scratch->width() < size.width() || scratch->height() < size.height()) {
-        int w = align(size.width(), 128);
-        int h = align(size.height(), 128);
-        scratch = recreateScratch(QSize(qMax(scratch->width(), w), \
                qMax(scratch->height(), h)));
-    }
-    fillScratch(Qt::transparent);
-    recursionCheck = true;
-    m_decoration->render(scratch, pending.boundingRect());
-    recursionCheck = false;
-    cleanupTimer.start(2000, this);
-}
-
-bool PaintRedirector::isToolTip(QWidget *object) const
-{
-    // ### We need a more reliable way of doing this
-    return object->windowFlags() & Qt::ToolTip;
-}
-
-bool PaintRedirector::eventFilter(QObject* o, QEvent* e)
-{
-    if (!widget || !m_client) {
-        return false;
-    }
-    switch(e->type()) {
-    case QEvent::ChildAdded: {
-        QChildEvent* c = static_cast< QChildEvent* >(e);
-        if (c->child()->isWidgetType() && !isToolTip(static_cast< QWidget* \
                >(c->child())))
-            added(static_cast< QWidget* >(c->child()));
-        break;
-    }
-    case QEvent::ChildRemoved: {
-        QChildEvent* c = static_cast< QChildEvent* >(e);
-        if (c->child()->isWidgetType())
-            removed(static_cast< QWidget* >(c->child()));
-        break;
-    }
-    case QEvent::Paint: {
-        if (!recursionCheck) {
-            QPaintEvent* pe = static_cast< QPaintEvent* >(e);
-            QWidget* w = static_cast< QWidget* >(o);
-            pending |= pe->region().translated(w->mapTo(widget, QPoint(0, 0)));
-            scheduled = pending;
-
-            // schedule repaint
-            const int paddingLeft = m_client->paddingLeft();
-            const int paddingTop = m_client->paddingTop();
-            const bool needsTranslate = (paddingLeft != 0 || paddingTop != 0);
-            m_client->addRepaint(needsTranslate ? pending.translated(-paddingLeft, \
                -paddingTop) : pending);
-            m_requiresRepaint = true;
-            return true; // filter out
-        }
-    }
-    default:
-        break;
-    }
-    return false;
-}
-
-void PaintRedirector::addRepaint(const QRegion &region)
-{
-    pending |= region;
-    scheduled = pending;
-
-    // schedule repaint
-    const int paddingLeft = m_client->paddingLeft();
-    const int paddingTop = m_client->paddingTop();
-    const bool needsTranslate = (paddingLeft != 0 || paddingTop != 0);
-    m_client->addRepaint(needsTranslate ? pending.translated(-paddingLeft, \
                -paddingTop) : pending);
-    m_requiresRepaint = true;
-}
-
-QRegion PaintRedirector::pendingRegion() const
-{
-    return pending;
-}
-
-QRegion PaintRedirector::scheduledRepaintRegion()
-{
-    QRegion tempRegion = scheduled;
-    scheduled = QRegion();
-    return tempRegion;
-}
-
-void PaintRedirector::added(QWidget* w)
-{
-    if (!w) {
-        return;
-    }
-    w->installEventFilter(this);
-    foreach (QObject * o, w->children()) {
-        if (o->isWidgetType() && !isToolTip(static_cast< QWidget* >(o)))
-            added(static_cast< QWidget* >(o));
-    }
-}
-
-void PaintRedirector::removed(QWidget* w)
-{
-    foreach (QObject * o, w->children()) {
-        if (o->isWidgetType())
-            removed(static_cast< QWidget* >(o));
-    }
-    w->installEventFilter(this);
-}
-
-void PaintRedirector::timerEvent(QTimerEvent* event)
-{
-    if (event->timerId() == cleanupTimer.timerId()) {
-        cleanupTimer.stop();
-        discardScratch();
-    }
-}
-
-void PaintRedirector::ensurePixmapsPainted()
-{
-    if (pending.isEmpty() || !m_client)
-        return;
-
-    performPendingPaint();
-
-    QRect rects[PixmapCount];
-    m_client->layoutDecorationRects(rects[LeftPixmap], rects[TopPixmap], \
                rects[RightPixmap], rects[BottomPixmap], Client::DecorationRelative);
-
-    updatePixmaps(rects, pending);
-
-    pending = QRegion();
-    scheduled = QRegion();
-
-    xcb_flush(connection());
-}
-
-void PaintRedirector::updatePixmaps(const QRect *rects, const QRegion &region)
-{
-    for (int i = 0; i < PixmapCount; ++i) {
-        if (!rects[i].isValid())
-            continue;
-
-        const QRect bounding = region.boundingRect();
-        const QRegion reg = region & rects[i];
-
-        if (reg.isEmpty())
-            continue;
-
-        paint(DecorationPixmap(i), rects[i], bounding, reg);
-    }
-}
-
-void PaintRedirector::preparePaint(const QPixmap &pending)
-{
-    Q_UNUSED(pending)
-}
-
-void PaintRedirector::resizePixmaps()
-{
-    QRect rects[PixmapCount];
-    m_client->layoutDecorationRects(rects[LeftPixmap], rects[TopPixmap], \
                rects[RightPixmap], rects[BottomPixmap], Client::DecorationRelative);
-
-    resizePixmaps(rects);
-
-    // repaint
-    if (widget) {
-        widget->update();
-    }
-}
-
-void PaintRedirector::resizePixmaps(const QRect *rects)
-{
-    for (int i = 0; i < PixmapCount; ++i) {
-        resize(DecorationPixmap(i), rects[i].size());
-    }
-}
-
-GLTexture *PaintRedirector::texture(PaintRedirector::DecorationPixmap border) const
-{
-    Q_UNUSED(border)
-    return NULL;
-}
-
-xcb_render_picture_t PaintRedirector::picture(PaintRedirector::DecorationPixmap \
                border) const
-{
-    Q_UNUSED(border)
-    return XCB_RENDER_PICTURE_NONE;
-}
-
-const QImage *PaintRedirector::image(PaintRedirector::DecorationPixmap border) const
-{
-    Q_UNUSED(border)
-    return NULL;
-}
-
-void PaintRedirector::resize(DecorationPixmap border, const QSize &size)
-{
-    Q_UNUSED(border)
-    Q_UNUSED(size)
-}
-
-void PaintRedirector::paint(DecorationPixmap border, const QRect& r, const QRect &b, \
                const QRegion &reg)
-{
-    Q_UNUSED(border)
-    Q_UNUSED(r)
-    Q_UNUSED(b)
-    Q_UNUSED(reg)
-}
-
-
-
-
-// ------------------------------------------------------------------
-
-
-
-
-ImageBasedPaintRedirector::ImageBasedPaintRedirector(Client *c, KDecoration *deco)
-    : PaintRedirector(c, deco)
-{
-}
-
-ImageBasedPaintRedirector::~ImageBasedPaintRedirector()
-{
-}
-
-QPaintDevice *ImageBasedPaintRedirector::recreateScratch(const QSize &size)
-{
-    m_scratchImage = QImage(size, QImage::Format_ARGB32_Premultiplied);
-    return &m_scratchImage;
-}
-
-QPaintDevice *ImageBasedPaintRedirector::scratch()
-{
-    return &m_scratchImage;
-}
-
-void ImageBasedPaintRedirector::fillScratch(Qt::GlobalColor color)
-{
-    m_scratchImage.fill(color);
-}
-
-void ImageBasedPaintRedirector::discardScratch()
-{
-    m_scratchImage = QImage();
-}
-
-
-
-// ------------------------------------------------------------------
-
-
-OpenGLPaintRedirector::OpenGLPaintRedirector(Client *c, KDecoration *deco)
-    : ImageBasedPaintRedirector(c, deco),
-      m_texture(nullptr)
-{
-    PaintRedirector::resizePixmaps();
-}
-
-OpenGLPaintRedirector::~OpenGLPaintRedirector()
-{
-    delete m_texture;
-}
-
-void OpenGLPaintRedirector::resizePixmaps(const QRect *rects)
-{
-    QSize size;
-
-    size.rwidth() = qMax(qMax(rects[TopPixmap].width(), \
                rects[BottomPixmap].width()),
-                         qMax(rects[LeftPixmap].height(), \
                rects[RightPixmap].height()));
-    size.rheight() = rects[TopPixmap].height() + rects[BottomPixmap].height() +
-                     rects[LeftPixmap].width() + rects[RightPixmap].width() + 3;
-
-    size.rwidth() = align(size.width(), 128);
-
-    effects->makeOpenGLContextCurrent();
-    if (!GLTexture::NPOTTextureSupported()) {
-        size.rwidth()  = nearestPowerOfTwo(size.width());
-        size.rheight() = nearestPowerOfTwo(size.height());
-    }
-
-    if (m_texture && m_texture->size() == size)
-        return;
-
-    delete m_texture;
-    m_texture = 0;
-
-    if (!size.isEmpty()) {
-        m_texture = new GLTexture(size.width(), size.height());
-        m_texture->setYInverted(true);
-        m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
-        m_texture->clear();
-    }
-}
-
-// Rotates the given source rect 90 ° counter-clockwise,
-// and flips it vertically
-static QImage rotate(const QImage &srcImage, const QRect &srcRect)
-{
-    QImage image(srcRect.height(), srcRect.width(), srcImage.format());
-
-    const uint32_t *src = reinterpret_cast<const uint32_t *>(srcImage.bits());
-    uint32_t *dst = reinterpret_cast<uint32_t *>(image.bits());
-
-    for (int x = 0; x < image.width(); x++) {
-        const uint32_t *s = src + (srcRect.y() + x) * srcImage.width() + \
                srcRect.x();
-        uint32_t *d = dst + x;
-
-        for (int y = 0; y < image.height(); y++) {
-            *d = s[y];
-            d += image.width();
-        }
-    }
-
-    return image;
-}
-
-void OpenGLPaintRedirector::updatePixmaps(const QRect *rects, const QRegion &region)
-{
-    const QImage &image = scratchImage();
-    const QRect bounding = region.boundingRect();
-
-    if (!m_texture)
-        return;
-
-    // Top, Right, Bottom, Left
-    Qt::Orientation orientations[4] = { Qt::Horizontal, Qt::Vertical, \
                Qt::Horizontal, Qt::Vertical };
-
-    const int topHeight    = rects[TopPixmap].height();
-    const int bottomHeight = rects[BottomPixmap].height();
-    const int leftWidth    = rects[RightPixmap].width();
-
-    const QPoint offsets[4] = {
-        QPoint(0, 0),                                         // Top
-        QPoint(0, topHeight + bottomHeight + leftWidth + 3),  // Right
-        QPoint(0, topHeight + 1),                             // Bottom
-        QPoint(0, topHeight + bottomHeight + 2)               // Left
-    };
-
-    for (int i = 0; i < 4; i++) {
-        const QRect dirty = (region & rects[i]).boundingRect();
-        if (dirty.isEmpty())
-            continue;
-
-        const QPoint dst = dirty.topLeft() - rects[i].topLeft() + offsets[i];
-        const QRect src(dirty.topLeft() - bounding.topLeft(), dirty.size());
-
-        if (orientations[i] == Qt::Horizontal) {
-            m_texture->update(image, dst, src);
-        } else {
-            // We have to rotate the src image
-            const QImage im = rotate(image, src);
-            m_texture->update(im, dst);
-        }
-    }
-}
-
-
-
-
-// ------------------------------------------------------------------
-
-
-
-
-RasterXRenderPaintRedirector::RasterXRenderPaintRedirector(Client *c, KDecoration \
                *deco)
-    : ImageBasedPaintRedirector(c, deco)
-    , m_gc(0)
-{
-    for (int i=0; i<PixmapCount; ++i) {
-        m_pixmaps[i] = XCB_PIXMAP_NONE;
-        m_pictures[i] = NULL;
-    }
-    resizePixmaps();
-}
-
-RasterXRenderPaintRedirector::~RasterXRenderPaintRedirector()
-{
-    for (int i=0; i<PixmapCount; ++i) {
-        if (m_pixmaps[i] != XCB_PIXMAP_NONE) {
-            xcb_free_pixmap(connection(), m_pixmaps[i]);
-        }
-        delete m_pictures[i];
-    }
-    if (m_gc != 0) {
-        xcb_free_gc(connection(), m_gc);
-    }
-}
-
-xcb_render_picture_t \
                RasterXRenderPaintRedirector::picture(PaintRedirector::DecorationPixmap \
                border) const
-{
-    XRenderPicture *picture = m_pictures[border];
-    if (!picture) {
-        return XCB_RENDER_PICTURE_NONE;
-    }
-    return *picture;
-}
-
-void RasterXRenderPaintRedirector::resize(PaintRedirector::DecorationPixmap border, \
                const QSize &size)
-{
-    if (m_sizes[border] != size) {
-        m_sizes[border] = size;
-        if (m_pixmaps[border] != XCB_PIXMAP_NONE) {
-            xcb_free_pixmap(connection(), m_pixmaps[border]);
-        }
-        delete m_pictures[border];
-        if (!size.isEmpty()) {
-            m_pixmaps[border] = xcb_generate_id(connection());
-            xcb_create_pixmap(connection(), 32, m_pixmaps[border], rootWindow(), \
                size.width(), size.height());
-            m_pictures[border] = new XRenderPicture(m_pixmaps[border], 32);
-        } else {
-            m_pixmaps[border] = XCB_PIXMAP_NONE;
-            m_pictures[border] = nullptr;
-        }
-    }
-    if (!m_pictures[border]) {
-        return;
-    }
-    // fill transparent
-    xcb_rectangle_t rect = {0, 0, uint16_t(size.width()), uint16_t(size.height())};
-    xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, \
                *m_pictures[border], preMultiply(Qt::transparent), 1, &rect);
-}
-
-void RasterXRenderPaintRedirector::preparePaint(const QPixmap &pending)
-{
-    m_tempImage = pending.toImage();
-}
-
-void RasterXRenderPaintRedirector::paint(PaintRedirector::DecorationPixmap border, \
                const QRect &r, const QRect &b, const QRegion &reg)
-{
-    // clip the sub area
-    const QRect bounding = reg.boundingRect();
-    const QPoint offset = bounding.topLeft() - r.topLeft();
-    if (m_gc == 0) {
-        m_gc = xcb_generate_id(connection());
-        xcb_create_gc(connection(), m_gc, m_pixmaps[border], 0, NULL);
-    }
-
-    const QImage img(scratchImage().copy(QRect(bounding.topLeft() - b.topLeft(), \
                bounding.size())));
-    xcb_put_image(connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, m_pixmaps[border], m_gc,
-                  img.width(), img.height(), offset.x(), offset.y(), 0, 32, \
                img.byteCount(), img.constBits());
-}
-
-QImagePaintRedirector::QImagePaintRedirector(Client *c, KDecoration *deco)
-    : ImageBasedPaintRedirector(c, deco)
-{
-    resizePixmaps();
-}
-
-QImagePaintRedirector::~QImagePaintRedirector()
-{
-}
-
-void QImagePaintRedirector::paint(PaintRedirector::DecorationPixmap border, const \
                QRect &r, const QRect &b, const QRegion &reg)
-{
-    // clip the sub area
-    const QRect bounding = reg.boundingRect();
-    const QPoint offset = bounding.topLeft() - r.topLeft();
-
-    QPainter painter(&m_images[border]);
-    painter.setCompositionMode(QPainter::CompositionMode_Source);
-    painter.drawImage(offset, scratchImage(), QRect(bounding.topLeft() - \
                b.topLeft(), bounding.size()));
-}
-
-void QImagePaintRedirector::resize(PaintRedirector::DecorationPixmap border, const \
                QSize &size)
-{
-    m_images[border] = QImage(size, QImage::Format_ARGB32_Premultiplied);
-    m_images[border].fill(Qt::transparent);
-}
-
-const QImage *QImagePaintRedirector::image(PaintRedirector::DecorationPixmap border) \
                const
-{
-    return &m_images[border];
-}
-
-} // namespace
-
-#include "paintredirector.moc"
diff --git a/paintredirector.h b/paintredirector.h
deleted file mode 100644
index 9d24dc8..0000000
--- a/paintredirector.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*****************************************************************
-This file is part of the KDE project.
-
-Copyright (C) 2009 Lubos Lunak <l.lunak@kde.org>
-Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-******************************************************************/
-
-#ifndef PAINTREDIRECTOR_H
-#define PAINTREDIRECTOR_H
-
-#include <qregion.h>
-#include <qtimer.h>
-#include <qwidget.h>
-#include <qbasictimer.h>
-// xcb
-#include <xcb/render.h>
-
-class KDecoration;
-
-namespace KWin
-{
-
-// forward declarations
-class Client;
-class Deleted;
-class XRenderPicture;
-class GLTexture;
-
-// This class redirects all painting of a given widget (including its children)
-// into a paint device (QPixmap).
-class PaintRedirector
-    : public QObject
-{
-    Q_OBJECT
-public:
-    enum DecorationPixmap {
-        TopPixmap,
-        RightPixmap,
-        BottomPixmap,
-        LeftPixmap,
-        PixmapCount
-    };
-    virtual ~PaintRedirector();
-    virtual bool eventFilter(QObject* o, QEvent* e);
-    QRegion pendingRegion() const;
-    QRegion scheduledRepaintRegion();
-
-    void markAsRepainted() {
-        m_requiresRepaint = false;
-    }
-    bool requiresRepaint() const {
-        return m_requiresRepaint;
-    }
-    void resizePixmaps();
-
-    template <typename T>
-    T topDecoPixmap() const;
-    template <typename T>
-    T leftDecoPixmap() const;
-    template <typename T>
-    T bottomDecoPixmap() const;
-    template <typename T>
-    T rightDecoPixmap() const;
-
-    /**
-     * Used by Deleted::copyToDeleted() to move the PaintRedirector to the Deleted.
-     * The actual redirecting ends as the decoration gets destroyed after the \
                Deleted
-     * is created.
-     **/
-    void reparent(Deleted *d);
-    static PaintRedirector *create(Client *c, KDecoration *deco);
-
-    void addRepaint(const QRegion &region);
-
-public Q_SLOTS:
-    void ensurePixmapsPainted();
-protected:
-    PaintRedirector(Client *c, KDecoration *deco);
-    virtual xcb_render_picture_t picture(DecorationPixmap border) const;
-    virtual GLTexture *texture(DecorationPixmap border) const;
-    virtual const QImage *image(DecorationPixmap border) const;
-    virtual void resizePixmaps(const QRect *rects);
-    virtual void resize(DecorationPixmap border, const QSize &size);
-    virtual void preparePaint(const QPixmap &pending);
-    virtual void updatePixmaps(const QRect *rects, const QRegion &region);
-    virtual void paint(DecorationPixmap border, const QRect& r, const QRect &b, \
                const QRegion &reg);
-    virtual QPaintDevice *scratch() = 0;
-    virtual QPaintDevice *recreateScratch(const QSize &size) = 0;
-    virtual void fillScratch(Qt::GlobalColor color) = 0;
-    virtual void discardScratch() = 0;
-
-private:
-    void added(QWidget* widget);
-    void removed(QWidget* widget);
-    bool isToolTip(QWidget* widget) const;
-    void timerEvent(QTimerEvent* event);
-
-    void performPendingPaint();
-    void repaintPixmap(DecorationPixmap border, const QRect& r, QRegion reg);
-    QWidget* widget;
-    QRegion pending;
-    QRegion scheduled;
-    bool recursionCheck;
-    QBasicTimer cleanupTimer;
-
-    Client *m_client;
-    KDecoration *m_decoration;
-    bool m_requiresRepaint;
-};
-
-class ImageBasedPaintRedirector : public PaintRedirector
-{
-    Q_OBJECT
-public:
-    virtual ~ImageBasedPaintRedirector();
-protected:
-    ImageBasedPaintRedirector(Client *c, KDecoration *deco);
-    virtual QPaintDevice *recreateScratch(const QSize &size);
-    virtual QPaintDevice *scratch();
-    virtual void fillScratch(Qt::GlobalColor color);
-    virtual void discardScratch();
-    const QImage &scratchImage() const;
-private:
-    QImage m_scratchImage;
-};
-
-class OpenGLPaintRedirector : public ImageBasedPaintRedirector
-{
-    Q_OBJECT
-
-public:
-    OpenGLPaintRedirector(Client *c, KDecoration *deco);
-    virtual ~OpenGLPaintRedirector();
-
-    GLTexture *decorationTexture() const { return m_texture; }
-
-protected:
-    virtual void resizePixmaps(const QRect *rects);
-    virtual void updatePixmaps(const QRect *rects, const QRegion &region);
-
-private:
-    GLTexture *m_texture;
-};
-
-class RasterXRenderPaintRedirector : public ImageBasedPaintRedirector
-{
-    Q_OBJECT
-public:
-    RasterXRenderPaintRedirector(Client *c, KDecoration *deco);
-    virtual ~RasterXRenderPaintRedirector();
-
-protected:
-    virtual xcb_render_picture_t picture(DecorationPixmap border) const;
-    virtual void resize(DecorationPixmap border, const QSize &size);
-    virtual void paint(DecorationPixmap border, const QRect &r, const QRect &b, \
                const QRegion &reg);
-    virtual void preparePaint(const QPixmap &pending);
-private:
-    QSize m_sizes[PixmapCount];
-    xcb_pixmap_t m_pixmaps[PixmapCount];
-    xcb_gcontext_t m_gc;
-    XRenderPicture* m_pictures[PixmapCount];
-    QImage m_tempImage;
-};
-
-class QImagePaintRedirector : public ImageBasedPaintRedirector
-{
-    Q_OBJECT
-public:
-    QImagePaintRedirector(Client *c, KDecoration *deco);
-    virtual ~QImagePaintRedirector();
-
-protected:
-    virtual void resize(DecorationPixmap border, const QSize &size) override;
-    virtual void paint(DecorationPixmap border, const QRect &r, const QRect &b, \
                const QRegion &reg) override;
-    virtual const QImage* image(DecorationPixmap border) const override;
-private:
-    QImage m_images[PixmapCount];
-};
-
-template <>
-inline
-GLTexture *PaintRedirector::bottomDecoPixmap() const
-{
-    return texture(BottomPixmap);
-}
-
-template <>
-inline
-GLTexture *PaintRedirector::leftDecoPixmap() const
-{
-    return texture(LeftPixmap);
-}
-
-template <>
-inline
-GLTexture *PaintRedirector::rightDecoPixmap() const
-{
-    return texture(RightPixmap);
-}
-
-template <>
-inline
-GLTexture *PaintRedirector::topDecoPixmap() const
-{
-    return texture(TopPixmap);
-}
-
-template <>
-inline
-xcb_render_picture_t PaintRedirector::bottomDecoPixmap() const
-{
-    return picture(BottomPixmap);
-}
-
-template <>
-inline
-xcb_render_picture_t PaintRedirector::leftDecoPixmap() const
-{
-    return picture(LeftPixmap);
-}
-
-template <>
-inline
-xcb_render_picture_t PaintRedirector::rightDecoPixmap() const
-{
-    return picture(RightPixmap);
-}
-
-template <>
-inline
-xcb_render_picture_t PaintRedirector::topDecoPixmap() const
-{
-    return picture(TopPixmap);
-}
-
-template <>
-inline
-const QImage *PaintRedirector::bottomDecoPixmap() const
-{
-    return image(BottomPixmap);
-}
-
-template <>
-inline
-const QImage *PaintRedirector::leftDecoPixmap() const
-{
-    return image(LeftPixmap);
-}
-
-template <>
-inline
-const QImage *PaintRedirector::rightDecoPixmap() const
-{
-    return image(RightPixmap);
-}
-
-template <>
-inline
-const QImage *PaintRedirector::topDecoPixmap() const
-{
-    return image(TopPixmap);
-}
-
-inline
-const QImage &ImageBasedPaintRedirector::scratchImage() const
-{
-    return m_scratchImage;
-}
-
-} // namespace
-
-#endif
diff --git a/scene.cpp b/scene.cpp
index 46aa72f..2b6a641 100644
--- a/scene.cpp
+++ b/scene.cpp
@@ -72,7 +72,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include <QVector2D>
 
 #include "client.h"
-#include "decorations.h"
 #include "deleted.h"
 #include "effects.h"
 #include "overlaywindow.h"
@@ -264,7 +263,6 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
         w->resetPaintingEnabled();
         data.paint = region;
         data.paint |= topw->repaints();
-        data.paint |= topw->decorationPendingRegion();
 
         // Reset the repaint_region.
         // This has to be done here because many effects schedule a repaint for
@@ -703,8 +701,7 @@ void Scene::Window::discardShape()
 const QRegion &Scene::Window::shape() const
 {
     if (!shape_valid) {
-        Client* c = dynamic_cast< Client* >(toplevel);
-        if (toplevel->shape() || (c != NULL && !c->mask().isEmpty())) {
+        if (toplevel->shape()) {
             auto cookie = xcb_shape_get_rectangles_unchecked(connection(), \
                toplevel->frameId(), XCB_SHAPE_SK_BOUNDING);
             ScopedCPointer<xcb_shape_get_rectangles_reply_t> \
reply(xcb_shape_get_rectangles_reply(connection(), cookie, nullptr));  if \
(!reply.isNull()) { @@ -809,7 +806,7 @@ WindowQuadList Scene::Window::buildQuads(bool \
force) const  Client *client = dynamic_cast<Client*>(toplevel);
         QRegion contents = clientShape();
         QRegion center = toplevel->transparentRect();
-        QRegion decoration = (client && decorationPlugin()->hasAlpha() ?
+        QRegion decoration = (client && true ?
                               QRegion(client->decorationRect()) : shape()) - center;
         ret = makeQuads(WindowQuadContents, contents);
 
diff --git a/scene.h b/scene.h
index 09689c2..10b9d28 100644
--- a/scene.h
+++ b/scene.h
@@ -30,6 +30,12 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  namespace KWin
 {
 
+namespace Decoration
+{
+class DecoratedClientImpl;
+class Renderer;
+}
+
 class AbstractThumbnailItem;
 class Workspace;
 class Deleted;
@@ -134,6 +140,8 @@ public:
      */
     virtual bool isLastFrameRendered() const = 0;
 
+    virtual Decoration::Renderer \
*createDecorationRenderer(Decoration::DecoratedClientImpl *) = 0; +
 public Q_SLOTS:
     // a window has been destroyed
     void windowDeleted(KWin::Deleted*);
diff --git a/scene_opengl.cpp b/scene_opengl.cpp
index 4d02abe..16fdcd8 100644
--- a/scene_opengl.cpp
+++ b/scene_opengl.cpp
@@ -44,9 +44,9 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "lanczosfilter.h"
 #include "main.h"
 #include "overlaywindow.h"
-#include "paintredirector.h"
 #include "screens.h"
 #include "workspace.h"
+#include "decorations/decoratedclient.h"
 
 #include <cmath>
 #include <unistd.h>
@@ -569,6 +569,11 @@ Shadow *SceneOpenGL::createShadow(Toplevel *toplevel)
     return new SceneOpenGLShadow(toplevel);
 }
 
+Decoration::Renderer \
*SceneOpenGL::createDecorationRenderer(Decoration::DecoratedClientImpl *impl) +{
+    return new SceneOpenGLDecorationRenderer(impl);
+}
+
 //****************************************
 // SceneOpenGL2
 //****************************************
@@ -963,39 +968,23 @@ void SceneOpenGL::Window::endRenderWindow()
     }
 }
 
-
-OpenGLPaintRedirector *SceneOpenGL::Window::paintRedirector() const
+GLTexture *SceneOpenGL::Window::getDecorationTexture() const
 {
+    // TODO: deleted
     if (toplevel->isClient()) {
         Client *client = static_cast<Client *>(toplevel);
-        if (client->noBorder())
-            return 0;
-
-        return static_cast<OpenGLPaintRedirector \
                *>(client->decorationPaintRedirector());
-    }
-
-    if (toplevel->isDeleted()) {
-        Deleted *deleted = static_cast<Deleted *>(toplevel);
-        if (deleted->noBorder())
-            return 0;
+        if (client->noBorder()) {
+            return nullptr;
+        }
 
-        return static_cast<OpenGLPaintRedirector \
*>(deleted->decorationPaintRedirector()); +        if \
(Decoration::DecoratedClientImpl *impl = client->decoratedClient()) { +            if \
(SceneOpenGLDecorationRenderer *renderer = \
static_cast<SceneOpenGLDecorationRenderer*>(impl->renderer())) { +                \
renderer->render(); +                return renderer->texture();
+            }
+        }
     }
-
-    return 0;
-}
-
-GLTexture *SceneOpenGL::Window::getDecorationTexture() const
-{
-    OpenGLPaintRedirector *redirector = paintRedirector();
-    if (!redirector)
-        return 0;
-
-    redirector->ensurePixmapsPainted();
-    GLTexture *texture = redirector->decorationTexture();
-    redirector->markAsRepainted();
-
-    return texture;
+    return nullptr;
 }
 
 void SceneOpenGL::Window::paintDecorations(const WindowPaintData &data, const \
QRegion &region) @@ -2009,4 +1998,104 @@ char SwapProfiler::end()
     return 0;
 }
 
+SceneOpenGLDecorationRenderer::SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl \
*client) +    : Renderer(client)
+    , m_texture()
+{
+    connect(this, &Renderer::renderScheduled, client->client(), static_cast<void \
(Client::*)(const QRect&)>(&Client::addRepaint)); +}
+
+SceneOpenGLDecorationRenderer::~SceneOpenGLDecorationRenderer() = default;
+
+// Rotates the given source rect 90 ° counter-clockwise,
+// and flips it vertically
+static QImage rotate(const QImage &srcImage, const QRect &srcRect)
+{
+    QImage image(srcRect.height(), srcRect.width(), srcImage.format());
+
+    const uint32_t *src = reinterpret_cast<const uint32_t *>(srcImage.bits());
+    uint32_t *dst = reinterpret_cast<uint32_t *>(image.bits());
+
+    for (int x = 0; x < image.width(); x++) {
+        const uint32_t *s = src + (srcRect.y() + x) * srcImage.width() + \
srcRect.x(); +        uint32_t *d = dst + x;
+
+        for (int y = 0; y < image.height(); y++) {
+            *d = s[y];
+            d += image.width();
+        }
+    }
+
+    return image;
+}
+
+void SceneOpenGLDecorationRenderer::render()
+{
+    const QRegion scheduled = getScheduled();
+    if (scheduled.isEmpty()) {
+        return;
+    }
+    if (areImageSizesDirty()) {
+        resizeTexture();
+        resetImageSizesDirty();
+    }
+
+    QRect left, top, right, bottom;
+    client()->client()->layoutDecorationRects(left, top, right, bottom, \
Client::DecorationRelative); +
+    const QRect geometry = scheduled.boundingRect();
+
+    auto renderPart = [this](const QRect &geo, const QRect &partRect, const QPoint \
&offset, bool rotated = false) { +        if (geo.isNull()) {
+            return;
+        }
+        QImage image = renderToImage(geo);
+        if (rotated) {
+            // TODO: get this done directly when rendering to the image
+            image = rotate(image, QRect(geo.topLeft() - partRect.topLeft(), \
geo.size())); +        }
+        m_texture->update(image, geo.topLeft() - partRect.topLeft() + offset);
+    };
+    renderPart(left.intersected(geometry), left, QPoint(0, top.height() + \
bottom.height() + 2), true); +    renderPart(top.intersected(geometry), top, \
QPoint(0, 0)); +    renderPart(right.intersected(geometry), right, QPoint(0, \
top.height() + bottom.height() + left.width() + 3), true); +    \
renderPart(bottom.intersected(geometry), bottom, QPoint(0, top.height() + 1)); +}
+
+static int align(int value, int align)
+{
+    return (value + align - 1) & ~(align - 1);
+}
+
+void SceneOpenGLDecorationRenderer::resizeTexture()
+{
+    QRect left, top, right, bottom;
+    client()->client()->layoutDecorationRects(left, top, right, bottom, \
Client::DecorationRelative); +    QSize size;
+
+    size.rwidth() = qMax(qMax(top.width(), bottom.width()),
+                         qMax(left.height(), right.height()));
+    size.rheight() = top.height() + bottom.height() +
+                     left.width() + right.width() + 3;
+
+    size.rwidth() = align(size.width(), 128);
+
+    if (!GLTexture::NPOTTextureSupported()) {
+        size.rwidth()  = nearestPowerOfTwo(size.width());
+        size.rheight() = nearestPowerOfTwo(size.height());
+    }
+
+    if (m_texture && m_texture->size() == size)
+        return;
+
+    if (!size.isEmpty()) {
+        m_texture.reset(new GLTexture(size.width(), size.height()));
+        m_texture->setYInverted(true);
+        m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
+        m_texture->clear();
+    } else {
+        m_texture.reset();
+    }
+}
+
 } // namespace
diff --git a/scene_opengl.h b/scene_opengl.h
index f39007c..d1b2a4f 100644
--- a/scene_opengl.h
+++ b/scene_opengl.h
@@ -28,12 +28,13 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "kwinglutils.h"
 #include "kwingltexture_p.h"
 
+#include "decorations/decorationrenderer.h"
+
 namespace KWin
 {
 class ColorCorrection;
 class LanczosFilter;
 class OpenGLBackend;
-class OpenGLPaintRedirector;
 
 class SceneOpenGL
     : public Scene
@@ -58,6 +59,7 @@ public:
     virtual bool makeOpenGLContextCurrent() override;
     virtual void doneOpenGLContextCurrent() override;
     virtual bool isLastFrameRendered() const override;
+    Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl \
*impl) override;  
     void idle();
 
@@ -238,9 +240,6 @@ protected:
 protected:
     SceneOpenGL *m_scene;
     bool m_hardwareClipping;
-
-private:
-    OpenGLPaintRedirector *paintRedirector() const;
 };
 
 class SceneOpenGL2Window : public SceneOpenGL::Window
@@ -617,6 +616,31 @@ private:
     QElapsedTimer m_renderTimer;
 };
 
+class SceneOpenGLDecorationRenderer : public Decoration::Renderer
+{
+    Q_OBJECT
+public:
+    enum class DecorationPart : int {
+        Left,
+        Top,
+        Right,
+        Bottom,
+        Count
+    };
+    explicit SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl *client);
+    virtual ~SceneOpenGLDecorationRenderer();
+
+    void render() override;
+
+    GLTexture *texture() {
+        return m_texture.data();
+    }
+
+private:
+    void resizeTexture();
+    QScopedPointer<GLTexture> m_texture;
+};
+
 inline bool SceneOpenGL::hasPendingFlush() const
 {
     return m_backend->hasPendingFlush();
diff --git a/scene_qpainter.cpp b/scene_qpainter.cpp
index 551ab58..493381c 100644
--- a/scene_qpainter.cpp
+++ b/scene_qpainter.cpp
@@ -24,16 +24,17 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "deleted.h"
 #include "effects.h"
 #include "main.h"
-#include "paintredirector.h"
 #include "toplevel.h"
 #if HAVE_WAYLAND
 #include "wayland_backend.h"
 #endif
 #include "workspace.h"
 #include "xcbutils.h"
+#include "decorations/decoratedclient.h"
 // Qt
 #include <QDebug>
 #include <QPainter>
+#include <KDecoration2/Decoration>
 
 namespace KWin
 {
@@ -442,33 +443,31 @@ void SceneQPainter::Window::renderWindowDecorations(QPainter \
*painter)  }
 
     bool noBorder = true;
-    PaintRedirector *redirector = NULL;
+    SceneQPainterDecorationRenderer *renderer = nullptr;
     QRect dtr, dlr, drr, dbr;
     if (client && !client->noBorder()) {
-        redirector = client->decorationPaintRedirector();
+        if (Decoration::DecoratedClientImpl *impl = client->decoratedClient()) {
+            if (SceneQPainterDecorationRenderer *r = \
static_cast<SceneQPainterDecorationRenderer *>(impl->renderer())) { +                \
renderer = r; +            }
+        }
         client->layoutDecorationRects(dlr, dtr, drr, dbr, Client::WindowRelative);
         noBorder = false;
     } else if (deleted && !deleted->noBorder()) {
         noBorder = false;
-        redirector = deleted->decorationPaintRedirector();
+        // TODO: renderer
         deleted->layoutDecorationRects(dlr, dtr, drr, dbr);
     }
-    if (noBorder || !redirector) {
+    if (noBorder || !renderer) {
         return;
     }
 
-    redirector->ensurePixmapsPainted();
-    const QImage *left   = redirector->leftDecoPixmap<const QImage *>();
-    const QImage *top    = redirector->topDecoPixmap<const QImage *>();
-    const QImage *right  = redirector->rightDecoPixmap<const QImage *>();
-    const QImage *bottom = redirector->bottomDecoPixmap<const QImage *>();
-
-    painter->drawImage(dtr, *top);
-    painter->drawImage(dlr, *left);
-    painter->drawImage(drr, *right);
-    painter->drawImage(dbr, *bottom);
+    renderer->render();
 
-    redirector->markAsRepainted();
+    painter->drawImage(dtr, \
renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Top)); +    \
painter->drawImage(dlr, \
renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Left)); +    \
painter->drawImage(drr, \
renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Right)); +    \
painter->drawImage(dbr, \
renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Bottom));  }
 
 WindowPixmap *SceneQPainter::Window::createWindowPixmap()
@@ -476,6 +475,11 @@ WindowPixmap *SceneQPainter::Window::createWindowPixmap()
     return new QPainterWindowPixmap(this);
 }
 
+Decoration::Renderer \
*SceneQPainter::createDecorationRenderer(Decoration::DecoratedClientImpl *impl) +{
+    return new SceneQPainterDecorationRenderer(impl);
+}
+
 //****************************************
 // QPainterWindowPixmap
 //****************************************
@@ -615,4 +619,77 @@ bool SceneQPainterShadow::prepareBackend()
     return true;
 }
 
+//****************************************
+// QPainterDecorationRenderer
+//****************************************
+SceneQPainterDecorationRenderer::SceneQPainterDecorationRenderer(Decoration::DecoratedClientImpl \
*client) +    : Renderer(client)
+{
+    connect(this, &Renderer::renderScheduled, client->client(), static_cast<void \
(Client::*)(const QRect&)>(&Client::addRepaint)); +}
+
+SceneQPainterDecorationRenderer::~SceneQPainterDecorationRenderer() = default;
+
+QImage SceneQPainterDecorationRenderer::image(SceneQPainterDecorationRenderer::DecorationPart \
part) const +{
+    Q_ASSERT(part != DecorationPart::Count);
+    return m_images[int(part)];
+}
+
+void SceneQPainterDecorationRenderer::render()
+{
+    const QRegion scheduled = getScheduled();
+    if (scheduled.isEmpty()) {
+        return;
+    }
+    if (areImageSizesDirty()) {
+        resizeImages();
+        resetImageSizesDirty();
+    }
+
+    const QRect top(QPoint(0, 0), m_images[int(DecorationPart::Top)].size());
+    const QRect left(QPoint(0, top.height()), \
m_images[int(DecorationPart::Left)].size()); +    const QRect \
right(QPoint(top.width() - m_images[int(DecorationPart::Right)].size().width(), \
top.height()), m_images[int(DecorationPart::Right)].size()); +    const QRect \
bottom(QPoint(0, left.y() + left.height()), \
m_images[int(DecorationPart::Bottom)].size()); +
+    const QRect geometry = scheduled.boundingRect();
+    auto renderPart = [this](const QRect &rect, const QRect &partRect, int index) {
+        if (rect.isEmpty()) {
+            return;
+        }
+        QPainter painter(&m_images[index]);
+        painter.setRenderHint(QPainter::Antialiasing);
+        painter.setWindow(partRect);
+        painter.setClipRect(rect);
+        painter.save();
+        // clear existing part
+        painter.setCompositionMode(QPainter::CompositionMode_Source);
+        painter.fillRect(rect, Qt::red);
+        painter.restore();
+        client()->decoration()->paint(&painter);
+    };
+
+    renderPart(left.intersected(geometry), left, int(DecorationPart::Left));
+    renderPart(top.intersected(geometry), top, int(DecorationPart::Top));
+    renderPart(right.intersected(geometry), right, int(DecorationPart::Right));
+    renderPart(bottom.intersected(geometry), bottom, int(DecorationPart::Bottom));
+}
+
+void SceneQPainterDecorationRenderer::resizeImages()
+{
+    QRect left, top, right, bottom;
+    client()->client()->layoutDecorationRects(left, top, right, bottom, \
Client::DecorationRelative); +
+    auto checkAndCreate = [this](int index, const QSize &size) {
+        if (m_images[index].size() != size) {
+            m_images[index] = QImage(size, QImage::Format_ARGB32_Premultiplied);
+            m_images[index].fill(Qt::transparent);
+        }
+    };
+    checkAndCreate(int(DecorationPart::Left), left.size());
+    checkAndCreate(int(DecorationPart::Right), right.size());
+    checkAndCreate(int(DecorationPart::Top), top.size());
+    checkAndCreate(int(DecorationPart::Bottom), bottom.size());
+}
+
 } // KWin
diff --git a/scene_qpainter.h b/scene_qpainter.h
index 5846eba..c510366 100644
--- a/scene_qpainter.h
+++ b/scene_qpainter.h
@@ -23,6 +23,8 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "scene.h"
 #include "shadow.h"
 
+#include "decorations/decorationrenderer.h"
+
 namespace KWin {
 
 namespace Xcb {
@@ -143,6 +145,7 @@ public:
     virtual bool initFailed() const override;
     virtual EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
     virtual Shadow *createShadow(Toplevel *toplevel) override;
+    Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl \
*impl) override;  
     QPainter *painter();
 
@@ -227,6 +230,29 @@ protected:
     virtual bool prepareBackend() override;
 };
 
+class SceneQPainterDecorationRenderer : public Decoration::Renderer
+{
+    Q_OBJECT
+public:
+    enum class DecorationPart : int {
+        Left,
+        Top,
+        Right,
+        Bottom,
+        Count
+    };
+    explicit SceneQPainterDecorationRenderer(Decoration::DecoratedClientImpl \
*client); +    virtual ~SceneQPainterDecorationRenderer();
+
+    void render() override;
+
+    QImage image(DecorationPart part) const;
+
+private:
+    void resizeImages();
+    QImage m_images[int(DecorationPart::Count)];
+};
+
 inline
 bool SceneQPainter::usesOverlayWindow() const
 {
diff --git a/scene_xrender.cpp b/scene_xrender.cpp
index ed45a8f..2871cc3 100644
--- a/scene_xrender.cpp
+++ b/scene_xrender.cpp
@@ -26,18 +26,17 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "toplevel.h"
 #include "client.h"
 #include "composite.h"
-#include "decorations.h"
 #include "deleted.h"
 #include "effects.h"
 #include "main.h"
 #include "overlaywindow.h"
-#include "paintredirector.h"
 #include "workspace.h"
 #include "xcbutils.h"
 #include "kwinxrenderutils.h"
 #if HAVE_WAYLAND
 #include "wayland_backend.h"
 #endif
+#include "decorations/decoratedclient.h"
 
 #include <xcb/xfixes.h>
 
@@ -466,6 +465,11 @@ Shadow *SceneXrender::createShadow(Toplevel *toplevel)
     return new SceneXRenderShadow(toplevel);
 }
 
+Decoration::Renderer \
*SceneXrender::createDecorationRenderer(Decoration::DecoratedClientImpl* client) +{
+    return new SceneXRenderDecorationRenderer(client);
+}
+
 //****************************************
 // SceneXrender::Window
 //****************************************
@@ -611,7 +615,7 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, \
WindowPaintDat  Deleted *deleted = dynamic_cast<Deleted*>(toplevel);
     const QRect decorationRect = toplevel->decorationRect();
     if (((client && !client->noBorder()) || (deleted && !deleted->noBorder())) &&
-                                                        \
decorationPlugin()->hasAlpha()) { +                                                   \
true) {  // decorated client
         transformed_shape = decorationRect;
         if (toplevel->shape()) {
@@ -717,32 +721,30 @@ void SceneXrender::Window::performPaint(int mask, QRegion \
region, WindowPaintDat  xcb_render_picture_t top    = XCB_RENDER_PICTURE_NONE;
     xcb_render_picture_t right  = XCB_RENDER_PICTURE_NONE;
     xcb_render_picture_t bottom = XCB_RENDER_PICTURE_NONE;
-    PaintRedirector *redirector = NULL;
     QRect dtr, dlr, drr, dbr;
-    if (client || deleted) {
+    SceneXRenderDecorationRenderer *renderer = nullptr;
+    // TODO: deleted
+    if (client) {
         if (client && !client->noBorder()) {
-            redirector = client->decorationPaintRedirector();
+            if (Decoration::DecoratedClientImpl *impl = client->decoratedClient()) {
+                renderer = \
static_cast<SceneXRenderDecorationRenderer*>(impl->renderer()); +            }
             noBorder = client->noBorder();
             client->layoutDecorationRects(dlr, dtr, drr, dbr, \
Client::WindowRelative);  }
-        if (deleted && !deleted->noBorder()) {
-            noBorder = deleted->noBorder();
-            redirector = deleted->decorationPaintRedirector();
-            deleted->layoutDecorationRects(dlr, dtr, drr, dbr);
-        }
-        if (redirector) {
-            redirector->ensurePixmapsPainted();
-            left   = redirector->leftDecoPixmap<xcb_render_picture_t>();
-            top    = redirector->topDecoPixmap<xcb_render_picture_t>();
-            right  = redirector->rightDecoPixmap<xcb_render_picture_t>();
-            bottom = redirector->bottomDecoPixmap<xcb_render_picture_t>();
-        }
-        if (!noBorder) {
-            MAP_RECT_TO_TARGET(dtr);
-            MAP_RECT_TO_TARGET(dlr);
-            MAP_RECT_TO_TARGET(drr);
-            MAP_RECT_TO_TARGET(dbr);
-        }
+    }
+    if (renderer) {
+        renderer->render();
+        left   = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Left);
 +        top    = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Top);
 +        right  = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Right);
 +        bottom = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Bottom);
 +    }
+    if (!noBorder) {
+        MAP_RECT_TO_TARGET(dtr);
+        MAP_RECT_TO_TARGET(dlr);
+        MAP_RECT_TO_TARGET(drr);
+        MAP_RECT_TO_TARGET(dbr);
     }
     //END deco preparations
 
@@ -860,9 +862,6 @@ xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, \
m_xrenderShadow->pic  renderDeco(right, drr);
                 renderDeco(bottom, dbr);
             }
-            if (redirector) {
-                redirector->markAsRepainted();
-            }
         }
 
         if (data.brightness() != 1.0) {
@@ -1307,6 +1306,115 @@ xcb_render_picture_t \
SceneXRenderShadow::picture(Shadow::ShadowElements element)  return \
*m_pictures[element];  }
 
+SceneXRenderDecorationRenderer::SceneXRenderDecorationRenderer(Decoration::DecoratedClientImpl \
*client) +    : Renderer(client)
+    , m_gc(XCB_NONE)
+{
+    connect(this, &Renderer::renderScheduled, client->client(), static_cast<void \
(Client::*)(const QRect&)>(&Client::addRepaint)); +    for (int i = 0; i < \
int(DecorationPart::Count); ++i) { +        m_pixmaps[i] = XCB_PIXMAP_NONE;
+        m_pictures[i] = nullptr;
+    }
+}
+
+SceneXRenderDecorationRenderer::~SceneXRenderDecorationRenderer()
+{
+    for (int i = 0; i < int(DecorationPart::Count); ++i) {
+        if (m_pixmaps[i] != XCB_PIXMAP_NONE) {
+            xcb_free_pixmap(connection(), m_pixmaps[i]);
+        }
+        delete m_pictures[i];
+    }
+    if (m_gc != 0) {
+        xcb_free_gc(connection(), m_gc);
+    }
+}
+
+void SceneXRenderDecorationRenderer::render()
+{
+    const QRegion scheduled = getScheduled();
+    if (scheduled.isEmpty()) {
+        return;
+    }
+    if (areImageSizesDirty()) {
+        resizePixmaps();
+        resetImageSizesDirty();
+    }
+
+    const QRect top(QPoint(0, 0), m_sizes[int(DecorationPart::Top)]);
+    const QRect left(QPoint(0, top.height()), m_sizes[int(DecorationPart::Left)]);
+    const QRect right(QPoint(top.width() - \
m_sizes[int(DecorationPart::Right)].width(), top.height()), \
m_sizes[int(DecorationPart::Right)]); +    const QRect bottom(QPoint(0, left.y() + \
left.height()), m_sizes[int(DecorationPart::Bottom)]); +
+    xcb_connection_t *c = connection();
+    if (m_gc == 0) {
+        m_gc = xcb_generate_id(connection());
+        xcb_create_gc(c, m_gc, m_pixmaps[int(DecorationPart::Top)], 0, nullptr);
+    }
+    auto renderPart = [this, c](const QRect &geo, const QPoint &offset, int index) {
+        if (geo.isNull()) {
+            return;
+        }
+        QImage image = renderToImage(geo);
+        xcb_put_image(c, XCB_IMAGE_FORMAT_Z_PIXMAP, m_pixmaps[index], m_gc,
+                      image.width(), image.height(), geo.x() - offset.x(), geo.y() - \
offset.y(), 0, 32, +                      image.byteCount(), image.constBits());
+    };
+    const QRect geometry = scheduled.boundingRect();
+    renderPart(left.intersected(geometry),   left.topLeft(),   \
int(DecorationPart::Left)); +    renderPart(top.intersected(geometry),    \
top.topLeft(),    int(DecorationPart::Top)); +    \
renderPart(right.intersected(geometry),  right.topLeft(),  \
int(DecorationPart::Right)); +    renderPart(bottom.intersected(geometry), \
bottom.topLeft(), int(DecorationPart::Bottom)); +    xcb_flush(c);
+}
+
+void SceneXRenderDecorationRenderer::resizePixmaps()
+{
+    QRect left, top, right, bottom;
+    client()->client()->layoutDecorationRects(left, top, right, bottom, \
Client::DecorationRelative); +
+    xcb_connection_t *c = connection();
+    auto checkAndCreate = [this, c](int border, const QRect &rect) {
+        const QSize size = rect.size();
+        if (m_sizes[border] != size) {
+            m_sizes[border] = size;
+            if (m_pixmaps[border] != XCB_PIXMAP_NONE) {
+                xcb_free_pixmap(c, m_pixmaps[border]);
+            }
+            delete m_pictures[border];
+            if (!size.isEmpty()) {
+                m_pixmaps[border] = xcb_generate_id(connection());
+                xcb_create_pixmap(connection(), 32, m_pixmaps[border], rootWindow(), \
size.width(), size.height()); +                m_pictures[border] = new \
XRenderPicture(m_pixmaps[border], 32); +            } else {
+                m_pixmaps[border] = XCB_PIXMAP_NONE;
+                m_pictures[border] = nullptr;
+            }
+        }
+        if (!m_pictures[border]) {
+            return;
+        }
+        // fill transparent
+        xcb_rectangle_t r = {0, 0, uint16_t(size.width()), uint16_t(size.height())};
+        xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, \
*m_pictures[border], preMultiply(Qt::transparent), 1, &r); +    };
+
+    checkAndCreate(int(DecorationPart::Left), left);
+    checkAndCreate(int(DecorationPart::Top), top);
+    checkAndCreate(int(DecorationPart::Right), right);
+    checkAndCreate(int(DecorationPart::Bottom), bottom);
+}
+
+xcb_render_picture_t \
SceneXRenderDecorationRenderer::picture(SceneXRenderDecorationRenderer::DecorationPart \
part) const +{
+    Q_ASSERT(part != DecorationPart::Count);
+    XRenderPicture *picture = m_pictures[int(part)];
+    if (!picture) {
+        return XCB_RENDER_PICTURE_NONE;
+    }
+    return *picture;
+}
+
 #undef DOUBLE_TO_FIXED
 #undef FIXED_TO_DOUBLE
 
diff --git a/scene_xrender.h b/scene_xrender.h
index 42e965f..fe0e5a1 100644
--- a/scene_xrender.h
+++ b/scene_xrender.h
@@ -23,6 +23,7 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  
 #include "scene.h"
 #include "shadow.h"
+#include "decorations/decorationrenderer.h"
 
 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
 
@@ -196,6 +197,7 @@ public:
     virtual bool isLastFrameRendered() const {
         return m_backend->isLastFrameRendered();
     }
+    Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl \
*client);  
     static SceneXrender *createScene();
 protected:
@@ -337,6 +339,32 @@ private:
     XRenderPicture* m_pictures[ShadowElementsCount];
 };
 
+class SceneXRenderDecorationRenderer : public Decoration::Renderer
+{
+    Q_OBJECT
+public:
+    enum class DecorationPart : int {
+        Left,
+        Top,
+        Right,
+        Bottom,
+        Count
+    };
+    explicit SceneXRenderDecorationRenderer(Decoration::DecoratedClientImpl \
*client); +    virtual ~SceneXRenderDecorationRenderer();
+
+    void render() override;
+
+    xcb_render_picture_t picture(DecorationPart part) const;
+
+private:
+    void resizePixmaps();
+    QSize m_sizes[int(DecorationPart::Count)];
+    xcb_pixmap_t m_pixmaps[int(DecorationPart::Count)];
+    xcb_gcontext_t m_gc;
+    XRenderPicture* m_pictures[int(DecorationPart::Count)];
+};
+
 } // namespace
 
 #endif
diff --git a/tabgroup.cpp b/tabgroup.cpp
index 1b5503e..c8f2d48 100644
--- a/tabgroup.cpp
+++ b/tabgroup.cpp
@@ -21,7 +21,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "tabgroup.h"
 
 #include "client.h"
-#include "decorations.h"
 #include "effects.h"
 #include "workspace.h"
 
@@ -63,7 +62,7 @@ bool TabGroup::add(Client* c, Client *other, bool after, bool \
becomeVisible)  {
     Q_ASSERT(!c->tabGroup());
 
-    if (!decorationPlugin()->supportsTabbing() || contains(c) || !contains(other))
+    if (contains(c) || !contains(other))
         return false;
 
     // Tabbed windows MUST have a decoration
diff --git a/toplevel.h b/toplevel.h
index 73e8242..b11a2b2 100644
--- a/toplevel.h
+++ b/toplevel.h
@@ -205,7 +205,6 @@ public:
     virtual QRect visibleRect() const; // the area the window occupies on the screen
     virtual QRect decorationRect() const; // rect including the decoration shadows
     virtual QRect transparentRect() const = 0;
-    virtual QRegion decorationPendingRegion() const; // decoration region that needs \
to be repainted  virtual bool isClient() const;
     virtual bool isDeleted() const;
 
@@ -511,11 +510,6 @@ inline QRect Toplevel::rect() const
     return QRect(0, 0, width(), height());
 }
 
-inline QRegion Toplevel::decorationPendingRegion() const
-{
-    return QRegion();
-}
-
 inline bool Toplevel::readyForPainting() const
 {
     return ready_for_painting;
diff --git a/useractions.cpp b/useractions.cpp
index 305930b..1294707 100755
--- a/useractions.cpp
+++ b/useractions.cpp
@@ -34,7 +34,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "useractions.h"
 #include "cursor.h"
 #include "client.h"
-#include "decorations.h"
 #include "input.h"
 #include "workspace.h"
 #include "effects.h"
@@ -337,7 +336,7 @@ void UserActionsMenu::init()
     m_menu->addSeparator();
 
     // Actions for window tabbing
-    if (decorationPlugin()->supportsTabbing()) {
+    if (false) {
         m_removeFromTabGroup = m_menu->addAction(i18n("&Untab"));
         setShortcut(m_removeFromTabGroup, QStringLiteral("Untab"));
         m_removeFromTabGroup->setData(Options::RemoveTabFromGroupOp);
@@ -409,7 +408,7 @@ void UserActionsMenu::menuAboutToShow()
     m_minimizeOperation->setEnabled(m_client.data()->isMinimizable());
     m_closeOperation->setEnabled(m_client.data()->isCloseable());
 
-    if (decorationPlugin()->supportsTabbing()) {
+    if (false) {
         initTabbingPopups();
         m_addTabsMenu->setPalette(m_client.data()->palette());
     } else {
diff --git a/workspace.cpp b/workspace.cpp
index 14606fd..711df62 100644
--- a/workspace.cpp
+++ b/workspace.cpp
@@ -36,7 +36,6 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include "composite.h"
 #include "cursor.h"
 #include "dbusinterface.h"
-#include "decorations.h"
 #include "deleted.h"
 #include "effects.h"
 #include "focuschain.h"
@@ -63,6 +62,7 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #endif
 #include "xcbutils.h"
 #include "main.h"
+#include "decorations/decorationbridge.h"
 // KDE
 #include <KConfig>
 #include <KConfigGroup>
@@ -171,7 +171,6 @@ Workspace::Workspace(bool restore)
 
     options->loadConfig();
     options->loadCompositingConfig(false);
-    DecorationPlugin::create(this);
     ColorMapper *colormaps = new ColorMapper(this);
     connect(this, SIGNAL(clientActivated(KWin::Client*)), colormaps, \
SLOT(update()));  
@@ -213,7 +212,9 @@ Workspace::Workspace(bool restore)
     XRenderUtils::init(connection(), rootWindow());
     m_compositor = Compositor::create(this);
     connect(this, SIGNAL(currentDesktopChanged(int,KWin::Client*)), m_compositor, \
                SLOT(addRepaintFull()));
-    connect(m_compositor, &Compositor::compositingToggled, decorationPlugin(), \
&DecorationPlugin::compositingToggled); +
+    new Decoration::DecorationBridge(this);
+    Decoration::DecorationBridge::self()->init();
 
     new DBusInterface(this);
 
@@ -784,18 +785,6 @@ void Workspace::slotReconfigure()
     m_userActionsMenu->discard();
     updateToolWindows(true);
 
-    DecorationPlugin *deco = DecorationPlugin::self();
-    if (!deco->isDisabled() && deco->reset()) {
-        deco->recreateDecorations();
-        deco->destroyPreviousPlugin();
-        connect(deco->factory(), &KDecorationFactory::recreateDecorations, deco, \
                &DecorationPlugin::recreateDecorations);
-    } else {
-        foreach (Client * c, clients) {
-            c->checkBorderSizes(true);
-            c->triggerDecorationRepaint();
-        }
-    }
-
     RuleBook::self()->load();
     for (ClientList::Iterator it = clients.begin();
             it != clients.end();
@@ -816,12 +805,6 @@ void Workspace::slotReconfigure()
                 (*it)->checkNoBorder();
         }
     }
-
-    if (!deco->isDisabled()) {
-        rootInfo()->setSupported(NET::WM2FrameOverlap, \
                deco->factory()->supports(AbilityExtendIntoClientArea));
-    } else {
-        rootInfo()->setSupported(NET::WM2FrameOverlap, false);
-    }
 }
 
 /**
@@ -1412,9 +1395,6 @@ QString Workspace::supportInformation() const
                               .arg(geo.width())
                               .arg(geo.height()));
     }
-    support.append(QStringLiteral("\nDecoration\n"));
-    support.append(QStringLiteral(  "==========\n"));
-    support.append(decorationPlugin()->supportInformation());
     support.append(QStringLiteral("\nCompositing\n"));
     support.append(QStringLiteral(  "===========\n"));
     if (effects) {


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic