diff --git a/docs/changelog.md b/docs/changelog.md index 4be9f53..524e9c4 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,17 @@ # Changelog of the Burn-My-Windows Extension +## [Burn My Windows 19](https://github.com/schneegans/Burn-My-Windows/releases/tag/v19) + +**Release Date:** TBD + +#### New Features + +* On GNOME, the incinerate effect now uses the current mouse pointer position as starting position of the burn effect. The old random behaviour can be enabled in the settings. + +#### Enhancements + +* On GNOME, effects can now execute code whenever an animation ended. This is useful for cleaning up resources. + ## [Burn My Windows 18](https://github.com/schneegans/Burn-My-Windows/releases/tag/v18) **Release Date:** 2022-06-30 diff --git a/extension.js b/extension.js index 067ab2e..207a8ce 100644 --- a/extension.js +++ b/extension.js @@ -229,6 +229,7 @@ class Extension { const shader = actor.get_effect('burn-my-windows-effect'); if (shader) { actor.remove_effect(shader); + shader.endAnimation(); shader.returnToFactory(); } } @@ -385,6 +386,7 @@ class Extension { const oldShader = actor.get_effect('burn-my-windows-effect'); if (oldShader) { actor.remove_effect(oldShader); + oldShader.endAnimation(); oldShader.returnToFactory(); } @@ -520,6 +522,7 @@ class Extension { const oldShader = actor.get_effect('burn-my-windows-effect'); if (oldShader) { actor.remove_effect(oldShader); + oldShader.endAnimation(); oldShader.returnToFactory(); } }); diff --git a/kwin/incinerate/onAnimationBegin.js b/kwin/incinerate/onAnimationBegin.js index 12be257..18f72bc 100644 --- a/kwin/incinerate/onAnimationBegin.js +++ b/kwin/incinerate/onAnimationBegin.js @@ -1,4 +1,9 @@ // This part is automatically included in the effect's source during the build process. // The code below is called whenever a window is closed or opened. -effect.setUniform(this.shader, 'uSeed', [Math.random(), Math.random()]); +let seed = [Math.random(), Math.random()]; +let startPos = seed[0] > seed[1] ? [seed[0], Math.floor(seed[1] + 0.5)] : + [Math.floor(seed[0] + 0.5), seed[1]]; + +effect.setUniform(this.shader, 'uSeed', seed); +effect.setUniform(this.shader, 'uStartPos', startPos); \ No newline at end of file diff --git a/resources/shaders/incinerate.frag b/resources/shaders/incinerate.frag index c33da41..61558b9 100644 --- a/resources/shaders/incinerate.frag +++ b/resources/shaders/incinerate.frag @@ -17,6 +17,7 @@ uniform vec2 uSeed; uniform vec3 uColor; uniform float uScale; uniform float uTurbulence; +uniform vec2 uStartPos; // This maps a given value in [0..1] to a color from the rgba color ramp // [transparent black ... semi-transparent uColor ... opaque white]. @@ -75,11 +76,8 @@ void main() { // Now we compute a 2D gradient in [0..1] which covers the entire window. The dark // regions will be burned first, the bright regions in the end. We mix a radial gradient - // with some noise. The center of the radial gradient is positioned somewhere at the - // window boundary. - vec2 center = uSeed.x > uSeed.y ? vec2(uSeed.x, floor(uSeed.y + 0.5)) - : vec2(floor(uSeed.x + 0.5), uSeed.y); - float circle = length(iTexCoord - center); + // with some noise. The center of the radial gradient is positioned at uStartPos. + float circle = length(iTexCoord - uStartPos); vec2 uv = iTexCoord / uScale * uSize / 1.5; float smokeNoise = diff --git a/resources/ui/gtk3/Incinerate.ui b/resources/ui/gtk3/Incinerate.ui index 808eba4..816b0f9 100644 --- a/resources/ui/gtk3/Incinerate.ui +++ b/resources/ui/gtk3/Incinerate.ui @@ -181,6 +181,68 @@ + + + 10 + 10 + 10 + 10 + 0 + + + + + vertical + 3 + + + Start at Pointer + 0 + start + center + 1 + + + + + If disabled, a random location will be chosen. + 0 + start + center + 1 + + + + + + + + end + center + + + + + + + edit-clear-symbolic + 1 + + + Reset to Default Value + + + + + + + + 10 diff --git a/resources/ui/gtk4/Incinerate.ui b/resources/ui/gtk4/Incinerate.ui index 958cd5e..71e5521 100644 --- a/resources/ui/gtk4/Incinerate.ui +++ b/resources/ui/gtk4/Incinerate.ui @@ -152,6 +152,59 @@ + + + 0 + + + + + vertical + 3 + + + Start at Pointer + 0 + start + center + 1 + + + + + If disabled, a random location will be chosen. + 0 + start + center + 1 + + + + + + + + end + center + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + 0 diff --git a/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml b/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml index 50f69e0..ee26406 100644 --- a/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml +++ b/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml @@ -371,6 +371,12 @@ The color of the effect. + + true + Incinerate Use Pointer + Use the pointer location for the incinerate effect. + + diff --git a/src/Incinerate.js b/src/Incinerate.js index dd3e777..0277929 100644 --- a/src/Incinerate.js +++ b/src/Incinerate.js @@ -47,22 +47,65 @@ var Incinerate = class { shader._uColor = shader.get_uniform_location('uColor'); shader._uScale = shader.get_uniform_location('uScale'); shader._uTurbulence = shader.get_uniform_location('uTurbulence'); + shader._uStartPos = shader.get_uniform_location('uStartPos'); // Write all uniform values at the start of each animation. - shader.connect('begin-animation', (shader, settings) => { - const c = Clutter.Color.from_string(settings.get_string('incinerate-color'))[1]; - + shader.connect('begin-animation', (shader, settings, forOpening, actor) => { // If we are currently performing integration test, the animation uses a fixed // seed. const testMode = settings.get_boolean('test-mode'); + let seed = [testMode ? 0 : Math.random(), testMode ? 0 : Math.random()]; + + // If this option is set, we use the mouse pointer position. Because the actor + // position may change after the begin-animation signal is called, we set the + // uStartPos uniform during the update callback. + if (settings.get_boolean('incinerate-use-pointer')) { + this._startPointerPos = global.get_pointer(); + this._actor = actor; + + } else { + // Else, a random position along the window boundary is used as start position + // for the incinerate effect. + let startPos = seed[0] > seed[1] ? [seed[0], Math.floor(seed[1] + 0.5)] : + [Math.floor(seed[0] + 0.5), seed[1]]; + + shader.set_uniform_float(shader._uStartPos, 2, startPos); + + this._startPointerPos = null; + } + + const c = Clutter.Color.from_string(settings.get_string('incinerate-color'))[1]; // clang-format off - shader.set_uniform_float(shader._uSeed, 2, [testMode ? 0 : Math.random(), testMode ? 0 : Math.random()]); - shader.set_uniform_float(shader._uColor, 3, [c.red / 255, c.green / 255, c.blue / 255]); - shader.set_uniform_float(shader._uScale, 1, [settings.get_double('incinerate-scale')]); + shader.set_uniform_float(shader._uSeed, 2, seed); + shader.set_uniform_float(shader._uColor, 3, [c.red / 255, c.green / 255, c.blue / 255]); + shader.set_uniform_float(shader._uScale, 1, [settings.get_double('incinerate-scale')]); shader.set_uniform_float(shader._uTurbulence, 1, [settings.get_double('incinerate-turbulence')]); // clang-format on }); + + // If the mouse pointer position is used as start position, we set the uStartPos + // uniform during the update callback as the actor position may not be set up + // properly before the begin animation callback. + shader.connect('update-animation', (shader) => { + if (this._startPointerPos) { + const [x, y] = this._startPointerPos; + const [ok, localX, localY] = this._actor.transform_stage_point(x, y); + + if (ok) { + let startPos = [ + Math.max(0.0, Math.min(1.0, localX / this._actor.width)), + Math.max(0.0, Math.min(1.0, localY / this._actor.height)) + ]; + shader.set_uniform_float(shader._uStartPos, 2, startPos); + } + } + }); + + // Make sure to drop the reference to the actor. + shader.connect('end-animation', (shader) => { + shader._actor = null; + }); }); } @@ -100,6 +143,7 @@ var Incinerate = class { dialog.bindAdjustment('incinerate-animation-time'); dialog.bindAdjustment('incinerate-scale'); dialog.bindAdjustment('incinerate-turbulence'); + dialog.bindSwitch('incinerate-use-pointer'); dialog.bindColorButton('incinerate-color'); // Finally, return the new settings page. diff --git a/src/Shader.js b/src/Shader.js index 2ae1ad0..630cb25 100644 --- a/src/Shader.js +++ b/src/Shader.js @@ -48,7 +48,8 @@ var Shader = GObject.registerClass( Signals: { 'begin-animation': {param_types: [Gio.Settings.$gtype, GObject.TYPE_BOOLEAN, Clutter.Actor.$gtype]}, - 'update-animation': {param_types: [GObject.TYPE_DOUBLE]} + 'update-animation': {param_types: [GObject.TYPE_DOUBLE]}, + 'end-animation': {} } }, class Shader extends Shell.GLSLEffect { // -------------------------------------------- @@ -99,6 +100,12 @@ var Shader = GObject.registerClass( this._progress = progress; } + // This will just emit the end-animation signal. It can be used to clean up any + // resources required during the animation. + endAnimation() { + this.emit('end-animation'); + } + // This is called by the constructor. This means, it's only called when the // effect is used for the first time. vfunc_build_pipeline() { diff --git a/tests/references/incinerate-close-gnome-wayland-nested-32.png b/tests/references/incinerate-close-gnome-wayland-nested-32.png index e509e00..a64987e 100644 Binary files a/tests/references/incinerate-close-gnome-wayland-nested-32.png and b/tests/references/incinerate-close-gnome-wayland-nested-32.png differ diff --git a/tests/references/incinerate-close-gnome-wayland-nested-33.png b/tests/references/incinerate-close-gnome-wayland-nested-33.png index 5073673..bd400af 100644 Binary files a/tests/references/incinerate-close-gnome-wayland-nested-33.png and b/tests/references/incinerate-close-gnome-wayland-nested-33.png differ diff --git a/tests/references/incinerate-close-gnome-wayland-nested-34.png b/tests/references/incinerate-close-gnome-wayland-nested-34.png index 902ffcb..03f2b53 100644 Binary files a/tests/references/incinerate-close-gnome-wayland-nested-34.png and b/tests/references/incinerate-close-gnome-wayland-nested-34.png differ diff --git a/tests/references/incinerate-close-gnome-wayland-nested-35.png b/tests/references/incinerate-close-gnome-wayland-nested-35.png index 902ffcb..03f2b53 100644 Binary files a/tests/references/incinerate-close-gnome-wayland-nested-35.png and b/tests/references/incinerate-close-gnome-wayland-nested-35.png differ diff --git a/tests/references/incinerate-close-gnome-wayland-nested-36.png b/tests/references/incinerate-close-gnome-wayland-nested-36.png index 9684afe..a027162 100644 Binary files a/tests/references/incinerate-close-gnome-wayland-nested-36.png and b/tests/references/incinerate-close-gnome-wayland-nested-36.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-32.png b/tests/references/incinerate-close-gnome-xsession-32.png index e509e00..a64987e 100644 Binary files a/tests/references/incinerate-close-gnome-xsession-32.png and b/tests/references/incinerate-close-gnome-xsession-32.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-33.png b/tests/references/incinerate-close-gnome-xsession-33.png index 5073673..bd400af 100644 Binary files a/tests/references/incinerate-close-gnome-xsession-33.png and b/tests/references/incinerate-close-gnome-xsession-33.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-34.png b/tests/references/incinerate-close-gnome-xsession-34.png index 22febf8..c214b01 100644 Binary files a/tests/references/incinerate-close-gnome-xsession-34.png and b/tests/references/incinerate-close-gnome-xsession-34.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-35.png b/tests/references/incinerate-close-gnome-xsession-35.png index 22febf8..c214b01 100644 Binary files a/tests/references/incinerate-close-gnome-xsession-35.png and b/tests/references/incinerate-close-gnome-xsession-35.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-36.png b/tests/references/incinerate-close-gnome-xsession-36.png index bf4760d..a95fb9c 100644 Binary files a/tests/references/incinerate-close-gnome-xsession-36.png and b/tests/references/incinerate-close-gnome-xsession-36.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-32.png b/tests/references/incinerate-open-gnome-wayland-nested-32.png index 04aa1f7..93cda9e 100644 Binary files a/tests/references/incinerate-open-gnome-wayland-nested-32.png and b/tests/references/incinerate-open-gnome-wayland-nested-32.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-33.png b/tests/references/incinerate-open-gnome-wayland-nested-33.png index 4faa883..f94b8a4 100644 Binary files a/tests/references/incinerate-open-gnome-wayland-nested-33.png and b/tests/references/incinerate-open-gnome-wayland-nested-33.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-34.png b/tests/references/incinerate-open-gnome-wayland-nested-34.png index 306d54a..87f5233 100644 Binary files a/tests/references/incinerate-open-gnome-wayland-nested-34.png and b/tests/references/incinerate-open-gnome-wayland-nested-34.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-35.png b/tests/references/incinerate-open-gnome-wayland-nested-35.png index 306d54a..87f5233 100644 Binary files a/tests/references/incinerate-open-gnome-wayland-nested-35.png and b/tests/references/incinerate-open-gnome-wayland-nested-35.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-36.png b/tests/references/incinerate-open-gnome-wayland-nested-36.png index d5ef62d..ce1d46c 100644 Binary files a/tests/references/incinerate-open-gnome-wayland-nested-36.png and b/tests/references/incinerate-open-gnome-wayland-nested-36.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-32.png b/tests/references/incinerate-open-gnome-xsession-32.png index 04aa1f7..2da2df2 100644 Binary files a/tests/references/incinerate-open-gnome-xsession-32.png and b/tests/references/incinerate-open-gnome-xsession-32.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-33.png b/tests/references/incinerate-open-gnome-xsession-33.png index 4faa883..3cd2fad 100644 Binary files a/tests/references/incinerate-open-gnome-xsession-33.png and b/tests/references/incinerate-open-gnome-xsession-33.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-34.png b/tests/references/incinerate-open-gnome-xsession-34.png index 0e7557b..7a20201 100644 Binary files a/tests/references/incinerate-open-gnome-xsession-34.png and b/tests/references/incinerate-open-gnome-xsession-34.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-35.png b/tests/references/incinerate-open-gnome-xsession-35.png index 0e7557b..7a20201 100644 Binary files a/tests/references/incinerate-open-gnome-xsession-35.png and b/tests/references/incinerate-open-gnome-xsession-35.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-36.png b/tests/references/incinerate-open-gnome-xsession-36.png index 410b154..9bd9e09 100644 Binary files a/tests/references/incinerate-open-gnome-xsession-36.png and b/tests/references/incinerate-open-gnome-xsession-36.png differ