🎉 Focus - again

This commit is contained in:
Justin Garza
2024-10-26 16:04:24 -04:00
parent 6f9b56a69a
commit a393d3cddb
8 changed files with 353 additions and 42 deletions
+5 -1
View File
@@ -34,7 +34,8 @@ This extension is not only more useless than the cube, but it is also much more
| **Doom** <br> Melt your windows. Inspired by the legendary screen transitions of the original Doom. | <img src ="docs/pics/doom.gif" /> |
| **Energize A** <br> Beam your windows away! | <img src ="docs/pics/energize-a.gif" /> |
| **Energize B** <br> Using different transporter technology results in an alternative visual effect. | <img src ="docs/pics/energize-b.gif" /> |
| **Fire** <br> 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. | <img src ="docs/pics/fire.gif" /> |
| **Fire** <br> 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. | <img src ="docs/pics/fire.gif" /> |
| **Focus** <br> Focus Dude, Focus | <img src ="docs/pics/focus.gif" /> |
| **Glide** <br> This very simple effect fades the window to transparency with subtle 3D effects. | <img src ="docs/pics/glide.gif" /> |
| **Glitch** <br> This effect applies some intentional graphics issues to your windows. | <img src ="docs/pics/glitch.gif" /> |
| **Hexagon** <br> With glowing lines and hexagon-shaped tiles, this effect looks very sci-fi. | <img src ="docs/pics/hexagon.gif" /> |
@@ -70,6 +71,8 @@ Below is a table which summarizes the current availability for all effects.
<tr><td>Energize A</td> <td>✅</td> <td>✅</td> <td>✅</td> <td>✅</td> </tr>
<tr><td>Energize B</td> <td>✅</td> <td>✅</td> <td>✅</td> <td>✅</td> </tr>
<tr><td>Fire</td> <td>✅</td> <td>✅</td> <td>✅</td> <td>✅</td> </tr>
<tr><td>Focus</td> <td>✅</td> <td>✅</td> <td>✅</td> <td>✅</td> </tr>
<!--^this is hypothetical ...i hope you don't mind-->
<tr><td>Glide</td> <td>✅</td> <td>✅</td> <td>✅</td> <td>✅</td> </tr>
<tr><td>Glitch</td> <td>✅</td> <td>✅</td> <td>✅</td> <td>✅</td> </tr>
<tr><td>Hexagon</td> <td>✅</td> <td>✅</td> <td>✅</td> <td>✅</td> </tr>
@@ -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) |
Binary file not shown.

After

Width:  |  Height:  |  Size: 615 KiB

+9 -20
View File
@@ -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(),
];
+11 -21
View File
@@ -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) => {
+86
View File
@@ -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);
}
+114
View File
@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
SPDX-FileCopyrightText: Your Name <your@email.com>
SPDX-License-Identifier: GPL-3.0-or-later
-->
<interface domain="burn-my-windows">
<object class="GtkAdjustment" id="focus-animation-time">
<property name="upper">5000</property>
<property name="lower">100</property>
<property name="step-increment">10</property>
<property name="page-increment">100</property>
</object>
<object class="GtkAdjustment" id="focus-blur-amount">
<property name="upper">100</property>
<property name="lower">0</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="focus-blur-quality">
<property name="upper">20</property>
<property name="lower">1</property>
<property name="step-increment">1</property>
<property name="page-increment">5</property>
</object>
<object class="AdwExpanderRow" id="focus-prefs">
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">Animation Time [ms]</property>
<child>
<object class="GtkScale">
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">0</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">focus-animation-time</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-focus-animation-time">
<property name="icon-name">edit-clear-symbolic</property>
<property name="valign">center</property>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">Blur Amount</property>
<child>
<object class="GtkScale">
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">2</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">focus-blur-amount</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-focus-blur-amount">
<property name="icon-name">edit-clear-symbolic</property>
<property name="valign">center</property>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">Blur Quality</property>
<child>
<object class="GtkScale">
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">2</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">focus-blur-quality</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-focus-blur-quality">
<property name="icon-name">edit-clear-symbolic</property>
<property name="valign">center</property>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</interface>
@@ -821,6 +821,35 @@ SPDX-License-Identifier: CC0-1.0
<description>The color of the dust.</description>
</key>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Simple Fade Effect Options -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<key name="focus-enable-effect" type="b">
<default>false</default>
<summary>Focus Enable Effect</summary>
<description>Use the Focus effect.</description>
</key>
<key name="focus-animation-time" type="i">
<default>500</default>
<summary>Focus Animation Time</summary>
<description>The time the Focus effect takes.</description>
</key>
<key name="focus-blur-amount" type="i">
<default>50</default>
<summary>Focus Blur Amount</summary>
<description>The Blur Amount before Focusing.</description>
</key>
<key name="focus-blur-quality" type="i">
<default>5</default>
<summary>Focus Blur Quality</summary>
<description>The Quality of the Blur (Setting this too high may increase GPU load and affect performance)</description>
</key>
</schema>
</schemalist>
+99
View File
@@ -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/<nick>.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};
}
}