File indexing completed on 2024-12-08 13:22:02

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2011 Martin Gräßlin <mgraesslin@kde.org>
0006     SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 #pragma once
0011 
0012 #include <QObject>
0013 #include <kwineffects.h>
0014 
0015 namespace KDecoration2
0016 {
0017 class Decoration;
0018 class DecorationShadow;
0019 }
0020 
0021 namespace KWaylandServer
0022 {
0023 class ShadowInterface;
0024 }
0025 
0026 namespace KWin
0027 {
0028 
0029 class Window;
0030 
0031 /**
0032  * @short Class representing a Window's Shadow to be rendered by the Compositor.
0033  *
0034  * This class holds all information about the Shadow to be rendered together with the
0035  * window during the Compositing stage. The Shadow consists of several pixmaps and offsets.
0036  * For a complete description please refer to https://community.kde.org/KWin/Shadow
0037  *
0038  * To create a Shadow instance use the static factory method createShadow which will
0039  * create an instance for the currently used Compositing Backend. It will read the X11 Property
0040  * and create the Shadow and all required data (such as WindowQuads). If there is no Shadow
0041  * defined for the Window the factory method returns @c NULL.
0042  *
0043  * @author Martin Gräßlin <mgraesslin@kde.org>
0044  * @todo React on Window size changes.
0045  */
0046 class KWIN_EXPORT Shadow : public QObject
0047 {
0048     Q_OBJECT
0049 public:
0050     ~Shadow() override;
0051 
0052     /**
0053      * This method updates the Shadow when the property has been changed.
0054      * It is the responsibility of the owner of the Shadow to call this method
0055      * whenever the owner receives a PropertyNotify event.
0056      * This method will invoke a re-read of the Property. In case the Property has
0057      * been withdrawn the method returns @c false. In that case the owner should
0058      * delete the Shadow.
0059      * @returns @c true when the shadow has been updated, @c false if the property is not set anymore.
0060      */
0061     virtual bool updateShadow();
0062 
0063     /**
0064      * Factory Method to create the shadow from the property.
0065      * This method takes care of creating an instance of the
0066      * Shadow class for the current Compositing Backend.
0067      *
0068      * If there is no shadow defined for @p window this method
0069      * will return @c NULL.
0070      * @param window The Window for which the shadow should be created
0071      * @return Created Shadow or @c NULL in case there is no shadow defined.
0072      */
0073     static std::unique_ptr<Shadow> createShadow(Window *window);
0074 
0075     Window *window() const;
0076     /**
0077      * Reparents the shadow to @p window.
0078      * Used when a window is deleted.
0079      * @param window The new parent
0080      */
0081     void setWindow(Window *window);
0082 
0083     bool hasDecorationShadow() const
0084     {
0085         return m_decorationShadow != nullptr;
0086     }
0087     QImage decorationShadowImage() const;
0088 
0089     QWeakPointer<KDecoration2::DecorationShadow> decorationShadow() const
0090     {
0091         return m_decorationShadow.toWeakRef();
0092     }
0093 
0094     enum ShadowElements {
0095         ShadowElementTop,
0096         ShadowElementTopRight,
0097         ShadowElementRight,
0098         ShadowElementBottomRight,
0099         ShadowElementBottom,
0100         ShadowElementBottomLeft,
0101         ShadowElementLeft,
0102         ShadowElementTopLeft,
0103         ShadowElementsCount
0104     };
0105     QSize elementSize(ShadowElements element) const;
0106 
0107     QRectF rect() const
0108     {
0109         return QRectF(QPoint(0, 0), m_cachedSize);
0110     }
0111     QMargins offset() const
0112     {
0113         return m_offset;
0114     }
0115 
0116 Q_SIGNALS:
0117     void offsetChanged();
0118     void rectChanged();
0119     void textureChanged();
0120 
0121 public Q_SLOTS:
0122     void geometryChanged();
0123 
0124 protected:
0125     Shadow(Window *window);
0126 
0127     inline const QImage &shadowElement(ShadowElements element) const
0128     {
0129         return m_shadowElements[element];
0130     };
0131 
0132     virtual bool prepareBackend() = 0;
0133 
0134 private:
0135     static std::unique_ptr<Shadow> createShadowFromX11(Window *window);
0136     static std::unique_ptr<Shadow> createShadowFromDecoration(Window *window);
0137     static std::unique_ptr<Shadow> createShadowFromWayland(Window *window);
0138     static std::unique_ptr<Shadow> createShadowFromInternalWindow(Window *window);
0139     static QVector<uint32_t> readX11ShadowProperty(xcb_window_t id);
0140     bool init(const QVector<uint32_t> &data);
0141     bool init(KDecoration2::Decoration *decoration);
0142     bool init(const QPointer<KWaylandServer::ShadowInterface> &shadow);
0143     bool init(const QWindow *window);
0144     Window *m_window;
0145     // shadow elements
0146     QImage m_shadowElements[ShadowElementsCount];
0147     // shadow offsets
0148     QMargins m_offset;
0149     // caches
0150     QSizeF m_cachedSize;
0151     // Decoration based shadows
0152     QSharedPointer<KDecoration2::DecorationShadow> m_decorationShadow;
0153 };
0154 
0155 }