Move decoration renderer to decoration item
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.
This commit is contained in:
parent
7f32594692
commit
f46c7bae8d
28 changed files with 328 additions and 537 deletions
|
@ -37,7 +37,6 @@ set(kwin_SRCS
|
|||
decorations/decoratedclient.cpp
|
||||
decorations/decorationbridge.cpp
|
||||
decorations/decorationpalette.cpp
|
||||
decorations/decorationrenderer.cpp
|
||||
decorations/decorations_logging.cpp
|
||||
decorations/settings.cpp
|
||||
deleted.cpp
|
||||
|
|
|
@ -1,30 +1,137 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "decorationitem.h"
|
||||
#include "abstract_client.h"
|
||||
#include "composite.h"
|
||||
#include "decorations/decoratedclient.h"
|
||||
#include "scene.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <KDecoration2/Decoration>
|
||||
#include <KDecoration2/DecoratedClient>
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
DecorationRenderer::DecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||
: m_client(client)
|
||||
, m_imageSizesDirty(true)
|
||||
{
|
||||
connect(client->decoration(), &KDecoration2::Decoration::damaged,
|
||||
this, &DecorationRenderer::addDamage);
|
||||
|
||||
connect(client->client(), &AbstractClient::screenScaleChanged,
|
||||
this, &DecorationRenderer::invalidate);
|
||||
connect(client->decoration(), &KDecoration2::Decoration::bordersChanged,
|
||||
this, &DecorationRenderer::invalidate);
|
||||
connect(client->decoratedClient(), &KDecoration2::DecoratedClient::sizeChanged,
|
||||
this, &DecorationRenderer::invalidate);
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
Decoration::DecoratedClientImpl *DecorationRenderer::client() const
|
||||
{
|
||||
return m_client;
|
||||
}
|
||||
|
||||
void DecorationRenderer::invalidate()
|
||||
{
|
||||
addDamage(m_client->client()->rect());
|
||||
m_imageSizesDirty = true;
|
||||
}
|
||||
|
||||
QRegion DecorationRenderer::damage() const
|
||||
{
|
||||
return m_damage;
|
||||
}
|
||||
|
||||
void DecorationRenderer::addDamage(const QRegion ®ion)
|
||||
{
|
||||
m_damage += region;
|
||||
emit damaged(region);
|
||||
}
|
||||
|
||||
void DecorationRenderer::resetDamage()
|
||||
{
|
||||
m_damage = QRegion();
|
||||
}
|
||||
|
||||
QImage DecorationRenderer::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_CORE) << "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 DecorationRenderer::renderToPainter(QPainter *painter, const QRect &rect)
|
||||
{
|
||||
client()->decoration()->paint(painter, rect);
|
||||
}
|
||||
|
||||
DecorationItem::DecorationItem(KDecoration2::Decoration *decoration, Scene::Window *window, Item *parent)
|
||||
: Item(window, parent)
|
||||
{
|
||||
Toplevel *toplevel = window->window();
|
||||
AbstractClient *client = qobject_cast<AbstractClient *>(window->window());
|
||||
m_renderer.reset(Compositor::self()->scene()->createDecorationRenderer(client->decoratedClient()));
|
||||
|
||||
connect(toplevel, &Toplevel::frameGeometryChanged,
|
||||
connect(client, &Toplevel::frameGeometryChanged,
|
||||
this, &DecorationItem::handleFrameGeometryChanged);
|
||||
|
||||
connect(toplevel, &Toplevel::screenScaleChanged,
|
||||
connect(client, &Toplevel::screenScaleChanged,
|
||||
this, &DecorationItem::discardQuads);
|
||||
connect(decoration, &KDecoration2::Decoration::bordersChanged,
|
||||
this, &DecorationItem::discardQuads);
|
||||
|
||||
setSize(toplevel->size());
|
||||
connect(renderer(), &DecorationRenderer::damaged,
|
||||
this, &DecorationItem::scheduleRepaint);
|
||||
|
||||
// If the decoration is about to be destroyed, render the decoration for the last time.
|
||||
connect(client, &Toplevel::markedAsZombie, this, &DecorationItem::preprocess);
|
||||
|
||||
setSize(client->size());
|
||||
}
|
||||
|
||||
void DecorationItem::preprocess()
|
||||
{
|
||||
const QRegion damage = m_renderer->damage();
|
||||
if (!damage.isEmpty()) {
|
||||
m_renderer->render(damage);
|
||||
m_renderer->resetDamage();
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationItem::handleFrameGeometryChanged()
|
||||
|
@ -32,4 +139,9 @@ void DecorationItem::handleFrameGeometryChanged()
|
|||
setSize(window()->size());
|
||||
}
|
||||
|
||||
DecorationRenderer *DecorationItem::renderer() const
|
||||
{
|
||||
return m_renderer.data();
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -16,6 +16,47 @@ class Decoration;
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
namespace Decoration
|
||||
{
|
||||
class DecoratedClientImpl;
|
||||
}
|
||||
|
||||
class KWIN_EXPORT DecorationRenderer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual void render(const QRegion ®ion) = 0;
|
||||
void invalidate();
|
||||
|
||||
// TODO: Move damage tracking inside DecorationItem.
|
||||
QRegion damage() const;
|
||||
void addDamage(const QRegion ®ion);
|
||||
void resetDamage();
|
||||
|
||||
Q_SIGNALS:
|
||||
void damaged(const QRegion ®ion);
|
||||
|
||||
protected:
|
||||
explicit DecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||
|
||||
Decoration::DecoratedClientImpl *client() const;
|
||||
|
||||
bool areImageSizesDirty() const {
|
||||
return m_imageSizesDirty;
|
||||
}
|
||||
void resetImageSizesDirty() {
|
||||
m_imageSizesDirty = false;
|
||||
}
|
||||
QImage renderToImage(const QRect &geo);
|
||||
void renderToPainter(QPainter *painter, const QRect &rect);
|
||||
|
||||
private:
|
||||
QPointer<Decoration::DecoratedClientImpl> m_client;
|
||||
QRegion m_damage;
|
||||
bool m_imageSizesDirty;
|
||||
};
|
||||
|
||||
/**
|
||||
* The DecorationItem class represents a server-side decoration.
|
||||
*/
|
||||
|
@ -26,11 +67,17 @@ class KWIN_EXPORT DecorationItem : public Item
|
|||
public:
|
||||
explicit DecorationItem(KDecoration2::Decoration *decoration, Scene::Window *window, Item *parent = nullptr);
|
||||
|
||||
DecorationRenderer *renderer() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleFrameGeometryChanged();
|
||||
|
||||
protected:
|
||||
void preprocess() override;
|
||||
|
||||
private:
|
||||
QPointer<KDecoration2::Decoration> m_decoration;
|
||||
QScopedPointer<DecorationRenderer> m_renderer;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "decoratedclient.h"
|
||||
#include "decorationbridge.h"
|
||||
#include "decorationpalette.h"
|
||||
#include "decorationrenderer.h"
|
||||
#include "abstract_client.h"
|
||||
#include "composite.h"
|
||||
#include "cursor.h"
|
||||
|
@ -33,9 +32,7 @@ DecoratedClientImpl::DecoratedClientImpl(AbstractClient *client, KDecoration2::D
|
|||
, ApplicationMenuEnabledDecoratedClientPrivate(decoratedClient, decoration)
|
||||
, m_client(client)
|
||||
, m_clientSize(client->clientSize())
|
||||
, m_renderer(nullptr)
|
||||
{
|
||||
createRenderer();
|
||||
client->setDecoratedClient(QPointer<DecoratedClientImpl>(this));
|
||||
connect(client, &AbstractClient::activeChanged, this,
|
||||
[decoratedClient, client]() {
|
||||
|
@ -77,19 +74,6 @@ DecoratedClientImpl::DecoratedClientImpl(AbstractClient *client, KDecoration2::D
|
|||
&Decoration::DecoratedClientImpl::signalShadeChange);
|
||||
connect(client, &AbstractClient::keepAboveChanged, decoratedClient, &KDecoration2::DecoratedClient::keepAboveChanged);
|
||||
connect(client, &AbstractClient::keepBelowChanged, decoratedClient, &KDecoration2::DecoratedClient::keepBelowChanged);
|
||||
connect(Compositor::self(), &Compositor::aboutToToggleCompositing, this, &DecoratedClientImpl::destroyRenderer);
|
||||
m_compositorToggledConnection = connect(Compositor::self(), &Compositor::compositingToggled, this,
|
||||
[this, decoration]() {
|
||||
createRenderer();
|
||||
decoration->update();
|
||||
}
|
||||
);
|
||||
connect(Compositor::self(), &Compositor::aboutToDestroy, this,
|
||||
[this] {
|
||||
disconnect(m_compositorToggledConnection);
|
||||
m_compositorToggledConnection = QMetaObject::Connection();
|
||||
}
|
||||
);
|
||||
connect(client, &AbstractClient::quickTileModeChanged, decoratedClient,
|
||||
[this, decoratedClient]() {
|
||||
emit decoratedClient->adjacentScreenEdgesChanged(adjacentScreenEdges());
|
||||
|
@ -318,16 +302,5 @@ bool DecoratedClientImpl::isApplicationMenuActive() const
|
|||
return m_client->applicationMenuActive();
|
||||
}
|
||||
|
||||
void DecoratedClientImpl::createRenderer()
|
||||
{
|
||||
m_renderer = kwinApp()->platform()->createDecorationRenderer(this);
|
||||
}
|
||||
|
||||
void DecoratedClientImpl::destroyRenderer()
|
||||
{
|
||||
delete m_renderer;
|
||||
m_renderer = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,6 @@ class AbstractClient;
|
|||
namespace Decoration
|
||||
{
|
||||
|
||||
class Renderer;
|
||||
|
||||
class DecoratedClientImpl : public QObject, public KDecoration2::ApplicationMenuEnabledDecoratedClientPrivate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -82,9 +80,6 @@ public:
|
|||
AbstractClient *client() {
|
||||
return m_client;
|
||||
}
|
||||
Renderer *renderer() {
|
||||
return m_renderer;
|
||||
}
|
||||
KDecoration2::DecoratedClient *decoratedClient() {
|
||||
return KDecoration2::DecoratedClientPrivate::client();
|
||||
}
|
||||
|
@ -95,12 +90,8 @@ private Q_SLOTS:
|
|||
void delayedRequestToggleMaximization(Options::WindowOperation operation);
|
||||
|
||||
private:
|
||||
void createRenderer();
|
||||
void destroyRenderer();
|
||||
AbstractClient *m_client;
|
||||
QSize m_clientSize;
|
||||
Renderer *m_renderer;
|
||||
QMetaObject::Connection m_compositorToggledConnection;
|
||||
|
||||
QString m_toolTipText;
|
||||
QTimer m_toolTipWakeUp;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
#include "decorationbridge.h"
|
||||
#include "decoratedclient.h"
|
||||
#include "decorationrenderer.h"
|
||||
#include "decorations_logging.h"
|
||||
#include "settings.h"
|
||||
// KWin core
|
||||
|
|
|
@ -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
|
|
@ -14,8 +14,6 @@
|
|||
#include "group.h"
|
||||
#include "netinfo.h"
|
||||
#include "shadow.h"
|
||||
#include "decorations/decoratedclient.h"
|
||||
#include "decorations/decorationrenderer.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
@ -30,13 +28,11 @@ Deleted::Deleted()
|
|||
, m_minimized(false)
|
||||
, m_modal(false)
|
||||
, m_wasClient(false)
|
||||
, m_decorationRenderer(nullptr)
|
||||
, m_fullscreen(false)
|
||||
, m_keepAbove(false)
|
||||
, m_keepBelow(false)
|
||||
, m_wasPopupWindow(false)
|
||||
, m_wasOutline(false)
|
||||
, m_wasDecorated(false)
|
||||
, m_wasLockScreen(false)
|
||||
{
|
||||
}
|
||||
|
@ -85,18 +81,11 @@ void Deleted::copyToDeleted(Toplevel* c)
|
|||
if (WinInfo* cinfo = dynamic_cast< WinInfo* >(info))
|
||||
cinfo->disable();
|
||||
if (AbstractClient *client = dynamic_cast<AbstractClient*>(c)) {
|
||||
m_wasDecorated = client->isDecorated();
|
||||
if (m_wasDecorated) {
|
||||
if (client->isDecorated()) {
|
||||
client->layoutDecorationRects(decoration_left,
|
||||
decoration_top,
|
||||
decoration_right,
|
||||
decoration_bottom);
|
||||
if (client->isDecorated()) {
|
||||
if (Decoration::Renderer *renderer = client->decoratedClient()->renderer()) {
|
||||
m_decorationRenderer = renderer;
|
||||
m_decorationRenderer->reparent(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_wasClient = true;
|
||||
m_minimized = client->isMinimized();
|
||||
|
@ -163,11 +152,6 @@ QPoint Deleted::clientPos() const
|
|||
return contentsRect.topLeft();
|
||||
}
|
||||
|
||||
bool Deleted::wasDecorated() const
|
||||
{
|
||||
return m_wasDecorated;
|
||||
}
|
||||
|
||||
void Deleted::layoutDecorationRects(QRect& left, QRect& top, QRect& right, QRect& bottom) const
|
||||
{
|
||||
left = decoration_left;
|
||||
|
|
|
@ -17,11 +17,6 @@ namespace KWin
|
|||
|
||||
class AbstractClient;
|
||||
|
||||
namespace Decoration
|
||||
{
|
||||
class Renderer;
|
||||
}
|
||||
|
||||
class KWIN_EXPORT Deleted : public Toplevel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -41,7 +36,6 @@ public:
|
|||
QRect transparentRect() const override;
|
||||
bool isDeleted() const override;
|
||||
xcb_window_t frameId() const override;
|
||||
bool wasDecorated() const;
|
||||
void layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect &bottom) const;
|
||||
Layer layer() const override {
|
||||
return m_layer;
|
||||
|
@ -61,10 +55,6 @@ public:
|
|||
}
|
||||
QByteArray windowRole() const override;
|
||||
|
||||
const Decoration::Renderer *decorationRenderer() const {
|
||||
return m_decorationRenderer;
|
||||
}
|
||||
|
||||
bool isFullScreen() const {
|
||||
return m_fullscreen;
|
||||
}
|
||||
|
@ -127,7 +117,6 @@ private:
|
|||
bool m_modal;
|
||||
QList<AbstractClient*> m_mainClients;
|
||||
bool m_wasClient;
|
||||
Decoration::Renderer *m_decorationRenderer;
|
||||
NET::WindowType m_type = NET::Unknown;
|
||||
QByteArray m_windowRole;
|
||||
bool m_fullscreen;
|
||||
|
@ -136,7 +125,6 @@ private:
|
|||
QString m_caption;
|
||||
bool m_wasPopupWindow;
|
||||
bool m_wasOutline;
|
||||
bool m_wasDecorated;
|
||||
bool m_wasLockScreen;
|
||||
qreal m_bufferScale = 1;
|
||||
};
|
||||
|
|
|
@ -595,14 +595,6 @@ OutlineVisual *Platform::createOutline(Outline *outline)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Decoration::Renderer *Platform::createDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||
{
|
||||
if (Compositor::self()->scene()) {
|
||||
return Compositor::self()->scene()->createDecorationRenderer(client);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Platform::invertScreen()
|
||||
{
|
||||
if (effects) {
|
||||
|
|
|
@ -45,12 +45,6 @@ class Toplevel;
|
|||
class XRenderBackend;
|
||||
#endif
|
||||
|
||||
namespace Decoration
|
||||
{
|
||||
class Renderer;
|
||||
class DecoratedClientImpl;
|
||||
}
|
||||
|
||||
class KWIN_EXPORT Outputs : public QVector<AbstractOutput*>
|
||||
{
|
||||
public:
|
||||
|
@ -359,13 +353,6 @@ public:
|
|||
*/
|
||||
virtual OutlineVisual *createOutline(Outline *outline);
|
||||
|
||||
/**
|
||||
* Creates the Decoration::Renderer for the given @p client.
|
||||
*
|
||||
* The default implementation creates a Renderer suited for the Compositor, @c nullptr if there is no Compositor.
|
||||
*/
|
||||
virtual Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||
|
||||
/**
|
||||
* Platform specific way to invert the screen.
|
||||
* Default implementation invokes the invert effect
|
||||
|
|
|
@ -8,7 +8,6 @@ set(X11PLATFORM_SOURCES
|
|||
overlaywindow_x11.cpp
|
||||
screenedges_filter.cpp
|
||||
windowselector.cpp
|
||||
x11_decoration_renderer.cpp
|
||||
x11_output.cpp
|
||||
x11_platform.cpp
|
||||
x11cursor.cpp
|
||||
|
|
|
@ -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
|
|
@ -33,7 +33,6 @@
|
|||
#include "overlaywindow_x11.h"
|
||||
#include "non_composited_outline.h"
|
||||
#include "workspace.h"
|
||||
#include "x11_decoration_renderer.h"
|
||||
#include "x11_output.h"
|
||||
#include "xcbutils.h"
|
||||
#include "renderloop.h"
|
||||
|
@ -406,15 +405,6 @@ OutlineVisual *X11StandalonePlatform::createOutline(Outline *outline)
|
|||
return ret;
|
||||
}
|
||||
|
||||
Decoration::Renderer *X11StandalonePlatform::createDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||
{
|
||||
auto renderer = Platform::createDecorationRenderer(client);
|
||||
if (!renderer) {
|
||||
renderer = new Decoration::X11Renderer(client);
|
||||
}
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void X11StandalonePlatform::invertScreen()
|
||||
{
|
||||
using namespace Xcb::RandR;
|
||||
|
|
|
@ -57,7 +57,6 @@ public:
|
|||
|
||||
OverlayWindow *createOverlayWindow() override;
|
||||
OutlineVisual *createOutline(Outline *outline) override;
|
||||
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client) override;
|
||||
|
||||
void invertScreen() override;
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "decorations/decoratedclient.h"
|
||||
#include "shadowitem.h"
|
||||
#include "surfaceitem.h"
|
||||
#include "windowitem.h"
|
||||
#include <logging.h>
|
||||
|
||||
#include <KWaylandServer/buffer_interface.h>
|
||||
|
@ -901,7 +902,7 @@ Shadow *SceneOpenGL::createShadow(Toplevel *toplevel)
|
|||
return new SceneOpenGLShadow(toplevel);
|
||||
}
|
||||
|
||||
Decoration::Renderer *SceneOpenGL::createDecorationRenderer(Decoration::DecoratedClientImpl *impl)
|
||||
DecorationRenderer *SceneOpenGL::createDecorationRenderer(Decoration::DecoratedClientImpl *impl)
|
||||
{
|
||||
return new SceneOpenGLDecorationRenderer(impl);
|
||||
}
|
||||
|
@ -1213,22 +1214,10 @@ void OpenGLWindow::endRenderWindow()
|
|||
|
||||
GLTexture *OpenGLWindow::getDecorationTexture() const
|
||||
{
|
||||
if (AbstractClient *client = dynamic_cast<AbstractClient *>(toplevel)) {
|
||||
if (!client->isDecorated()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (SceneOpenGLDecorationRenderer *renderer = static_cast<SceneOpenGLDecorationRenderer*>(client->decoratedClient()->renderer())) {
|
||||
renderer->render();
|
||||
return renderer->texture();
|
||||
}
|
||||
} else if (toplevel->isDeleted()) {
|
||||
Deleted *deleted = static_cast<Deleted *>(toplevel);
|
||||
if (!deleted->wasDecorated()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (const SceneOpenGLDecorationRenderer *renderer = static_cast<const SceneOpenGLDecorationRenderer*>(deleted->decorationRenderer())) {
|
||||
return renderer->texture();
|
||||
}
|
||||
const DecorationItem *decorationItem = windowItem()->decorationItem();
|
||||
if (decorationItem) {
|
||||
auto renderer = static_cast<const SceneOpenGLDecorationRenderer *>(decorationItem->renderer());
|
||||
return renderer->texture();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2489,10 +2478,9 @@ bool SceneOpenGLShadow::prepareBackend()
|
|||
}
|
||||
|
||||
SceneOpenGLDecorationRenderer::SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||
: Renderer(client)
|
||||
: DecorationRenderer(client)
|
||||
, m_texture()
|
||||
{
|
||||
connect(this, &Renderer::renderScheduled, client->client(), static_cast<void (AbstractClient::*)(const QRegion&)>(&AbstractClient::addRepaint));
|
||||
}
|
||||
|
||||
SceneOpenGLDecorationRenderer::~SceneOpenGLDecorationRenderer()
|
||||
|
@ -2573,12 +2561,8 @@ static void clamp(QImage &image, const QRect &viewport)
|
|||
}
|
||||
}
|
||||
|
||||
void SceneOpenGLDecorationRenderer::render()
|
||||
void SceneOpenGLDecorationRenderer::render(const QRegion ®ion)
|
||||
{
|
||||
const QRegion scheduled = getScheduled();
|
||||
if (scheduled.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (areImageSizesDirty()) {
|
||||
resizeTexture();
|
||||
resetImageSizesDirty();
|
||||
|
@ -2645,7 +2629,7 @@ void SceneOpenGLDecorationRenderer::render()
|
|||
m_texture->update(image, (position + dirtyOffset - viewport.topLeft()) * image.devicePixelRatio());
|
||||
};
|
||||
|
||||
const QRect geometry = scheduled.boundingRect();
|
||||
const QRect geometry = region.boundingRect();
|
||||
|
||||
const QPoint topPosition(padding, padding);
|
||||
const QPoint bottomPosition(padding, topPosition.y() + top.height() + 2 * padding);
|
||||
|
@ -2695,13 +2679,6 @@ void SceneOpenGLDecorationRenderer::resizeTexture()
|
|||
}
|
||||
}
|
||||
|
||||
void SceneOpenGLDecorationRenderer::reparent(Deleted *deleted)
|
||||
{
|
||||
render();
|
||||
Renderer::reparent(deleted);
|
||||
}
|
||||
|
||||
|
||||
OpenGLFactory::OpenGLFactory(QObject *parent)
|
||||
: SceneFactory(parent)
|
||||
{
|
||||
|
|
|
@ -13,13 +13,12 @@
|
|||
|
||||
#include "openglbackend.h"
|
||||
|
||||
#include "decorationitem.h"
|
||||
#include "scene.h"
|
||||
#include "shadow.h"
|
||||
|
||||
#include "kwinglutils.h"
|
||||
|
||||
#include "decorations/decorationrenderer.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
class LanczosFilter;
|
||||
|
@ -45,7 +44,7 @@ public:
|
|||
void doneOpenGLContextCurrent() override;
|
||||
bool supportsSurfacelessContext() const override;
|
||||
bool supportsNativeFence() const override;
|
||||
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
|
||||
DecorationRenderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
|
||||
void triggerFence() override;
|
||||
virtual QMatrix4x4 projectionMatrix() const = 0;
|
||||
bool animationsSupported() const override;
|
||||
|
@ -256,7 +255,7 @@ private:
|
|||
QSharedPointer<GLTexture> m_texture;
|
||||
};
|
||||
|
||||
class SceneOpenGLDecorationRenderer : public Decoration::Renderer
|
||||
class SceneOpenGLDecorationRenderer : public DecorationRenderer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -270,8 +269,7 @@ public:
|
|||
explicit SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||
~SceneOpenGLDecorationRenderer() override;
|
||||
|
||||
void render() override;
|
||||
void reparent(Deleted *deleted) override;
|
||||
void render(const QRegion ®ion) override;
|
||||
|
||||
GLTexture *texture() {
|
||||
return m_texture.data();
|
||||
|
|
|
@ -314,25 +314,18 @@ void SceneQPainter::Window::renderShadow(QPainter* painter)
|
|||
void SceneQPainter::Window::renderWindowDecorations(QPainter *painter)
|
||||
{
|
||||
// TODO: custom decoration opacity
|
||||
AbstractClient *client = dynamic_cast<AbstractClient*>(toplevel);
|
||||
Deleted *deleted = dynamic_cast<Deleted*>(toplevel);
|
||||
if (!client && !deleted) {
|
||||
const DecorationItem *decorationItem = windowItem()->decorationItem();
|
||||
if (!decorationItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SceneQPainterDecorationRenderer *renderer = nullptr;
|
||||
const auto renderer = static_cast<const SceneQPainterDecorationRenderer *>(decorationItem->renderer());
|
||||
QRect dtr, dlr, drr, dbr;
|
||||
if (client && client->isDecorated()) {
|
||||
if (SceneQPainterDecorationRenderer *r = static_cast<SceneQPainterDecorationRenderer *>(client->decoratedClient()->renderer())) {
|
||||
r->render();
|
||||
renderer = r;
|
||||
}
|
||||
if (auto client = qobject_cast<AbstractClient *>(toplevel)) {
|
||||
client->layoutDecorationRects(dlr, dtr, drr, dbr);
|
||||
} else if (deleted && deleted->wasDecorated()) {
|
||||
} else if (auto deleted = qobject_cast<Deleted *>(toplevel)) {
|
||||
deleted->layoutDecorationRects(dlr, dtr, drr, dbr);
|
||||
renderer = static_cast<const SceneQPainterDecorationRenderer *>(deleted->decorationRenderer());
|
||||
}
|
||||
if (!renderer) {
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -342,7 +335,7 @@ void SceneQPainter::Window::renderWindowDecorations(QPainter *painter)
|
|||
painter->drawImage(dbr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Bottom));
|
||||
}
|
||||
|
||||
Decoration::Renderer *SceneQPainter::createDecorationRenderer(Decoration::DecoratedClientImpl *impl)
|
||||
DecorationRenderer *SceneQPainter::createDecorationRenderer(Decoration::DecoratedClientImpl *impl)
|
||||
{
|
||||
return new SceneQPainterDecorationRenderer(impl);
|
||||
}
|
||||
|
@ -690,25 +683,18 @@ bool SceneQPainterShadow::prepareBackend()
|
|||
// QPainterDecorationRenderer
|
||||
//****************************************
|
||||
SceneQPainterDecorationRenderer::SceneQPainterDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||
: Renderer(client)
|
||||
: DecorationRenderer(client)
|
||||
{
|
||||
connect(this, &Renderer::renderScheduled, client->client(), static_cast<void (AbstractClient::*)(const QRegion&)>(&AbstractClient::addRepaint));
|
||||
}
|
||||
|
||||
SceneQPainterDecorationRenderer::~SceneQPainterDecorationRenderer() = default;
|
||||
|
||||
QImage SceneQPainterDecorationRenderer::image(SceneQPainterDecorationRenderer::DecorationPart part) const
|
||||
{
|
||||
Q_ASSERT(part != DecorationPart::Count);
|
||||
return m_images[int(part)];
|
||||
}
|
||||
|
||||
void SceneQPainterDecorationRenderer::render()
|
||||
void SceneQPainterDecorationRenderer::render(const QRegion ®ion)
|
||||
{
|
||||
const QRegion scheduled = getScheduled();
|
||||
if (scheduled.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (areImageSizesDirty()) {
|
||||
resizeImages();
|
||||
resetImageSizesDirty();
|
||||
|
@ -723,7 +709,7 @@ void SceneQPainterDecorationRenderer::render()
|
|||
const QRect right(QPoint(top.width() - imageSize(DecorationPart::Right).width(), top.height()), imageSize(DecorationPart::Right));
|
||||
const QRect bottom(QPoint(0, left.y() + left.height()), imageSize(DecorationPart::Bottom));
|
||||
|
||||
const QRect geometry = scheduled.boundingRect();
|
||||
const QRect geometry = region.boundingRect();
|
||||
auto renderPart = [this](const QRect &rect, const QRect &partRect, int index) {
|
||||
if (rect.isEmpty()) {
|
||||
return;
|
||||
|
@ -767,13 +753,6 @@ void SceneQPainterDecorationRenderer::resizeImages()
|
|||
checkAndCreate(int(DecorationPart::Bottom), bottom.size());
|
||||
}
|
||||
|
||||
void SceneQPainterDecorationRenderer::reparent(Deleted *deleted)
|
||||
{
|
||||
render();
|
||||
Renderer::reparent(deleted);
|
||||
}
|
||||
|
||||
|
||||
QPainterFactory::QPainterFactory(QObject *parent)
|
||||
: SceneFactory(parent)
|
||||
{
|
||||
|
|
|
@ -11,11 +11,10 @@
|
|||
|
||||
#include "qpainterbackend.h"
|
||||
|
||||
#include "decorationitem.h"
|
||||
#include "scene.h"
|
||||
#include "shadow.h"
|
||||
|
||||
#include "decorations/decorationrenderer.h"
|
||||
|
||||
namespace KWin {
|
||||
|
||||
class KWIN_EXPORT SceneQPainter : public Scene
|
||||
|
@ -32,7 +31,7 @@ public:
|
|||
bool initFailed() const override;
|
||||
EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
|
||||
Shadow *createShadow(Toplevel *toplevel) override;
|
||||
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
|
||||
DecorationRenderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
|
||||
void screenGeometryChanged(const QSize &size) override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
|
||||
|
@ -112,7 +111,7 @@ private:
|
|||
QImage m_texture;
|
||||
};
|
||||
|
||||
class SceneQPainterDecorationRenderer : public Decoration::Renderer
|
||||
class SceneQPainterDecorationRenderer : public DecorationRenderer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -124,10 +123,8 @@ public:
|
|||
Count
|
||||
};
|
||||
explicit SceneQPainterDecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||
~SceneQPainterDecorationRenderer() override;
|
||||
|
||||
void render() override;
|
||||
void reparent(Deleted *deleted) override;
|
||||
void render(const QRegion ®ion) override;
|
||||
|
||||
QImage image(DecorationPart part) const;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "screens.h"
|
||||
#include "shadowitem.h"
|
||||
#include "surfaceitem_x11.h"
|
||||
#include "windowitem.h"
|
||||
#include "xcbutils.h"
|
||||
#include "decorations/decoratedclient.h"
|
||||
|
||||
|
@ -135,7 +136,7 @@ Shadow *SceneXrender::createShadow(Toplevel *toplevel)
|
|||
return new SceneXRenderShadow(toplevel);
|
||||
}
|
||||
|
||||
Decoration::Renderer *SceneXrender::createDecorationRenderer(Decoration::DecoratedClientImpl* client)
|
||||
DecorationRenderer *SceneXrender::createDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||
{
|
||||
return new SceneXRenderDecorationRenderer(client);
|
||||
}
|
||||
|
@ -309,7 +310,8 @@ void SceneXrender::Window::performPaint(int mask, const QRegion &_region, const
|
|||
X11Client *client = dynamic_cast<X11Client *>(toplevel);
|
||||
Deleted *deleted = dynamic_cast<Deleted*>(toplevel);
|
||||
const QRect decorationRect = toplevel->rect();
|
||||
if ((client && client->isDecorated()) || (deleted && deleted->wasDecorated())) {
|
||||
const DecorationItem *decorationItem = windowItem()->decorationItem();
|
||||
if (decorationItem) {
|
||||
// decorated client
|
||||
transformed_shape = decorationRect;
|
||||
if (toplevel->shape()) {
|
||||
|
@ -378,7 +380,7 @@ void SceneXrender::Window::performPaint(int mask, const QRegion &_region, const
|
|||
// This solves a number of glitches and on top of this
|
||||
// it optimizes painting quite a bit
|
||||
const bool blitInTempPixmap = xRenderOffscreen() || (data.crossFadeProgress() < 1.0 && !opaque) ||
|
||||
(scaled && (wantShadow || (client && client->isDecorated()) || (deleted && deleted->wasDecorated())));
|
||||
(scaled && (wantShadow || decorationItem));
|
||||
|
||||
xcb_render_picture_t renderTarget = m_scene->xrenderBufferPicture();
|
||||
if (blitInTempPixmap) {
|
||||
|
@ -423,18 +425,15 @@ void SceneXrender::Window::performPaint(int mask, const QRegion &_region, const
|
|||
xcb_render_picture_t bottom = XCB_RENDER_PICTURE_NONE;
|
||||
QRect dtr, dlr, drr, dbr;
|
||||
const SceneXRenderDecorationRenderer *renderer = nullptr;
|
||||
if (client && client->isDecorated()) {
|
||||
SceneXRenderDecorationRenderer *r = static_cast<SceneXRenderDecorationRenderer*>(client->decoratedClient()->renderer());
|
||||
if (r) {
|
||||
r->render();
|
||||
renderer = r;
|
||||
if (decorationItem) {
|
||||
renderer = static_cast<const SceneXRenderDecorationRenderer *>(decorationItem->renderer());
|
||||
noBorder = false;
|
||||
|
||||
if (client) {
|
||||
client->layoutDecorationRects(dlr, dtr, drr, dbr);
|
||||
} else if (deleted) {
|
||||
deleted->layoutDecorationRects(dlr, dtr, drr, dbr);
|
||||
}
|
||||
noBorder = false;
|
||||
client->layoutDecorationRects(dlr, dtr, drr, dbr);
|
||||
} else if (deleted && deleted->wasDecorated()) {
|
||||
renderer = static_cast<const SceneXRenderDecorationRenderer*>(deleted->decorationRenderer());
|
||||
noBorder = false;
|
||||
deleted->layoutDecorationRects(dlr, dtr, drr, dbr);
|
||||
}
|
||||
if (renderer) {
|
||||
left = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Left);
|
||||
|
@ -1004,10 +1003,9 @@ xcb_render_picture_t SceneXRenderShadow::picture(Shadow::ShadowElements element)
|
|||
}
|
||||
|
||||
SceneXRenderDecorationRenderer::SceneXRenderDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||
: Renderer(client)
|
||||
: DecorationRenderer(client)
|
||||
, m_gc(XCB_NONE)
|
||||
{
|
||||
connect(this, &Renderer::renderScheduled, client->client(), static_cast<void (AbstractClient::*)(const QRegion&)>(&AbstractClient::addRepaint));
|
||||
for (int i = 0; i < int(DecorationPart::Count); ++i) {
|
||||
m_pixmaps[i] = XCB_PIXMAP_NONE;
|
||||
m_pictures[i] = nullptr;
|
||||
|
@ -1027,12 +1025,8 @@ SceneXRenderDecorationRenderer::~SceneXRenderDecorationRenderer()
|
|||
}
|
||||
}
|
||||
|
||||
void SceneXRenderDecorationRenderer::render()
|
||||
void SceneXRenderDecorationRenderer::render(const QRegion ®ion)
|
||||
{
|
||||
QRegion scheduled = getScheduled();
|
||||
if (scheduled.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (areImageSizesDirty()) {
|
||||
resizePixmaps();
|
||||
resetImageSizesDirty();
|
||||
|
@ -1058,7 +1052,7 @@ void SceneXRenderDecorationRenderer::render()
|
|||
image.width(), image.height(), geo.x() - offset.x(), geo.y() - offset.y(), 0, 32,
|
||||
image.sizeInBytes(), image.constBits());
|
||||
};
|
||||
const QRect geometry = scheduled.boundingRect();
|
||||
const QRect geometry = region.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));
|
||||
|
@ -1113,12 +1107,6 @@ xcb_render_picture_t SceneXRenderDecorationRenderer::picture(SceneXRenderDecorat
|
|||
return *picture;
|
||||
}
|
||||
|
||||
void SceneXRenderDecorationRenderer::reparent(Deleted *deleted)
|
||||
{
|
||||
render();
|
||||
Renderer::reparent(deleted);
|
||||
}
|
||||
|
||||
#undef DOUBLE_TO_FIXED
|
||||
#undef FIXED_TO_DOUBLE
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#ifndef KWIN_SCENE_XRENDER_H
|
||||
#define KWIN_SCENE_XRENDER_H
|
||||
|
||||
#include "decorationitem.h"
|
||||
#include "scene.h"
|
||||
#include "shadow.h"
|
||||
#include "decorations/decorationrenderer.h"
|
||||
|
||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||
|
||||
|
@ -39,7 +39,7 @@ public:
|
|||
void screenGeometryChanged(const QSize &size) override;
|
||||
xcb_render_picture_t xrenderBufferPicture() const override;
|
||||
OverlayWindow *overlayWindow() const override;
|
||||
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client) override;
|
||||
DecorationRenderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client) override;
|
||||
PlatformSurfaceTexture *createPlatformSurfaceTextureX11(SurfacePixmapX11 *pixmap) override;
|
||||
|
||||
bool animationsSupported() const override {
|
||||
|
@ -162,7 +162,7 @@ private:
|
|||
XRenderPicture* m_pictures[ShadowElementsCount];
|
||||
};
|
||||
|
||||
class SceneXRenderDecorationRenderer : public Decoration::Renderer
|
||||
class SceneXRenderDecorationRenderer : public DecorationRenderer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -176,8 +176,7 @@ public:
|
|||
explicit SceneXRenderDecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||
~SceneXRenderDecorationRenderer() override;
|
||||
|
||||
void render() override;
|
||||
void reparent(Deleted *deleted) override;
|
||||
void render(const QRegion ®ion) override;
|
||||
|
||||
xcb_render_picture_t picture(DecorationPart part) const;
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
|
||||
#include "scene.h"
|
||||
#include "abstract_output.h"
|
||||
#include "decorationitem.h"
|
||||
#include "internal_client.h"
|
||||
#include "platform.h"
|
||||
#include "shadowitem.h"
|
||||
|
|
|
@ -23,12 +23,11 @@ namespace KWin
|
|||
namespace Decoration
|
||||
{
|
||||
class DecoratedClientImpl;
|
||||
class Renderer;
|
||||
}
|
||||
|
||||
class AbstractOutput;
|
||||
class AbstractThumbnailItem;
|
||||
class DecorationItem;
|
||||
class DecorationRenderer;
|
||||
class Deleted;
|
||||
class EffectFrameImpl;
|
||||
class EffectWindowImpl;
|
||||
|
@ -156,7 +155,7 @@ public:
|
|||
|
||||
virtual void triggerFence();
|
||||
|
||||
virtual Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *) = 0;
|
||||
virtual DecorationRenderer *createDecorationRenderer(Decoration::DecoratedClientImpl *) = 0;
|
||||
|
||||
/**
|
||||
* Whether the Scene is able to drive animations.
|
||||
|
|
|
@ -15,6 +15,7 @@ class Decoration;
|
|||
|
||||
namespace KWin
|
||||
{
|
||||
class DecorationItem;
|
||||
|
||||
/**
|
||||
* The WindowItem class represents a window in the scene.
|
||||
|
|
|
@ -75,6 +75,71 @@ const NET::WindowTypes SUPPORTED_MANAGED_WINDOW_TYPES_MASK = NET::NormalMask | N
|
|||
| NET::UtilityMask | NET::SplashMask | NET::NotificationMask | NET::OnScreenDisplayMask
|
||||
| NET::CriticalNotificationMask;
|
||||
|
||||
X11DecorationRenderer::X11DecorationRenderer(Decoration::DecoratedClientImpl *client)
|
||||
: DecorationRenderer(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, &X11DecorationRenderer::update);
|
||||
connect(this, &X11DecorationRenderer::damaged, m_scheduleTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
|
||||
}
|
||||
|
||||
X11DecorationRenderer::~X11DecorationRenderer()
|
||||
{
|
||||
if (m_gc != XCB_NONE) {
|
||||
xcb_free_gc(connection(), m_gc);
|
||||
}
|
||||
}
|
||||
|
||||
void X11DecorationRenderer::update()
|
||||
{
|
||||
if (!damage().isEmpty()) {
|
||||
render(damage());
|
||||
resetDamage();
|
||||
}
|
||||
}
|
||||
|
||||
void X11DecorationRenderer::render(const QRegion ®ion)
|
||||
{
|
||||
if (!client()) {
|
||||
return;
|
||||
}
|
||||
xcb_connection_t *c = kwinApp()->x11Connection();
|
||||
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 = region.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();
|
||||
}
|
||||
|
||||
// Creating a client:
|
||||
// - only by calling Workspace::createClient()
|
||||
// - it creates a new client and calls manage() for it
|
||||
|
@ -1054,6 +1119,7 @@ void X11Client::createDecoration(const QRect& oldgeom)
|
|||
move(calculateGravitation(false));
|
||||
resize(adjustedSize());
|
||||
updateDecorationInputShape();
|
||||
maybeCreateX11DecorationRenderer();
|
||||
if (Compositor::compositing()) {
|
||||
discardWindowPixmap();
|
||||
}
|
||||
|
@ -1066,6 +1132,7 @@ void X11Client::destroyDecoration()
|
|||
if (isDecorated()) {
|
||||
QPoint grav = calculateGravitation(true);
|
||||
AbstractClient::destroyDecoration();
|
||||
maybeDestroyX11DecorationRenderer();
|
||||
resize(adjustedSize());
|
||||
move(grav);
|
||||
if (compositing())
|
||||
|
@ -1077,6 +1144,22 @@ void X11Client::destroyDecoration()
|
|||
m_decoInputExtent.reset();
|
||||
}
|
||||
|
||||
void X11Client::maybeCreateX11DecorationRenderer()
|
||||
{
|
||||
if (kwinApp()->operationMode() != Application::OperationModeX11) {
|
||||
return;
|
||||
}
|
||||
if (!compositing() && decoratedClient()) {
|
||||
m_decorationRenderer.reset(new X11DecorationRenderer(decoratedClient()));
|
||||
decoration()->update();
|
||||
}
|
||||
}
|
||||
|
||||
void X11Client::maybeDestroyX11DecorationRenderer()
|
||||
{
|
||||
m_decorationRenderer.reset();
|
||||
}
|
||||
|
||||
void X11Client::layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect &bottom) const
|
||||
{
|
||||
if (!isDecorated()) {
|
||||
|
@ -1353,6 +1436,8 @@ bool X11Client::setupCompositing()
|
|||
if (!Toplevel::setupCompositing()){
|
||||
return false;
|
||||
}
|
||||
// If compositing is back on, stop rendering decoration in the frame window.
|
||||
maybeDestroyX11DecorationRenderer();
|
||||
updateVisibility(); // for internalKeep()
|
||||
return true;
|
||||
}
|
||||
|
@ -1363,6 +1448,8 @@ void X11Client::finishCompositing(ReleaseReason releaseReason)
|
|||
updateVisibility();
|
||||
// for safety in case KWin is just resizing the window
|
||||
resetHaveResizeEffect();
|
||||
// If compositing is off, render the decoration in the X11 frame window.
|
||||
maybeCreateX11DecorationRenderer();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#pragma once
|
||||
|
||||
// kwin
|
||||
#include "decorationitem.h"
|
||||
#include "options.h"
|
||||
#include "rules.h"
|
||||
#include "abstract_client.h"
|
||||
|
@ -46,6 +47,28 @@ enum class Predicate {
|
|||
InputIdMatch,
|
||||
};
|
||||
|
||||
/**
|
||||
* @todo Remove when the X11 platform support is dropped. This decoration renderer
|
||||
* will be used if compositing is off.
|
||||
*/
|
||||
class X11DecorationRenderer : public DecorationRenderer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit X11DecorationRenderer(Decoration::DecoratedClientImpl *client);
|
||||
~X11DecorationRenderer() override;
|
||||
|
||||
protected:
|
||||
void render(const QRegion ®ion) override;
|
||||
|
||||
private:
|
||||
void update();
|
||||
|
||||
QTimer *m_scheduleTimer;
|
||||
xcb_gcontext_t m_gc;
|
||||
};
|
||||
|
||||
class KWIN_EXPORT X11Client : public AbstractClient
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -424,6 +447,9 @@ private:
|
|||
*/
|
||||
void updateShowOnScreenEdge();
|
||||
|
||||
void maybeCreateX11DecorationRenderer();
|
||||
void maybeDestroyX11DecorationRenderer();
|
||||
|
||||
Xcb::Window m_client;
|
||||
Xcb::Window m_wrapper;
|
||||
Xcb::Window m_frame;
|
||||
|
@ -506,6 +532,7 @@ private:
|
|||
QRect m_bufferGeometryBeforeUpdateBlocking;
|
||||
QRect m_frameGeometryBeforeUpdateBlocking;
|
||||
QRect m_clientGeometryBeforeUpdateBlocking;
|
||||
QScopedPointer<X11DecorationRenderer> m_decorationRenderer;
|
||||
};
|
||||
|
||||
inline xcb_window_t X11Client::wrapperId() const
|
||||
|
|
Loading…
Reference in a new issue