File indexing completed on 2024-05-19 16:34:48
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "workspacescene_qpainter.h" 0010 // KWin 0011 #include "decorations/decoratedclient.h" 0012 #include "scene/itemrenderer_qpainter.h" 0013 #include "window.h" 0014 0015 // Qt 0016 #include <KDecoration2/Decoration> 0017 #include <QDebug> 0018 #include <QPainter> 0019 0020 #include <cmath> 0021 0022 namespace KWin 0023 { 0024 0025 //**************************************** 0026 // SceneQPainter 0027 //**************************************** 0028 0029 WorkspaceSceneQPainter::WorkspaceSceneQPainter(QPainterBackend *backend) 0030 : WorkspaceScene(std::make_unique<ItemRendererQPainter>()) 0031 , m_backend(backend) 0032 { 0033 } 0034 0035 WorkspaceSceneQPainter::~WorkspaceSceneQPainter() 0036 { 0037 } 0038 0039 std::unique_ptr<Shadow> WorkspaceSceneQPainter::createShadow(Window *window) 0040 { 0041 return std::make_unique<SceneQPainterShadow>(window); 0042 } 0043 0044 DecorationRenderer *WorkspaceSceneQPainter::createDecorationRenderer(Decoration::DecoratedClientImpl *impl) 0045 { 0046 return new SceneQPainterDecorationRenderer(impl); 0047 } 0048 0049 //**************************************** 0050 // QPainterShadow 0051 //**************************************** 0052 SceneQPainterShadow::SceneQPainterShadow(Window *window) 0053 : Shadow(window) 0054 { 0055 } 0056 0057 SceneQPainterShadow::~SceneQPainterShadow() 0058 { 0059 } 0060 0061 bool SceneQPainterShadow::prepareBackend() 0062 { 0063 return true; 0064 } 0065 0066 //**************************************** 0067 // QPainterDecorationRenderer 0068 //**************************************** 0069 SceneQPainterDecorationRenderer::SceneQPainterDecorationRenderer(Decoration::DecoratedClientImpl *client) 0070 : DecorationRenderer(client) 0071 { 0072 } 0073 0074 QImage SceneQPainterDecorationRenderer::image(SceneQPainterDecorationRenderer::DecorationPart part) const 0075 { 0076 Q_ASSERT(part != DecorationPart::Count); 0077 return m_images[int(part)]; 0078 } 0079 0080 void SceneQPainterDecorationRenderer::render(const QRegion ®ion) 0081 { 0082 if (areImageSizesDirty()) { 0083 resizeImages(); 0084 resetImageSizesDirty(); 0085 } 0086 0087 auto imageSize = [this](DecorationPart part) { 0088 return m_images[int(part)].size() / m_images[int(part)].devicePixelRatio(); 0089 }; 0090 0091 const QRect top(QPoint(0, 0), imageSize(DecorationPart::Top)); 0092 const QRect left(QPoint(0, top.height()), imageSize(DecorationPart::Left)); 0093 const QRect right(QPoint(top.width() - imageSize(DecorationPart::Right).width(), top.height()), imageSize(DecorationPart::Right)); 0094 const QRect bottom(QPoint(0, left.y() + left.height()), imageSize(DecorationPart::Bottom)); 0095 0096 const QRect geometry = region.boundingRect(); 0097 auto renderPart = [this](const QRect &rect, const QRect &partRect, int index) { 0098 if (rect.isEmpty()) { 0099 return; 0100 } 0101 QPainter painter(&m_images[index]); 0102 painter.setRenderHint(QPainter::Antialiasing); 0103 painter.setWindow(QRect(partRect.topLeft(), partRect.size() * effectiveDevicePixelRatio())); 0104 painter.setClipRect(rect); 0105 painter.save(); 0106 // clear existing part 0107 painter.setCompositionMode(QPainter::CompositionMode_Source); 0108 painter.fillRect(rect, Qt::transparent); 0109 painter.restore(); 0110 client()->decoration()->paint(&painter, rect); 0111 }; 0112 0113 renderPart(left.intersected(geometry), left, int(DecorationPart::Left)); 0114 renderPart(top.intersected(geometry), top, int(DecorationPart::Top)); 0115 renderPart(right.intersected(geometry), right, int(DecorationPart::Right)); 0116 renderPart(bottom.intersected(geometry), bottom, int(DecorationPart::Bottom)); 0117 } 0118 0119 void SceneQPainterDecorationRenderer::resizeImages() 0120 { 0121 QRectF left, top, right, bottom; 0122 client()->window()->layoutDecorationRects(left, top, right, bottom); 0123 0124 auto checkAndCreate = [this](int index, const QSizeF &size) { 0125 auto dpr = effectiveDevicePixelRatio(); 0126 if (m_images[index].size() != size * dpr || m_images[index].devicePixelRatio() != dpr) { 0127 m_images[index] = QImage(size.toSize() * dpr, QImage::Format_ARGB32_Premultiplied); 0128 m_images[index].setDevicePixelRatio(dpr); 0129 m_images[index].fill(Qt::transparent); 0130 } 0131 }; 0132 checkAndCreate(int(DecorationPart::Left), left.size()); 0133 checkAndCreate(int(DecorationPart::Right), right.size()); 0134 checkAndCreate(int(DecorationPart::Top), top.size()); 0135 checkAndCreate(int(DecorationPart::Bottom), bottom.size()); 0136 } 0137 0138 } // KWin