support kdecoration2 blurregion

--use kdecoration2 blurred regions to adjust blur effect appropriately when
needed

CCBUG:395725

Requires: https://invent.kde.org/plasma/kdecoration/-/merge_requests/17
This commit is contained in:
Michail Vourlakos 2022-02-09 21:00:07 +00:00
parent c0d0fab049
commit bc145b614c
7 changed files with 73 additions and 2 deletions

View file

@ -189,6 +189,9 @@ public:
bool decorationHasAlpha() const override {
return false;
}
KDecoration2::Decoration *decoration() const override {
return nullptr;
}
QString caption() const override {
return QString();
}

View file

@ -52,6 +52,7 @@
#include "wayland_server.h"
#include "decorations/decorationbridge.h"
#include <KDecoration2/Decoration>
#include <KDecoration2/DecorationSettings>
namespace KWin
@ -355,6 +356,10 @@ void EffectsHandlerImpl::setupClientConnections(AbstractClient* c)
connect(c, &AbstractClient::visibleGeometryChanged, this, [this, c]() {
Q_EMIT windowExpandedGeometryChanged(c->effectWindow());
});
connect(c, &AbstractClient::decorationChanged, this, [this, c]() {
Q_EMIT windowDecorationChanged(c->effectWindow());
});
}
void EffectsHandlerImpl::setupUnmanagedConnections(Unmanaged* u)
@ -2078,6 +2083,16 @@ QRect EffectWindowImpl::decorationInnerRect() const
return toplevel->rect() - toplevel->frameMargins();
}
KDecoration2::Decoration *EffectWindowImpl::decoration() const
{
auto client = qobject_cast<AbstractClient *>(toplevel);
if (!client) {
return nullptr;
}
return client->decoration();
}
QByteArray EffectWindowImpl::readProperty(long atom, long type, int format) const
{
if (!kwinApp()->x11Connection()) {

View file

@ -490,6 +490,7 @@ public:
qlonglong windowId() const override;
QRect decorationInnerRect() const override;
KDecoration2::Decoration *decoration() const override;
QByteArray readProperty(long atom, long type, int format) const override;
void deleteProperty(long atom) const override;

View file

@ -55,6 +55,7 @@ set(kwin_effect_KDE_LIBS
KF5::Plasma # screenedge effect
KF5::WindowSystem
KF5::Service # utils / screenshot effect
KDecoration2::KDecoration # blur effect
Plasma::KWaylandServer
)

View file

@ -25,6 +25,8 @@
#include <KSharedConfig>
#include <KConfigGroup>
#include <KDecoration2/Decoration>
namespace KWin
{
@ -65,6 +67,7 @@ BlurEffect::BlurEffect()
connect(effects, &EffectsHandler::windowAdded, this, &BlurEffect::slotWindowAdded);
connect(effects, &EffectsHandler::windowDeleted, this, &BlurEffect::slotWindowDeleted);
connect(effects, &EffectsHandler::windowDecorationChanged, this, &BlurEffect::setupDecorationConnections);
connect(effects, &EffectsHandler::propertyNotify, this, &BlurEffect::slotPropertyNotify);
connect(effects, &EffectsHandler::virtualScreenGeometryChanged, this, &BlurEffect::slotScreenGeometryChanged);
connect(effects, &EffectsHandler::xcbConnectionChanged, this,
@ -334,6 +337,7 @@ void BlurEffect::slotWindowAdded(EffectWindow *w)
internal->installEventFilter(this);
}
setupDecorationConnections(w);
updateBlurRegion(w);
}
@ -354,6 +358,17 @@ void BlurEffect::slotPropertyNotify(EffectWindow *w, long atom)
}
}
void BlurEffect::setupDecorationConnections(EffectWindow *w)
{
if (!w->decoration()) {
return;
}
connect(w->decoration(), &KDecoration2::Decoration::blurRegionChanged, this, [this, w] () {
updateBlurRegion(w);
});
}
bool BlurEffect::eventFilter(QObject *watched, QEvent *event)
{
auto internal = qobject_cast<QWindow*>(watched);
@ -399,6 +414,23 @@ bool BlurEffect::supported()
return supported;
}
QRegion BlurEffect::decorationBlurRegion(const EffectWindow *w) const
{
if (!w || !effects->decorationSupportsBlurBehind() || !w->decoration()) {
return QRegion();
}
QRegion decorationRegion = QRegion(w->decoration()->rect()) - w->decorationInnerRect();
if (!w->decoration()->blurRegion().isNull()) {
//! we return only blurred regions that belong to decoration region
return decorationRegion.intersected(w->decoration()->blurRegion());
}
//! when decoration requests blur but does not provide any blur region we can assume it prefers entire decoration region
return decorationRegion;
}
QRect BlurEffect::expand(const QRect &rect) const
{
return rect.adjusted(-m_expandSize, -m_expandSize, m_expandSize, m_expandSize);
@ -424,7 +456,7 @@ QRegion BlurEffect::blurRegion(const EffectWindow *w) const
const QRegion appRegion = qvariant_cast<QRegion>(value);
if (!appRegion.isEmpty()) {
if (w->decorationHasAlpha() && effects->decorationSupportsBlurBehind()) {
region = QRegion(w->rect()) - w->decorationInnerRect();
region = decorationBlurRegion(w);
}
region |= appRegion.translated(w->contentsRect().topLeft()) &
w->decorationInnerRect();
@ -436,7 +468,7 @@ QRegion BlurEffect::blurRegion(const EffectWindow *w) const
} else if (w->decorationHasAlpha() && effects->decorationSupportsBlurBehind()) {
// If the client hasn't specified a blur region, we'll only enable
// the effect behind the decoration.
region = QRegion(w->rect()) - w->decorationInnerRect();
region = decorationBlurRegion(w);
}
return region;

View file

@ -58,6 +58,7 @@ public Q_SLOTS:
void slotWindowDeleted(KWin::EffectWindow *w);
void slotPropertyNotify(KWin::EffectWindow *w, long atom);
void slotScreenGeometryChanged();
void setupDecorationConnections(EffectWindow *w);
private:
QRect expand(const QRect &rect) const;
@ -67,6 +68,7 @@ private:
void initBlurStrengthValues();
void updateTexture();
QRegion blurRegion(const EffectWindow *w) const;
QRegion decorationBlurRegion(const EffectWindow *w) const;
bool shouldBlur(const EffectWindow *w, int mask, const WindowPaintData &data) const;
void updateBlurRegion(EffectWindow *w) const;
void doBlur(const QRegion &shape, const QRect &screen, const float opacity, const QMatrix4x4 &screenProjection, bool isDock, QRect windowRect);

View file

@ -54,6 +54,10 @@ class QTabletEvent;
*/
Q_DECLARE_LOGGING_CATEGORY(KWINEFFECTS)
namespace KDecoration2 {
class Decoration;
}
namespace KWaylandServer {
class SurfaceInterface;
class Display;
@ -1865,6 +1869,14 @@ Q_SIGNALS:
*/
void sessionStateChanged();
/**
* This signal is emitted when decoration of @p was changed.
*
* @param w The window for which decoration changed
* @since 5.25
*/
void windowDecorationChanged(KWin::EffectWindow *window);
/**
* This signal is emitted when the visible geometry of a window changed.
*/
@ -2377,6 +2389,11 @@ public:
virtual QRect decorationInnerRect() const = 0;
bool hasDecoration() const;
virtual bool decorationHasAlpha() const = 0;
/**
* Returns the decoration
* @since 5.25
*/
virtual KDecoration2::Decoration *decoration() const = 0;
virtual QByteArray readProperty(long atom, long type, int format) const = 0;
virtual void deleteProperty(long atom) const = 0;