diff --git a/README.md b/README.md
index b66f2e0..25ea8e7 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,8 @@ This extension is not only more useless than the cube, but it is also much more
| **Doom** Melt your windows. Inspired by the legendary screen transitions of the original Doom. | |
| **Energize A** Beam your windows away! | |
| **Energize B** Using different transporter technology results in an alternative visual effect. | |
-| **Fire** The classic effect inspired by Compiz. However, this is implemented using a GLSL shader and not with a particle system like in the old days. | |
+| **Fire** The classic effect inspired by Compiz. However, this is implemented using a GLSL shader and not with a particle system like in the old days. | |
+| **Focus** Focus Dude, Focus | |
| **Glide** This very simple effect fades the window to transparency with subtle 3D effects. | |
| **Glitch** This effect applies some intentional graphics issues to your windows. | |
| **Hexagon** With glowing lines and hexagon-shaped tiles, this effect looks very sci-fi. | |
@@ -70,6 +71,8 @@ Below is a table which summarizes the current availability for all effects.
Energize A
✅
✅
✅
✅
Energize B
✅
✅
✅
✅
Fire
✅
✅
✅
✅
+
Focus
✅
✅
✅
✅
+
Glide
✅
✅
✅
✅
Glitch
✅
✅
✅
✅
Hexagon
✅
✅
✅
✅
@@ -190,6 +193,7 @@ Here are links to all effects which are currently available in the KDE store:
| [Energize A](https://store.kde.org/p/1884310) | [Energize A](https://store.kde.org/p/2133829) |
| [Energize B](https://store.kde.org/p/1884311) | [Energize B](https://store.kde.org/p/2133828) |
| [Fire](https://store.kde.org/p/1884307) | [Fire](https://store.kde.org/p/2133822) |
+| [Focus - coming soon,maybe] | [Focus - coming soon,maybe] |
| [Glide](https://store.kde.org/p/1935778) | [Glide](https://store.kde.org/p/2133839) |
| [Glitch](https://store.kde.org/p/1972813) | [Glitch](https://store.kde.org/p/2133844) |
| [Hexagon](https://store.kde.org/p/1884309) | [Hexagon](https://store.kde.org/p/2133836) |
diff --git a/docs/pics/focus.gif b/docs/pics/focus.gif
new file mode 100644
index 0000000..d678618
Binary files /dev/null and b/docs/pics/focus.gif differ
diff --git a/extension.js b/extension.js
index 2cd97c2..cdc3ef6 100644
--- a/extension.js
+++ b/extension.js
@@ -28,6 +28,7 @@ import Doom from './src/effects/Doom.js';
import EnergizeA from './src/effects/EnergizeA.js';
import EnergizeB from './src/effects/EnergizeB.js';
import Fire from './src/effects/Fire.js';
+import Focus from './src/effects/Focus.js';
import Glide from './src/effects/Glide.js';
import Glitch from './src/effects/Glitch.js';
import Hexagon from './src/effects/Hexagon.js';
@@ -44,6 +45,7 @@ import TVEffect from './src/effects/TVEffect.js';
import TVGlitch from './src/effects/TVGlitch.js';
import Wisps from './src/effects/Wisps.js';
+
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import {Workspace} from 'resource:///org/gnome/shell/ui/workspace.js';
import {WindowPreview} from 'resource:///org/gnome/shell/ui/windowPreview.js';
@@ -69,26 +71,13 @@ export default class BurnMyWindows extends Extension {
// New effects must be registered here and in prefs.js.
this._ALL_EFFECTS = [
- new Apparition(),
- new BrokenGlass(),
- new Doom(),
- new EnergizeA(),
- new EnergizeB(),
- new Fire(),
- new Glide(),
- new Glitch(),
- new Hexagon(),
- new Incinerate(),
- new Matrix(),
- new PaintBrush(),
- new Pixelate(),
- new PixelWheel(),
- new PixelWipe(),
- new Portal(),
- new SnapOfDisintegration(),
- new TRexAttack(),
- new TVEffect(),
- new TVGlitch(),
+ new Apparition(), new BrokenGlass(), new Doom(),
+ new EnergizeA(), new EnergizeB(), new Fire(),
+ new Focus(), new Glide(), new Glitch(),
+ new Hexagon(), new Incinerate(), new Matrix(),
+ new PaintBrush(), new Pixelate(), new PixelWheel(),
+ new PixelWipe(), new Portal(), new SnapOfDisintegration(),
+ new TRexAttack(), new TVEffect(), new TVGlitch(),
new Wisps(),
];
diff --git a/prefs.js b/prefs.js
index 419ac84..3882c9b 100644
--- a/prefs.js
+++ b/prefs.js
@@ -29,6 +29,7 @@ import Doom from './src/effects/Doom.js';
import EnergizeA from './src/effects/EnergizeA.js';
import EnergizeB from './src/effects/EnergizeB.js';
import Fire from './src/effects/Fire.js';
+import Focus from './src/effects/Focus.js';
import Glide from './src/effects/Glide.js';
import Glitch from './src/effects/Glitch.js';
import Hexagon from './src/effects/Hexagon.js';
@@ -45,6 +46,7 @@ import TVEffect from './src/effects/TVEffect.js';
import TVGlitch from './src/effects/TVGlitch.js';
import Wisps from './src/effects/Wisps.js';
+
import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
// Currently, the extension supports only one set of UI files. In the past, there were
@@ -69,29 +71,13 @@ export default class BurnMyWindowsPreferences extends ExtensionPreferences {
// New effects must be registered here and in extension.js.
this._ALL_EFFECTS = [
- Apparition,
- BrokenGlass,
- Doom,
- EnergizeA,
- EnergizeB,
- Fire,
- Glide,
- Glitch,
- Hexagon,
- Incinerate,
- Matrix,
- PaintBrush,
- Pixelate,
- PixelWheel,
- PixelWipe,
- Portal,
- SnapOfDisintegration,
- TRexAttack,
- TVEffect,
- TVGlitch,
- Wisps,
+ Apparition, BrokenGlass, Doom, EnergizeA, EnergizeB, Fire,
+ Focus, Glide, Glitch, Hexagon, Incinerate, Matrix,
+ PaintBrush, Pixelate, PixelWheel, PixelWipe, Portal, SnapOfDisintegration,
+ TRexAttack, TVEffect, TVGlitch, Wisps,
];
+
// Load all of our resources.
this._resources =
Gio.Resource.load(this.path + '/resources/burn-my-windows.gresource');
@@ -105,6 +91,7 @@ export default class BurnMyWindowsPreferences extends ExtensionPreferences {
this._builder.add_from_resource(`/ui/common/menus.ui`);
this._builder.add_from_resource(`/ui/${getUIDir()}/prefs.ui`);
+
// Store a reference to the general settings object.
this._settings = this.getSettings();
@@ -134,6 +121,7 @@ export default class BurnMyWindowsPreferences extends ExtensionPreferences {
// Maybe the service is masked...
}
+
let powerProfileRow = this._builder.get_object('profile-power-profile');
powerProfileRow.set_visible(hasPowerProfiles);
@@ -173,6 +161,7 @@ export default class BurnMyWindowsPreferences extends ExtensionPreferences {
}
});
+
// This is our top-level widget which we will return later.
this._widget = this._builder.get_object('general-prefs');
@@ -274,6 +263,7 @@ export default class BurnMyWindowsPreferences extends ExtensionPreferences {
}
});
+
// Some things can only be done once the widget is shown as we do not have access to
// the toplevel widget before.
this._widget.connect('realize', (widget) => {
diff --git a/resources/shaders/focus.frag b/resources/shaders/focus.frag
new file mode 100644
index 0000000..5082499
--- /dev/null
+++ b/resources/shaders/focus.frag
@@ -0,0 +1,86 @@
+//////////////////////////////////////////////////////////////////////////////////////////
+// ) ( //
+// ( /( ( ( ) ( ( ( ( )\ ) ( ( //
+// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( //
+// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ //
+// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) //
+// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< //
+// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ //
+// |__/ //
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// SPDX-FileCopyrightText: Justin Garza JGarza9788@gmail.com
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+// The content from common.glsl is automatically prepended to each shader effect. This
+// provides the standard input:
+
+// vec2 iTexCoord: Texture coordinates for retrieving the window input color.
+// bool uIsFullscreen: True if the window is maximized or in fullscreen mode.
+// bool uForOpening: True if a window-open animation is ongoing, false otherwise.
+// float uProgress: A value which transitions from 0 to 1 during the animation.
+// float uDuration: The duration of the current animation in seconds.
+// vec2 uSize: The size of uTexture in pixels.
+// float uPadding: The empty area around the actual window (e.g. where the shadow
+// is drawn). For now, this will only be set on GNOME.
+
+// Furthermore, there are two global methods for reading the window input color and
+// setting the shader output color. Both methods assume straight alpha:
+
+// vec4 getInputColor(vec2 coords)
+// void setOutputColor(vec4 outColor)
+
+
+// Ease-in-out cubic for alpha
+float easeInOutCubic(float x) {
+ return x < 0.5 ? 4.0 * x * x * x : 1.0 - pow(-2.0 * x + 2.0, 3.0) / 2.0;
+}
+
+// Ease-in-out sine for blur
+float easeInOutSine(float x) {
+ return -(cos(3.14159265 * x) - 1.0) / 2.0;
+}
+
+// A simple blur function
+vec4 blur(vec2 uv, float radius, float samples) {
+ vec4 color = vec4(0.0);
+
+ const float tau = 6.28318530718;
+ const float directions = 15.0;
+
+ for (float d = 0.0; d < tau; d += tau / directions) {
+ for (float s = 0.0; s < 1.0; s += 1.0 / samples) {
+ vec2 offset = vec2(cos(d), sin(d)) * radius * (1.0 - s) / uSize;
+ color += getInputColor(uv + offset);
+ }
+ }
+
+ return color / samples / directions;
+}
+
+
+// The width of the fading effect is loaded from the settings.
+uniform float uBlurAmount;
+uniform float uBlurQuality;
+
+void main() {
+
+ float progl = uForOpening ? uProgress : 1.0 - uProgress;
+
+ float easedProgressBlur = easeInOutSine(progl); // Blur easing
+ float easedProgressAlpha = easeInOutCubic(progl); // Alpha easing
+
+ // Control blur amount using easedProgressBlur
+ float blurAmount = mix(uBlurAmount, 0.0, easedProgressBlur);
+
+ // Apply blur
+ vec4 texColor = blur( iTexCoord.st, blurAmount, uBlurQuality);
+
+ // Control alpha using easedProgressAlpha
+ float alpha = easedProgressAlpha;
+
+ // Set final color with alpha transition
+ texColor.a *= alpha;
+
+ setOutputColor(texColor);
+}
\ No newline at end of file
diff --git a/resources/ui/adw/focus.ui b/resources/ui/adw/focus.ui
new file mode 100644
index 0000000..15965f4
--- /dev/null
+++ b/resources/ui/adw/focus.ui
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/schemas/org.gnome.shell.extensions.burn-my-windows-profile.gschema.xml b/schemas/org.gnome.shell.extensions.burn-my-windows-profile.gschema.xml
index d9ae300..41b793d 100644
--- a/schemas/org.gnome.shell.extensions.burn-my-windows-profile.gschema.xml
+++ b/schemas/org.gnome.shell.extensions.burn-my-windows-profile.gschema.xml
@@ -821,6 +821,35 @@ SPDX-License-Identifier: CC0-1.0
The color of the dust.
+
+
+
+
+
+
+ false
+ Focus Enable Effect
+ Use the Focus effect.
+
+
+
+ 500
+ Focus Animation Time
+ The time the Focus effect takes.
+
+
+
+ 50
+ Focus Blur Amount
+ The Blur Amount before Focusing.
+
+
+
+ 5
+ Focus Blur Quality
+ The Quality of the Blur (Setting this too high may increase GPU load and affect performance)
+
+
\ No newline at end of file
diff --git a/src/effects/Focus.js b/src/effects/Focus.js
new file mode 100644
index 0000000..7e18fd8
--- /dev/null
+++ b/src/effects/Focus.js
@@ -0,0 +1,99 @@
+//////////////////////////////////////////////////////////////////////////////////////////
+// ) ( //
+// ( /( ( ( ) ( ( ( ( )\ ) ( ( //
+// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( //
+// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ //
+// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) //
+// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< //
+// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ //
+// |__/ //
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// SPDX-FileCopyrightText: Justin Garza JGarza9788@gmail.com
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+'use strict';
+
+import * as utils from '../utils.js';
+
+// We import the ShaderFactory only in the Shell process as it is not required in the
+// preferences process. The preferences process does not create any shader instances, it
+// only uses the static metadata of the effect.
+const ShaderFactory = await utils.importInShellOnly('./ShaderFactory.js');
+
+const _ = await utils.importGettext();
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// This effect uses a blur effect to allow the window to focus in and out of view. //
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// The effect class can be used to get some metadata (like the effect's name or supported
+// GNOME Shell versions), to initialize the respective page of the settings dialog, as
+// well as to create the actual shader for the effect.
+export default class Effect {
+ // The constructor creates a ShaderFactory which will be used by extension.js to create
+ // shader instances for this effect. The shaders will be automagically created using the
+ // GLSL file in resources/shaders/.glsl. The callback will be called for each
+ // newly created shader instance.
+ constructor() {
+ this.shaderFactory = new ShaderFactory(Effect.getNick(), (shader) => {
+ // Store uniform locations of newly created shaders.
+ shader._uBlurAmount = shader.get_uniform_location('uBlurAmount');
+ shader._uBlurQuality = shader.get_uniform_location('uBlurQuality');
+
+ // Write all uniform values at the start of each animation.
+ shader.connect('begin-animation', (shader, settings) => {
+ shader.set_uniform_float(shader._uBlurAmount, 1, [
+ settings.get_int('focus-blur-amount'),
+ ]);
+
+ shader.set_uniform_float(shader._uBlurQuality, 1, [
+ settings.get_int('focus-blur-quality'),
+ ]);
+ });
+ });
+ }
+
+ // ---------------------------------------------------------------------------- metadata
+
+ // The effect is available on all GNOME Shell versions supported by this extension.
+ static getMinShellVersion() {
+ return [3, 36];
+ }
+
+ // This will be called in various places where a unique identifier for this effect is
+ // required. It should match the prefix of the settings keys which store whether the
+ // effect is enabled currently (e.g. '*-enable-effect'), and its animation time
+ // (e.g. '*-animation-time'). Also, the shader file and the settings UI files should be
+ // named likes this.
+ static getNick() {
+ return 'focus';
+ }
+
+ // This will be shown in the sidebar of the preferences dialog as well as in the
+ // drop-down menus where the user can choose the effect.
+ static getLabel() {
+ return _('Focus');
+ }
+
+ // -------------------------------------------------------------------- API for prefs.js
+
+ // This is called by the preferences dialog whenever a new effect profile is loaded. It
+ // binds all user interface elements to the respective settings keys of the profile.
+ static bindPreferences(dialog) {
+ // These connect the settings to the UI elements. Have a look at prefs.js
+ // on how to bind other types of UI elements.
+ dialog.bindAdjustment('focus-animation-time');
+ dialog.bindAdjustment('focus-blur-amount');
+ dialog.bindAdjustment('focus-blur-quality');
+ }
+
+ // ---------------------------------------------------------------- API for extension.js
+
+ // The getActorScale() is called from extension.js to adjust the actor's size during the
+ // animation. This is useful if the effect requires drawing something beyond the usual
+ // bounds of the actor. This only works for GNOME 3.38+.
+ static getActorScale(settings, forOpening, actor) {
+ return {x: 1.0, y: 1.0};
+ }
+}