From bc145b614c9f1c7594b01d88a2dfbebead50d489 Mon Sep 17 00:00:00 2001 From: Michail Vourlakos Date: Wed, 9 Feb 2022 21:00:07 +0000 Subject: [PATCH] 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 --- autotests/test_window_paint_data.cpp | 3 +++ src/effects.cpp | 15 ++++++++++++ src/effects.h | 1 + src/effects/CMakeLists.txt | 1 + src/effects/blur/blur.cpp | 36 ++++++++++++++++++++++++++-- src/effects/blur/blur.h | 2 ++ src/libkwineffects/kwineffects.h | 17 +++++++++++++ 7 files changed, 73 insertions(+), 2 deletions(-) diff --git a/autotests/test_window_paint_data.cpp b/autotests/test_window_paint_data.cpp index 22af4bd867..73f98087ba 100644 --- a/autotests/test_window_paint_data.cpp +++ b/autotests/test_window_paint_data.cpp @@ -189,6 +189,9 @@ public: bool decorationHasAlpha() const override { return false; } + KDecoration2::Decoration *decoration() const override { + return nullptr; + } QString caption() const override { return QString(); } diff --git a/src/effects.cpp b/src/effects.cpp index 1be036079f..32e5321ca4 100644 --- a/src/effects.cpp +++ b/src/effects.cpp @@ -52,6 +52,7 @@ #include "wayland_server.h" #include "decorations/decorationbridge.h" +#include #include 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(toplevel); + if (!client) { + return nullptr; + } + + return client->decoration(); +} + QByteArray EffectWindowImpl::readProperty(long atom, long type, int format) const { if (!kwinApp()->x11Connection()) { diff --git a/src/effects.h b/src/effects.h index bb18a6e545..08fb215e76 100644 --- a/src/effects.h +++ b/src/effects.h @@ -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; diff --git a/src/effects/CMakeLists.txt b/src/effects/CMakeLists.txt index 4c6e413058..9b8aad8da9 100644 --- a/src/effects/CMakeLists.txt +++ b/src/effects/CMakeLists.txt @@ -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 ) diff --git a/src/effects/blur/blur.cpp b/src/effects/blur/blur.cpp index a9158d5a7f..e2fc6194bb 100644 --- a/src/effects/blur/blur.cpp +++ b/src/effects/blur/blur.cpp @@ -25,6 +25,8 @@ #include #include +#include + 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(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(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; diff --git a/src/effects/blur/blur.h b/src/effects/blur/blur.h index b242f9a8c1..1b81c99535 100644 --- a/src/effects/blur/blur.h +++ b/src/effects/blur/blur.h @@ -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); diff --git a/src/libkwineffects/kwineffects.h b/src/libkwineffects/kwineffects.h index 8076a07088..bcfd01829d 100644 --- a/src/libkwineffects/kwineffects.h +++ b/src/libkwineffects/kwineffects.h @@ -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;