Skip to content

Commit

Permalink
Merge pull request #81 from taj-ny/develop
Browse files Browse the repository at this point in the history
v1.3.0
  • Loading branch information
taj-ny committed Jun 17, 2024
2 parents b1a27bf + af0693d commit b9dd76a
Show file tree
Hide file tree
Showing 14 changed files with 675 additions and 139 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16.0)

project(forceblur)
set(PROJECT_VERSION "1.2.1")
set(PROJECT_VERSION "1.3.0")
set(PROJECT_VERSION_MAJOR 0)

set(KF_MIN_VERSION "5.240.0")
Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
# kwin-effects-forceblur [![AUR Version](https://img.shields.io/aur/version/kwin-effects-forceblur)](https://aur.archlinux.org/packages/kwin-effects-forceblur)
A fork of the KWin Blur effect for KDE Plasma 6 with the ability to blur any window on Wayland and X11.
Kwin-effects-forceblur (name subject to change) is a fork of the KWin Blur effect for KDE Plasma 6 with several improvements and bug fixes.

Latest features are available on the ``develop`` branch.

![image](https://github.com/taj-ny/kwin-effects-forceblur/assets/79316397/9d2f337e-badd-4d95-ba55-96c80202e196)
<sup>Window opacity has been set to 85% for System Settings and Dolphin, Firefox uses a transparent theme | [NixOS configuration](https://github.com/taj-ny/nix-config)</sup>
![image](https://github.com/taj-ny/kwin-effects-forceblur/assets/79316397/1078cf12-e6da-43c7-80b4-d90a8b0f3404)
<sup>Window opacity has been set to 85% for System Settings, Dolphin and VSCodium, Firefox uses a transparent theme | [NixOS configuration](https://github.com/taj-ny/nix-config)</sup>

# Features
- Wayland support
- Force blur
- Rounded corners with optional anti-aliasing
- Draw image behind windows instead of blurring (can be used with a blurred image of the wallpaper in order to achieve a very similar effect to blur but with **much** lower GPU usage)
- Rounded corners
- Fix for [artifacts](https://github.com/taj-ny/kwin-effects-forceblur/pull/38) when using a transparent color scheme

### Bug fixes
Fixes for blur-related Plasma bugs that haven't been patched yet.

- Blur may sometimes disappear during animations
- [Transparent color schemes don't work properly with the Breeze application style](https://github.com/taj-ny/kwin-effects-forceblur/pull/38)

# Installation
<details>
Expand Down
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

stdenv.mkDerivation rec {
pname = "kwin-effects-forceblur";
version = "1.2.1";
version = "1.3.0";

src = ./.;

Expand Down
505 changes: 394 additions & 111 deletions src/blur.cpp

Large diffs are not rendered by default.

64 changes: 52 additions & 12 deletions src/blur.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,27 @@ public Q_SLOTS:

private:
void initBlurStrengthValues();
QRegion blurRegion(EffectWindow *w, bool noRoundedCorners = false) const;
QRegion blurRegion(EffectWindow *w) const;
QRegion decorationBlurRegion(const EffectWindow *w) const;
QRegion transformedBlurRegion(QRegion blurRegion, const WindowPaintData &data) const;
bool decorationSupportsBlurBehind(const EffectWindow *w) const;
bool shouldBlur(const EffectWindow *w, int mask, const WindowPaintData &data) const;
bool shouldBlur(const EffectWindow *w, int mask, const WindowPaintData &data);
bool shouldForceBlur(const EffectWindow *w) const;
void updateBlurRegion(EffectWindow *w);
void updateCornerRegions();
void blur(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion &region, WindowPaintData &data);
GLTexture *ensureNoiseTexture();
bool hasFakeBlur(EffectWindow *w) const;

/*
* @returns An array containing rounded corner masks for the given screen scale and radii. If no masks exist, they
* will be generated.
*/
std::array<QRegion, 4> roundedCorners(int topCornerRadius, int bottomCornerRadius, qreal scale);

/*
* Generates rounded corner masks for the left and right corner of the given radius.
* @param top Whether the corners belong to the top part of the window.
*/
void generateRoundedCornerMasks(int radius, QRegion &left, QRegion &right, bool top) const;

private:
struct
Expand Down Expand Up @@ -123,10 +134,33 @@ public Q_SLOTS:
int mvpMatrixLocation;
int textureSizeLocation;
int texStartPosLocation;
int regionSizeLocation;

std::unique_ptr<GLTexture> texture;
} m_texturePass;

struct
{
std::unique_ptr<GLShader> shader;

int roundTopLeftCornerLocation;
int roundTopRightCornerLocation;
int roundBottomLeftCornerLocation;
int roundBottomRightCornerLocation;

int topCornerRadiusLocation;
int bottomCornerRadiusLocation;

int antialiasingLocation;

int regionSizeLocation;

int beforeBlurTextureLocation;
int afterBlurTextureLocation;

int mvpMatrixLocation;
} m_roundedCorners;

bool m_valid = false;
long net_wm_blur_region = 0;
QRegion m_paintedArea; // keeps track of all painted areas (from bottom to top)
Expand All @@ -142,9 +176,6 @@ public Q_SLOTS:
bool m_blurNonMatching;
bool m_blurDecorations;
bool m_transparentBlur;
int m_topCornerRadius;
int m_bottomCornerRadius;
bool m_roundCornersOfMaximizedWindows;
bool m_blurMenus;
bool m_blurDocks;
bool m_paintAsTranslucent;
Expand All @@ -153,11 +184,17 @@ public Q_SLOTS:

bool m_hasValidFakeBlurTexture;

// Regions to subtract from the blurred region
QRegion m_topLeftCorner;
QRegion m_topRightCorner;
QRegion m_bottomLeftCorner;
QRegion m_bottomRightCorner;
int m_windowTopCornerRadius;
int m_windowBottomCornerRadius;
int m_menuCornerRadius;
int m_dockCornerRadius;
float m_roundedCornersAntialiasing;
bool m_roundCornersOfMaximizedWindows;
int m_cornerRadiusOffset;

// Corner masks where the key is the screen scale and the value is an array of the masks
// (top left, top right, bottom left, bottom right). Used for rounding the blur region.
std::map<const std::tuple<int, int, qreal>, std::array<QRegion, 4>> m_corners;

struct OffsetStruct
{
Expand All @@ -176,6 +213,9 @@ public Q_SLOTS:

QList<BlurValuesStruct> blurStrengthValues;

// Windows to blur even when transformed.
QList<const EffectWindow*> m_blurWhenTransformed;

QMap<EffectWindow *, QMetaObject::Connection> windowBlurChangedConnections;
QMap<EffectWindow *, QMetaObject::Connection> windowExpandedGeometryChangedConnections;
std::unordered_map<EffectWindow *, BlurEffectData> m_windows;
Expand Down
9 changes: 9 additions & 0 deletions src/blur.kcfg
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ class3</default>
<entry name="BottomCornerRadius" type="Int">
<default>0</default>
</entry>
<entry name="MenuCornerRadius" type="Int">
<default>0</default>
</entry>
<entry name="DockCornerRadius" type="Int">
<default>0</default>
</entry>
<entry name="RoundedCornersAntialiasing" type="Double">
<default>1.0</default>
</entry>
<entry name="RoundCornersOfMaximizedWindows" type="Bool">
<default>false</default>
</entry>
Expand Down
2 changes: 2 additions & 0 deletions src/blur.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<file>shaders/downsample_core.frag</file>
<file>shaders/noise.frag</file>
<file>shaders/noise_core.frag</file>
<file>shaders/roundedcorners.frag</file>
<file>shaders/roundedcorners_core.frag</file>
<file>shaders/texture.frag</file>
<file>shaders/texture_core.frag</file>
<file>shaders/upsample.frag</file>
Expand Down
58 changes: 56 additions & 2 deletions src/kcm/blur_config.ui
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@
<item>
<widget class="QLabel">
<property name="text">
<string>Top corner radius</string>
<string>Window top corner radius</string>
</property>
</widget>
</item>
Expand All @@ -339,7 +339,7 @@
<item>
<widget class="QLabel">
<property name="text">
<string>Bottom corner radius</string>
<string>Window bottom corner radius</string>
</property>
</widget>
</item>
Expand All @@ -352,6 +352,60 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel">
<property name="text">
<string>Menu corner radius</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="kcfg_MenuCornerRadius">
<property name="minimum">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel">
<property name="text">
<string>Dock corner radius</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="kcfg_DockCornerRadius">
<property name="minimum">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel">
<property name="text">
<string>Anti-aliasing</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="kcfg_RoundedCornersAntialiasing">
<property name="minimum">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="kcfg_RoundCornersOfMaximizedWindows">
<property name="text">
Expand Down
53 changes: 53 additions & 0 deletions src/shaders/roundedcorners.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Modified version of https://www.shadertoy.com/view/ldfSDj

uniform bool roundTopLeftCorner;
uniform bool roundTopRightCorner;
uniform bool roundBottomLeftCorner;
uniform bool roundBottomRightCorner;

uniform int topCornerRadius;
uniform int bottomCornerRadius;

uniform float antialiasing;

uniform vec2 regionSize;

uniform sampler2D beforeBlurTexture;
uniform sampler2D afterBlurTexture;

varying vec2 uv;

float udRoundBox(vec2 p, vec2 b, vec2 fragCoord)
{
float radius = 0.0;
if ((fragCoord.y <= topCornerRadius)
&& ((roundTopLeftCorner && fragCoord.x <= topCornerRadius)
|| (roundTopRightCorner && fragCoord.x >= regionSize.x - topCornerRadius))) {
radius = topCornerRadius;
p.y -= radius;
} else if ((fragCoord.y >= regionSize.y - bottomCornerRadius)
&& ((roundBottomLeftCorner && fragCoord.x <= bottomCornerRadius)
|| (roundBottomRightCorner && fragCoord.x >= regionSize.x - bottomCornerRadius))) {
radius = bottomCornerRadius;
p.y += radius;
}

return length(max(abs(p) - (b + vec2(0.0, radius)) + radius, 0.0)) - radius;
}

void main(void)
{
vec2 halfRegionSize = regionSize * 0.5;
vec2 fragCoord = uv * regionSize;
float box = udRoundBox(fragCoord - halfRegionSize, halfRegionSize, fragCoord);

// If antialiasing is 0, the shader will be used to generate corner masks.
vec3 foreground = vec3(1.0, 1.0, 1.0);
vec3 background = vec3(0.0, 0.0, 0.0);
if (antialiasing > 0.0) {
foreground = texture2D(afterBlurTexture, uv).rgb;
background = texture2D(beforeBlurTexture, uv).rgb;
}

gl_FragColor = vec4(mix(foreground, background, smoothstep(0.0, antialiasing, box)), 1.0);
}
57 changes: 57 additions & 0 deletions src/shaders/roundedcorners_core.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#version 140

// Modified version of https://www.shadertoy.com/view/ldfSDj

uniform bool roundTopLeftCorner;
uniform bool roundTopRightCorner;
uniform bool roundBottomLeftCorner;
uniform bool roundBottomRightCorner;

uniform int topCornerRadius;
uniform int bottomCornerRadius;

uniform float antialiasing;

uniform vec2 regionSize;

uniform sampler2D beforeBlurTexture;
uniform sampler2D afterBlurTexture;

in vec2 uv;

out vec4 fragColor;

float udRoundBox(vec2 p, vec2 b, vec2 fragCoord)
{
float radius = 0.0;
if ((fragCoord.y <= topCornerRadius)
&& ((roundTopLeftCorner && fragCoord.x <= topCornerRadius)
|| (roundTopRightCorner && fragCoord.x >= regionSize.x - topCornerRadius))) {
radius = topCornerRadius;
p.y -= radius;
} else if ((fragCoord.y >= regionSize.y - bottomCornerRadius)
&& ((roundBottomLeftCorner && fragCoord.x <= bottomCornerRadius)
|| (roundBottomRightCorner && fragCoord.x >= regionSize.x - bottomCornerRadius))) {
radius = bottomCornerRadius;
p.y += radius;
}

return length(max(abs(p) - (b + vec2(0.0, radius)) + radius, 0.0)) - radius;
}

void main(void)
{
vec2 halfRegionSize = regionSize * 0.5;
vec2 fragCoord = uv * regionSize;
float box = udRoundBox(fragCoord - halfRegionSize, halfRegionSize, fragCoord);

// If antialiasing is 0, the shader will be used to generate corner masks.
vec3 foreground = vec3(1.0, 1.0, 1.0);
vec3 background = vec3(0.0, 0.0, 0.0);
if (antialiasing > 0.0) {
foreground = texture(afterBlurTexture, uv).rgb;
background = texture(beforeBlurTexture, uv).rgb;
}

fragColor = vec4(mix(foreground, background, smoothstep(0.0, antialiasing, box)), 1.0);
}
Loading

0 comments on commit b9dd76a

Please sign in to comment.