Currently, the implementation of the DecoratedClient and the decoration renderer are strongly coupled. This poses a problem with the item based design as the ultimate goal is to have scene items construct paint nodes which are then fed to the renderer. The DecorationItem has to have control over the decoration texture. Another issue is that the scene cannot smoothly cross-fade between two window states if the decoration is removed, e.g. from fullscreen mode to normal and vice versa. This change moves the decoration renderer to the decoration item. With the introduction of a generic scene texture atlas, we hope to get rid of the decoration renderer altogether.remotes/origin/work/xwl_drag2
parent
7f32594692
commit
f46c7bae8d
28 changed files with 328 additions and 537 deletions
@ -1,102 +0,0 @@ |
||||
/*
|
||||
KWin - the KDE window manager |
||||
This file is part of the KDE project. |
||||
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> |
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later |
||||
*/ |
||||
#include "decorationrenderer.h" |
||||
#include "decoratedclient.h" |
||||
#include "decorations/decorations_logging.h" |
||||
#include "deleted.h" |
||||
#include "abstract_client.h" |
||||
#include "screens.h" |
||||
|
||||
#include <KDecoration2/Decoration> |
||||
#include <KDecoration2/DecoratedClient> |
||||
|
||||
#include <QDebug> |
||||
#include <QPainter> |
||||
|
||||
namespace KWin |
||||
{ |
||||
namespace Decoration |
||||
{ |
||||
|
||||
Renderer::Renderer(DecoratedClientImpl *client) |
||||
: QObject(client) |
||||
, m_client(client) |
||||
, m_imageSizesDirty(true) |
||||
{ |
||||
auto markImageSizesDirty = [this]{ |
||||
schedule(m_client->client()->rect()); |
||||
m_imageSizesDirty = true; |
||||
}; |
||||
connect(client->decoration(), &KDecoration2::Decoration::damaged, this, &Renderer::schedule); |
||||
connect(client->client(), &AbstractClient::screenScaleChanged, this, markImageSizesDirty); |
||||
connect(client->decoration(), &KDecoration2::Decoration::bordersChanged, this, markImageSizesDirty); |
||||
connect(client->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged, this, markImageSizesDirty); |
||||
} |
||||
|
||||
Renderer::~Renderer() = default; |
||||
|
||||
void Renderer::schedule(const QRegion &rect) |
||||
{ |
||||
m_scheduled = m_scheduled.united(rect); |
||||
emit renderScheduled(rect); |
||||
} |
||||
|
||||
QRegion Renderer::getScheduled() |
||||
{ |
||||
QRegion region = m_scheduled; |
||||
m_scheduled = QRegion(); |
||||
return region; |
||||
} |
||||
|
||||
QImage Renderer::renderToImage(const QRect &geo) |
||||
{ |
||||
Q_ASSERT(m_client); |
||||
auto dpr = client()->client()->screenScale(); |
||||
|
||||
// Guess the pixel format of the X pixmap into which the QImage will be copied.
|
||||
QImage::Format format; |
||||
const int depth = client()->client()->depth(); |
||||
switch (depth) { |
||||
case 30: |
||||
format = QImage::Format_A2RGB30_Premultiplied; |
||||
break; |
||||
case 24: |
||||
case 32: |
||||
format = QImage::Format_ARGB32_Premultiplied; |
||||
break; |
||||
default: |
||||
qCCritical(KWIN_DECORATIONS) << "Unsupported client depth" << depth; |
||||
format = QImage::Format_ARGB32_Premultiplied; |
||||
break; |
||||
}; |
||||
|
||||
QImage image(geo.width() * dpr, geo.height() * dpr, format); |
||||
image.setDevicePixelRatio(dpr); |
||||
image.fill(Qt::transparent); |
||||
QPainter p(&image); |
||||
p.setRenderHint(QPainter::Antialiasing); |
||||
p.setWindow(QRect(geo.topLeft(), geo.size() * qPainterEffectiveDevicePixelRatio(&p))); |
||||
p.setClipRect(geo); |
||||
renderToPainter(&p, geo); |
||||
return image; |
||||
} |
||||
|
||||
void Renderer::renderToPainter(QPainter *painter, const QRect &rect) |
||||
{ |
||||
client()->decoration()->paint(painter, rect); |
||||
} |
||||
|
||||
void Renderer::reparent(Deleted *deleted) |
||||
{ |
||||
setParent(deleted); |
||||
m_client = nullptr; |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -1,76 +0,0 @@ |
||||
/*
|
||||
KWin - the KDE window manager |
||||
This file is part of the KDE project. |
||||
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> |
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later |
||||
*/ |
||||
#ifndef KWIN_DECORATION_RENDERER_H |
||||
#define KWIN_DECORATION_RENDERER_H |
||||
|
||||
#include <QObject> |
||||
#include <QRegion> |
||||
|
||||
#include <kwin_export.h> |
||||
|
||||
namespace KWin |
||||
{ |
||||
|
||||
class Deleted; |
||||
|
||||
namespace Decoration |
||||
{ |
||||
|
||||
class DecoratedClientImpl; |
||||
|
||||
class KWIN_EXPORT Renderer : public QObject |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
~Renderer() override; |
||||
|
||||
void schedule(const QRegion ®ion); |
||||
|
||||
/**
|
||||
* Reparents this Renderer to the @p deleted. |
||||
* After this call the Renderer is no longer able to render |
||||
* anything, client() returns a nullptr. |
||||
*/ |
||||
virtual void reparent(Deleted *deleted); |
||||
|
||||
Q_SIGNALS: |
||||
void renderScheduled(const QRegion &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); |
||||
void renderToPainter(QPainter *painter, const QRect &rect); |
||||
|
||||
private: |
||||
DecoratedClientImpl *m_client; |
||||
QRegion m_scheduled; |
||||
bool m_imageSizesDirty; |
||||
}; |
||||
|
||||
} |
||||
} |
||||
|
||||
#endif |
||||
@ -1,98 +0,0 @@ |
||||
/*
|
||||
KWin - the KDE window manager |
||||
This file is part of the KDE project. |
||||
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> |
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later |
||||
*/ |
||||
#include "x11_decoration_renderer.h" |
||||
#include "decorations/decoratedclient.h" |
||||
#include "x11client.h" |
||||
#include "deleted.h" |
||||
|
||||
#include <kwinglobals.h> |
||||
|
||||
#include <KDecoration2/Decoration> |
||||
#include <KDecoration2/DecoratedClient> |
||||
|
||||
#include <QTimer> |
||||
|
||||
namespace KWin |
||||
{ |
||||
namespace Decoration |
||||
{ |
||||
|
||||
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::reparent(Deleted *deleted) |
||||
{ |
||||
if (m_scheduleTimer->isActive()) { |
||||
m_scheduleTimer->stop(); |
||||
} |
||||
disconnect(m_scheduleTimer, &QTimer::timeout, this, &X11Renderer::render); |
||||
disconnect(this, &Renderer::renderScheduled, m_scheduleTimer, static_cast<void (QTimer::*)()>(&QTimer::start)); |
||||
Renderer::reparent(deleted); |
||||
} |
||||
|
||||
void X11Renderer::render() |
||||
{ |
||||
if (!client()) { |
||||
return; |
||||
} |
||||
const QRegion scheduled = getScheduled(); |
||||
if (scheduled.isEmpty()) { |
||||
return; |
||||
} |
||||
xcb_connection_t *c = connection(); |
||||
if (m_gc == XCB_NONE) { |
||||
m_gc = xcb_generate_id(c); |
||||
xcb_create_gc(c, m_gc, client()->client()->frameId(), 0, nullptr); |
||||
} |
||||
|
||||
QRect left, top, right, bottom; |
||||
client()->client()->layoutDecorationRects(left, top, right, bottom); |
||||
|
||||
const QRect geometry = scheduled.boundingRect(); |
||||
left = left.intersected(geometry); |
||||
top = top.intersected(geometry); |
||||
right = right.intersected(geometry); |
||||
bottom = bottom.intersected(geometry); |
||||
|
||||
auto renderPart = [this, c](const QRect &geo) { |
||||
if (!geo.isValid()) { |
||||
return; |
||||
} |
||||
QImage image = renderToImage(geo); |
||||
xcb_put_image(c, XCB_IMAGE_FORMAT_Z_PIXMAP, client()->client()->frameId(), m_gc, |
||||
image.width(), image.height(), geo.x(), geo.y(), 0, client()->client()->depth(), |
||||
image.sizeInBytes(), image.constBits()); |
||||
}; |
||||
renderPart(left); |
||||
renderPart(top); |
||||
renderPart(right); |
||||
renderPart(bottom); |
||||
|
||||
xcb_flush(c); |
||||
resetImageSizesDirty(); |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -1,44 +0,0 @@ |
||||
/*
|
||||
KWin - the KDE window manager |
||||
This file is part of the KDE project. |
||||
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> |
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later |
||||
*/ |
||||
#ifndef KWIN_DECORATION_X11_RENDERER_H |
||||
#define KWIN_DECORATION_X11_RENDERER_H |
||||
|
||||
#include "decorations/decorationrenderer.h" |
||||
|
||||
#include <xcb/xcb.h> |
||||
|
||||
class QTimer; |
||||
|
||||
namespace KWin |
||||
{ |
||||
|
||||
namespace Decoration |
||||
{ |
||||
|
||||
class X11Renderer : public Renderer |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
explicit X11Renderer(DecoratedClientImpl *client); |
||||
~X11Renderer() override; |
||||
|
||||
void reparent(Deleted *deleted) override; |
||||
|
||||
protected: |
||||
void render() override; |
||||
|
||||
private: |
||||
QTimer *m_scheduleTimer; |
||||
xcb_gcontext_t m_gc; |
||||
}; |
||||
|
||||
} |
||||
} |
||||
|
||||
#endif |
||||
Loading…
Reference in new issue