kwin/src/shadow.h
David Edmundson 7292af3d04 Use floating geometry throughout
With fractional scaling integer based logical geometry may not match
device pixels. Once we have a floating point base we can fix that. This
also is
important for our X11 scale override, with a scale of 2 we could
get logical sizes with halves.

We already have all input being floating point, this doubles down on it
for all remaining geometry.

- Outputs remain integer to ensure that any screen on the right remains
aligned.
 - Placement also remains integer based for now.
- Repainting is untouched as we always expand outwards
 			   (QRectF::toAdjustedRect().
 - Decoration is untouched for now
 - Rules are integer in the config, but floating in the adjusting/API
This should also be fine.

At some point we'll add a method to snap to the device pixel
grid. Effectively `round(value * dpr)  / dpr` though right now things
mostly work.

This also gets rid of a lot of hacks for QRect right and bottom which
are very
confusing.

Parts to watch out in the port are:
 QRectF::contains now includes edges
QRectF::right and bottom are now sane so previous hacks have to be
removed
 QRectF(QPoint, QPoint) behaves differently for the same reason
 QRectF::center too

In test results some adjusted values which are the result of
QRect.center because using QRectF's center should behave the same to the
user.
2022-07-14 10:04:46 +01:00

160 lines
4.6 KiB
C++

/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2011 Martin Gräßlin <mgraesslin@kde.org>
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef KWIN_SHADOW_H
#define KWIN_SHADOW_H
#include <QObject>
#include <QPixmap>
#include <kwineffects.h>
namespace KDecoration2
{
class Decoration;
class DecorationShadow;
}
namespace KWaylandServer
{
class ShadowInterface;
}
namespace KWin
{
class Window;
/**
* @short Class representing a Window's Shadow to be rendered by the Compositor.
*
* This class holds all information about the Shadow to be rendered together with the
* window during the Compositing stage. The Shadow consists of several pixmaps and offsets.
* For a complete description please refer to https://community.kde.org/KWin/Shadow
*
* To create a Shadow instance use the static factory method createShadow which will
* create an instance for the currently used Compositing Backend. It will read the X11 Property
* and create the Shadow and all required data (such as WindowQuads). If there is no Shadow
* defined for the Window the factory method returns @c NULL.
*
* @author Martin Gräßlin <mgraesslin@kde.org>
* @todo React on Window size changes.
*/
class KWIN_EXPORT Shadow : public QObject
{
Q_OBJECT
public:
~Shadow() override;
/**
* This method updates the Shadow when the property has been changed.
* It is the responsibility of the owner of the Shadow to call this method
* whenever the owner receives a PropertyNotify event.
* This method will invoke a re-read of the Property. In case the Property has
* been withdrawn the method returns @c false. In that case the owner should
* delete the Shadow.
* @returns @c true when the shadow has been updated, @c false if the property is not set anymore.
*/
virtual bool updateShadow();
/**
* Factory Method to create the shadow from the property.
* This method takes care of creating an instance of the
* Shadow class for the current Compositing Backend.
*
* If there is no shadow defined for @p window this method
* will return @c NULL.
* @param window The Window for which the shadow should be created
* @return Created Shadow or @c NULL in case there is no shadow defined.
*/
static Shadow *createShadow(Window *window);
Window *window() const;
/**
* Reparents the shadow to @p window.
* Used when a window is deleted.
* @param window The new parent
*/
void setWindow(Window *window);
bool hasDecorationShadow() const
{
return m_decorationShadow != nullptr;
}
QImage decorationShadowImage() const;
QWeakPointer<KDecoration2::DecorationShadow> decorationShadow() const
{
return m_decorationShadow.toWeakRef();
}
enum ShadowElements {
ShadowElementTop,
ShadowElementTopRight,
ShadowElementRight,
ShadowElementBottomRight,
ShadowElementBottom,
ShadowElementBottomLeft,
ShadowElementLeft,
ShadowElementTopLeft,
ShadowElementsCount
};
QSize elementSize(ShadowElements element) const;
QRectF rect() const
{
return QRectF(QPoint(0, 0), m_cachedSize);
}
QMargins offset() const
{
return m_offset;
}
Q_SIGNALS:
void offsetChanged();
void rectChanged();
void textureChanged();
public Q_SLOTS:
void geometryChanged();
protected:
Shadow(Window *window);
inline const QPixmap &shadowPixmap(ShadowElements element) const
{
return m_shadowElements[element];
};
virtual bool prepareBackend() = 0;
void setShadowElement(const QPixmap &shadow, ShadowElements element);
private:
static Shadow *createShadowFromX11(Window *window);
static Shadow *createShadowFromDecoration(Window *window);
static Shadow *createShadowFromWayland(Window *window);
static Shadow *createShadowFromInternalWindow(Window *window);
static QVector<uint32_t> readX11ShadowProperty(xcb_window_t id);
bool init(const QVector<uint32_t> &data);
bool init(KDecoration2::Decoration *decoration);
bool init(const QPointer<KWaylandServer::ShadowInterface> &shadow);
bool init(const QWindow *window);
Window *m_window;
// shadow pixmaps
QPixmap m_shadowElements[ShadowElementsCount];
// shadow offsets
QMargins m_offset;
// caches
QSizeF m_cachedSize;
// Decoration based shadows
QSharedPointer<KDecoration2::DecorationShadow> m_decorationShadow;
};
}
#endif // KWIN_SHADOW_H