File indexing completed on 2024-05-19 05:32:22

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<DecorationRenderer> WorkspaceSceneQPainter::createDecorationRenderer(Decoration::DecoratedClientImpl *impl)
0040 {
0041     return std::make_unique<SceneQPainterDecorationRenderer>(impl);
0042 }
0043 
0044 std::unique_ptr<ShadowTextureProvider> WorkspaceSceneQPainter::createShadowTextureProvider(Shadow *shadow)
0045 {
0046     return std::make_unique<QPainterShadowTextureProvider>(shadow);
0047 }
0048 
0049 //****************************************
0050 // QPainterShadow
0051 //****************************************
0052 QPainterShadowTextureProvider::QPainterShadowTextureProvider(Shadow *shadow)
0053     : ShadowTextureProvider(shadow)
0054 {
0055 }
0056 
0057 void QPainterShadowTextureProvider::update()
0058 {
0059 }
0060 
0061 //****************************************
0062 // QPainterDecorationRenderer
0063 //****************************************
0064 SceneQPainterDecorationRenderer::SceneQPainterDecorationRenderer(Decoration::DecoratedClientImpl *client)
0065     : DecorationRenderer(client)
0066 {
0067 }
0068 
0069 QImage SceneQPainterDecorationRenderer::image(SceneQPainterDecorationRenderer::DecorationPart part) const
0070 {
0071     Q_ASSERT(part != DecorationPart::Count);
0072     return m_images[int(part)];
0073 }
0074 
0075 void SceneQPainterDecorationRenderer::render(const QRegion &region)
0076 {
0077     if (areImageSizesDirty()) {
0078         resizeImages();
0079         resetImageSizesDirty();
0080     }
0081 
0082     auto imageSize = [this](DecorationPart part) {
0083         return m_images[int(part)].size() / m_images[int(part)].devicePixelRatio();
0084     };
0085 
0086     const QRect top(QPoint(0, 0), imageSize(DecorationPart::Top));
0087     const QRect left(QPoint(0, top.height()), imageSize(DecorationPart::Left));
0088     const QRect right(QPoint(top.width() - imageSize(DecorationPart::Right).width(), top.height()), imageSize(DecorationPart::Right));
0089     const QRect bottom(QPoint(0, left.y() + left.height()), imageSize(DecorationPart::Bottom));
0090 
0091     const QRect geometry = region.boundingRect();
0092     auto renderPart = [this](const QRect &rect, const QRect &partRect, int index) {
0093         if (rect.isEmpty()) {
0094             return;
0095         }
0096         QPainter painter(&m_images[index]);
0097         painter.setRenderHint(QPainter::Antialiasing);
0098         painter.setWindow(QRect(partRect.topLeft(), partRect.size() * effectiveDevicePixelRatio()));
0099         painter.setClipRect(rect);
0100         painter.save();
0101         // clear existing part
0102         painter.setCompositionMode(QPainter::CompositionMode_Source);
0103         painter.fillRect(rect, Qt::transparent);
0104         painter.restore();
0105         client()->decoration()->paint(&painter, rect);
0106     };
0107 
0108     renderPart(left.intersected(geometry), left, int(DecorationPart::Left));
0109     renderPart(top.intersected(geometry), top, int(DecorationPart::Top));
0110     renderPart(right.intersected(geometry), right, int(DecorationPart::Right));
0111     renderPart(bottom.intersected(geometry), bottom, int(DecorationPart::Bottom));
0112 }
0113 
0114 void SceneQPainterDecorationRenderer::resizeImages()
0115 {
0116     QRectF left, top, right, bottom;
0117     client()->window()->layoutDecorationRects(left, top, right, bottom);
0118 
0119     auto checkAndCreate = [this](int index, const QSizeF &size) {
0120         auto dpr = effectiveDevicePixelRatio();
0121         if (m_images[index].size() != size * dpr || m_images[index].devicePixelRatio() != dpr) {
0122             m_images[index] = QImage(size.toSize() * dpr, QImage::Format_ARGB32_Premultiplied);
0123             m_images[index].setDevicePixelRatio(dpr);
0124             m_images[index].fill(Qt::transparent);
0125         }
0126     };
0127     checkAndCreate(int(DecorationPart::Left), left.size());
0128     checkAndCreate(int(DecorationPart::Right), right.size());
0129     checkAndCreate(int(DecorationPart::Top), top.size());
0130     checkAndCreate(int(DecorationPart::Bottom), bottom.size());
0131 }
0132 
0133 } // KWin
0134 
0135 #include "moc_workspacescene_qpainter.cpp"