Compare commits

...

32 Commits
v4 ... v5

Author SHA1 Message Date
Simon Schneegans 27fec7adea ♻️ Rename method
Deploy / Extension Bundle (push) Has been cancelled
2022-01-02 14:00:18 +01:00
Simon Schneegans 3630e461a9 📝 Tweak README 2022-01-02 13:35:40 +01:00
Simon Schneegans d14e9750cf 📝 Add list of included effects 2022-01-02 13:32:17 +01:00
Simon Schneegans d44f021348 🔀 Merge pull request #19 from Schneegans/feature/menu-button 2022-01-02 12:51:13 +01:00
Simon Schneegans 681afb4793 📝 Add changelog entry 2022-01-02 12:49:59 +01:00
Simon Schneegans 5682a5cdf8 🪲 Fix GTK3 2022-01-02 12:48:47 +01:00
Simon Schneegans 8c7e3abbeb 🎉 Add a menu button 2022-01-02 12:37:51 +01:00
Simon Schneegans 7e05588682 🔧 Tweak motto 2022-01-02 12:34:13 +01:00
Simon Schneegans 13d02da36b 🔀 Merge pull request #18 from Schneegans/feature/fix-14 2022-01-02 12:32:58 +01:00
Simon Schneegans 552dc3b0c7 📝 Fix changelog 2022-01-02 12:31:15 +01:00
Simon Schneegans 976533ccc8 🎉 Support ovierview animations in GNOME 3.36 2022-01-02 07:58:35 +01:00
Simon Schneegans 403fac3367 📝 Add changelog entry 2022-01-01 21:57:57 +01:00
Simon Schneegans b916f9677e 🔧 Do not attempt to animate window closing in the overview of GNOME 3.36 2022-01-01 21:49:31 +01:00
Simon Schneegans 4965ca8735 🔀 Merge pull request #16 from Schneegans/feature/claws 2022-01-01 21:23:12 +01:00
Simon Schneegans c9bfdc4bf9 📝 Add comment 2022-01-01 21:21:56 +01:00
Simon Schneegans 54fa765766 📝 Add changelog entry 2022-01-01 21:19:30 +01:00
Simon Schneegans 37cd1fb7cc 📝 Add plenty of comments 2022-01-01 21:18:49 +01:00
Simon Schneegans 5d845e09c1 🎨 Add claws source file 2022-01-01 20:59:21 +01:00
Simon Schneegans f758f4db82 🔧 Tweak defaults 2022-01-01 20:55:12 +01:00
Simon Schneegans b410536fc2 🎉 Make T-Rex effect configurable 2022-01-01 20:47:59 +01:00
Simon Schneegans db636a7cfe Merge branch 'main' into feature/claws 2022-01-01 20:17:51 +01:00
Simon Schneegans 8c6c1bc7bd 🪲 Fix GTK3 2022-01-01 20:16:59 +01:00
Simon Schneegans 976e713a2b 🎉 Make TV Effect color configurable 2022-01-01 20:12:41 +01:00
Simon Schneegans 7dea28a145 🔧 Reduce scaling 2022-01-01 19:51:26 +01:00
Simon Schneegans 918a12060c 🎉 Add initial T-Rex shader 2022-01-01 19:48:24 +01:00
Simon Schneegans 11a3562533 🔀 Merge pull request #15 from Schneegans/feature/tv-effect 2021-12-31 20:36:56 +01:00
Simon Schneegans 68c851c9e0 📝 Add changelog entry 2021-12-31 20:35:37 +01:00
Simon Schneegans 03db97fdda 📝 Add comments 2021-12-31 20:34:50 +01:00
Simon Schneegans 0ee171aae0 Merge branch 'main' into feature/tv-effect 2021-12-30 13:51:54 +01:00
Simon Schneegans 9c9b9657e8 🎉 Improve fire appearance 2021-12-30 13:51:14 +01:00
Simon Schneegans fdd21a44b8 🎉 Add TV Effect shader 2021-12-30 13:42:41 +01:00
Simon Schneegans cd3b91a191 🎉 Bump version number 2021-12-25 20:39:28 +01:00
20 changed files with 759 additions and 176 deletions
+9 -5
View File
@@ -1,8 +1,4 @@
<p align="center">
<img src ="docs/pics/teaser.gif" />
</p>
# Set your Windows on Fire!
# Set GNOME Shell on Fire!
<a href="https://github.com/Schneegans/Burn-My-Windows/actions"><img src="https://github.com/Schneegans/Burn-My-Windows/workflows/Checks/badge.svg?branch=main" /></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-GPLv3-blue.svg?labelColor=303030" /></a>
@@ -11,6 +7,14 @@
When I released the [Desktop Cube Extension](https://github.com/Schneegans/Desktop-Cube/), many people requested to revive one of the most useless features of Linux desktop history: Setting windows on fire!
This extension is not only more useless than the cube, but it is also much more hacky. So I expect some bug! [Let's incinerate them all](https://github.com/Schneegans/Burn-My-Windows/issues)!
## Included Effects
Name | Preview
-----|--------
**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" />
**Matrix** <br> Turn your windows into a shower of green letters! The color is actually configurable. <br><br> _Only available in GNOME Shell 40+_ | <img src ="docs/pics/matrix.gif" />
**T-Rex Attack** <br> Destroy your windows with a series of violent slashes! <br><br> _Only available in GNOME Shell 40+_ | <img src ="docs/pics/trex.gif" />
**TV-Effect** <br> This is a very simple effect to demonstrate that this extension could also be used in a more professional environment. | <img src ="docs/pics/tv.gif" />
## Installation
+7
View File
@@ -0,0 +1,7 @@
# Notes for `claws.blend`
This is the source file for `resources/img/claws.png`. To generate the image, the animation in `claws.blend` is rendered to 256 PNG files and then combined using this command:
```bash
convert *.png -average claws.png
```
Binary file not shown.
+18
View File
@@ -1,5 +1,23 @@
# Changelog of the Burn-My-Windows Extension
## [Burn My Window 5](https://github.com/schneegans/Burn-My-Windows/releases/tag/v5)
**Release Date:** TBD
#### New Features
* Added a new ridiculous close-animation: the T-Rex-Attack!
* Added a new simple close-animation: the TV-Effect!
* Added a menu to the preferences dialog with links for bug reporting and donations.
#### Other Enhancements
* The fire shader now uses a `smoothstep` to make it less blocky.
#### Bug Fixes
* Fixed a bug which messed up the overview of GNOME Shell 3.36.
## [Burn My Window 4](https://github.com/schneegans/Burn-My-Windows/releases/tag/v4)
**Release Date:** 2021-12-25
Binary file not shown.

After

Width:  |  Height:  |  Size: 949 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

+35 -3
View File
@@ -15,6 +15,9 @@
const {Clutter, Gio, Meta} = imports.gi;
const Config = imports.misc.config;
const [GS_MAJOR, GS_MINOR] = Config.PACKAGE_VERSION.split('.');
const Workspace = imports.ui.workspace.Workspace;
const WindowManager = imports.ui.windowManager.WindowManager;
const WINDOW_REPOSITIONING_DELAY = imports.ui.workspace.WINDOW_REPOSITIONING_DELAY;
@@ -24,6 +27,8 @@ const Me = imports.misc.extensionUtils.getCurrentExtension();
const utils = Me.imports.src.common.utils;
const FireShader = Me.imports.src.extension.FireShader.FireShader;
const MatrixShader = Me.imports.src.extension.MatrixShader.MatrixShader;
const TVEffectShader = Me.imports.src.extension.TVEffectShader.TVEffectShader;
const TRexShader = Me.imports.src.extension.TRexShader.TRexShader;
//////////////////////////////////////////////////////////////////////////////////////////
// This extensions modifies the window-close animation to look like the window was set //
@@ -50,6 +55,7 @@ class Extension {
// We will monkey-patch these three methods. Let's store the original ones.
this._origWindowRemoved = Workspace.prototype._windowRemoved;
this._origDoRemoveWindow = Workspace.prototype._doRemoveWindow;
this._origAddWindowClone = Workspace.prototype._addWindowClone;
this._origShouldAnimateActor = WindowManager.prototype._shouldAnimateActor;
// We may also override these animation times.
@@ -75,6 +81,19 @@ class Extension {
// the WorkspacesView.
const extensionThis = this;
// On GNOME 3.36, the window clone's 'destroy' handler only calls _removeWindowClone
// but not _doRemoveWindow. The latter is required to trigger the repositioning of the
// overview window layout. Therefore we call this method in addition.
// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/gnome-3-36/js/ui/workspace.js#L1877
// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspace.js#L1415
if (GS_MAJOR == 3 && GS_MINOR == 36) {
Workspace.prototype._addWindowClone = function(...params) {
const [clone, overlay] = extensionThis._origAddWindowClone.apply(this, params);
clone.connect('destroy', () => this._doRemoveWindow(clone.metaWindow));
return [clone, overlay];
};
}
// These three method overrides are mega-hacky! They are only required to make the
// fire animation work in the overview. Usually, windows are not faded when closed
// from the overview (why?). With these overrides we make sure that they are actually
@@ -93,6 +112,7 @@ class Extension {
// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspace.js#L1178
Workspace.prototype._doRemoveWindow = function(metaWin) {
if (extensionThis._shouldDestroy(this, metaWin)) {
utils.debug((new Error()).stack);
extensionThis._origDoRemoveWindow.apply(this, [metaWin]);
}
};
@@ -104,11 +124,11 @@ class Extension {
// whether it was called by _destroyWindow. If so, we return true. Let's see if this
// breaks stuff left and right...
// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/windowManager.js#L1125
WindowManager.prototype._shouldAnimateActor = function(actor, types) {
WindowManager.prototype._shouldAnimateActor = function(...params) {
if ((new Error()).stack.split('\n')[1].includes('_destroyWindow@')) {
return true;
}
return extensionThis._origShouldAnimateActor.apply(this, [actor, types]);
return extensionThis._origShouldAnimateActor.apply(this, params);
};
// The close animation is set up in WindowManager's _destroyWindow:
@@ -154,6 +174,15 @@ class Extension {
shader = new FireShader(this._settings);
} else if (mode == 2) {
shader = new MatrixShader(this._settings);
} else if (mode == 3) {
shader = new TVEffectShader(this._settings);
tweakTransition('scale-y', 0.5);
} else if (mode == 4) {
shader = new TRexShader(this._settings);
const warp = 0.5 * this._settings.get_double('claw-scratch-warp');
tweakTransition('scale-x', 1.0 + warp);
tweakTransition('scale-y', 1.0 + warp);
}
if (shader) {
@@ -182,6 +211,7 @@ class Extension {
Workspace.prototype._windowRemoved = this._origWindowRemoved;
Workspace.prototype._doRemoveWindow = this._origDoRemoveWindow;
Workspace.prototype._addWindowClone = this._origAddWindowClone;
WindowManager.prototype._shouldAnimateActor = this._origShouldAnimateActor;
imports.ui.windowManager.DESTROY_WINDOW_ANIMATION_TIME = this._origWindowTime;
@@ -200,7 +230,9 @@ class Extension {
return true;
}
const actor = workspace._windows[index]._windowActor;
// This was called "realWindow" in GNOME 3.36.
const GS_336 = GS_MAJOR == 3 && GS_MINOR == 36;
const actor = workspace._windows[index][GS_336 ? 'realWindow' : '_windowActor'];
if (!actor.get_transition('scale-y')) {
return true;
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"uuid": "burn-my-windows@schneegans.github.com",
"description": "Disintegrate your apps the old-school way.",
"description": "Disintegrate your apps with style.",
"name": "Burn My Windows",
"gettext-domain": "burn-my-windows",
"settings-schema": "org.gnome.shell.extensions.burn-my-windows",
@@ -11,5 +11,5 @@
"41"
],
"url": "https://github.com/Schneegans/Burn-My-Windows",
"version": 4
"version": 5
}
+39 -4
View File
@@ -34,7 +34,7 @@ var PreferencesDialog = class PreferencesDialog {
// Load the user interface file.
this._builder = new Gtk.Builder();
this._builder.add_from_resource(`/ui/${utils.gtk4() ? 'gtk4' : 'gtk3'}.ui`);
this._builder.add_from_resource(`/ui/${utils.isGTK4() ? 'gtk4' : 'gtk3'}.ui`);
// This is our top-level widget which we will return later.
this._widget = this._builder.get_object('settings-widget');
@@ -57,8 +57,13 @@ var PreferencesDialog = class PreferencesDialog {
this._bindAdjustment('matrix-randomness');
this._bindColorButton('matrix-trail-color');
this._bindColorButton('matrix-tip-color');
this._bindColorButton('tv-effect-color');
this._bindColorButton('claw-scratch-color');
this._bindAdjustment('claw-scratch-scale');
this._bindAdjustment('claw-scratch-count');
this._bindAdjustment('claw-scratch-warp');
// The fire-gradient-reset button needs to by bound explicitly.
// The fire-gradient-reset button needs to be bound explicitly.
this._builder.get_object('reset-fire-colors').connect('clicked', () => {
this._settings.reset('fire-color-1');
this._settings.reset('fire-color-2');
@@ -70,6 +75,36 @@ var PreferencesDialog = class PreferencesDialog {
// Initialize the fire-preset dropdown.
this._createFirePresets();
// Add a menu to the title bar of the preferences dialog.
this._widget.connect('realize', (widget) => {
const window = utils.isGTK4() ? widget.get_root() : widget.get_toplevel();
// Show the version number in the title bar.
window.set_title(`Burn-My-Windows ${Me.metadata.version}`);
// Add the menu.
const menu = this._builder.get_object('menu-button');
window.get_titlebar().pack_end(menu);
// Populate the actions.
const group = Gio.SimpleActionGroup.new();
const addAction = (name, uri) => {
const action = Gio.SimpleAction.new(name, null);
action.connect('activate', () => Gtk.show_uri(null, uri, Gdk.CURRENT_TIME));
group.add_action(action);
};
addAction('homepage', 'https://github.com/Schneegans/Burn-My-Windows');
addAction('bugs', 'https://github.com/Schneegans/Burn-My-Windows/issues');
addAction(
'donate-paypal',
'https://www.paypal.com/donate/?hosted_button_id=3F7UFL8KLVPXE');
addAction('donate-github', 'https://github.com/sponsors/Schneegans');
window.insert_action_group('prefs', group);
});
// As we do not have something like a destructor, we just listen for the destroy
// signal of our main widget.
this._widget.connect('destroy', () => {
@@ -78,7 +113,7 @@ var PreferencesDialog = class PreferencesDialog {
});
// Show the widgets on GTK3.
if (!utils.gtk4()) {
if (!utils.isGTK4()) {
this._widget.show_all();
}
}
@@ -245,7 +280,7 @@ var PreferencesDialog = class PreferencesDialog {
this._builder.get_object('fire-preset-button').set_menu_model(menu);
const root = utils.gtk4() ? widget.get_root() : widget.get_toplevel();
const root = utils.isGTK4() ? widget.get_root() : widget.get_toplevel();
root.insert_action_group(groupName, group);
});
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

+51 -157
View File
@@ -13,12 +13,50 @@
<col id="1">fire</col>
</row>
<row>
<col id="0">Matrix</col>
<col id="1">matrix</col>
<col id="0">TV Effect</col>
<col id="1">tv</col>
</row>
</data>
</object>
<menu id="main-menu">
<section>
<item>
<attribute name="label" translatable="yes">Visit Homepage</attribute>
<attribute name="action">prefs.homepage</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Report a Bug</attribute>
<attribute name="action">prefs.bugs</attribute>
</item>
</section>
<section>
<submenu>
<attribute name="label" translatable="yes">Donate</attribute>
<item>
<attribute name="label" translatable="yes">Via PayPal</attribute>
<attribute name="action">prefs.donate-paypal</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Via GitHub</attribute>
<attribute name="action">prefs.donate-github</attribute>
</item>
</submenu>
</section>
</menu>
<object class="GtkMenuButton" id="menu-button">
<property name="menu-model">main-menu</property>
<property name="visible">1</property>
<child>
<object class="GtkImage">
<property name="icon-name">open-menu-symbolic</property>
<property name="visible">1</property>
<property name="icon-size">1</property>
</object>
</child>
</object>
<object class="GtkAdjustment" id="destroy-animation-time">
<property name="upper">10000</property>
<property name="lower">500</property>
@@ -88,7 +126,7 @@
<object class="GtkListBox">
<property name="selection-mode">none</property>
<!-- <child>
<child>
<object class="GtkListBoxRow">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
@@ -138,7 +176,7 @@
</object>
</child>
</object>
</child> -->
</child>
<child>
<object class="GtkListBoxRow">
@@ -459,13 +497,14 @@
</object>
</child>
<!-- <child>
<child>
<object class="GtkBox">
<property name="margin-top">30</property>
<property name="margin-bottom">10</property>
<child>
<object class="GtkLabel">
<property name="label">Matrix Animation Options</property>
<property name="label">TV Effect Options</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<style>
@@ -474,9 +513,9 @@
</object>
</child>
</object>
</child> -->
</child>
<!-- <child>
<child>
<object class="GtkFrame">
<child>
<object class="GtkListBox">
@@ -497,7 +536,7 @@
<property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Scale</property>
<property name="label" translatable="yes">Color</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
@@ -505,112 +544,13 @@
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<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">matrix-scale</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-matrix-scale">
<child>
<object class="GtkImage">
<property name="icon-name">edit-clear-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
<property name="tooltip-text">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Randomness</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<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">matrix-randomness</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-matrix-randomness">
<child>
<object class="GtkImage">
<property name="icon-name">edit-clear-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
<property name="tooltip-text">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Trail Color</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkColorButton" id="matrix-trail-color">
<object class="GtkColorButton" id="tv-effect-color">
<property name="use_alpha">1</property>
<property name="show_editor">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-matrix-trail-color">
<object class="GtkButton" id="reset-tv-effect-color">
<child>
<object class="GtkImage">
<property name="icon-name">edit-clear-symbolic</property>
@@ -628,56 +568,10 @@
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Tip Color</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkColorButton" id="matrix-tip-color">
<property name="use_alpha">1</property>
<property name="show_editor">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-matrix-tip-color">
<child>
<object class="GtkImage">
<property name="icon-name">edit-clear-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
<property name="tooltip-text">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child> -->
</child>
</object>
</child>
+311
View File
@@ -16,9 +16,48 @@
<col id="0">Matrix</col>
<col id="1">matrix</col>
</row>
<row>
<col id="0">TV Effect</col>
<col id="1">tv</col>
</row>
<row>
<col id="0">T-Rex Attack</col>
<col id="1">trex</col>
</row>
</data>
</object>
<menu id="main-menu">
<section>
<item>
<attribute name="label" translatable="yes">Visit Homepage</attribute>
<attribute name="action">prefs.homepage</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Report a Bug</attribute>
<attribute name="action">prefs.bugs</attribute>
</item>
</section>
<section>
<submenu>
<attribute name="label" translatable="yes">Donate</attribute>
<item>
<attribute name="label" translatable="yes">Via PayPal</attribute>
<attribute name="action">prefs.donate-paypal</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Via GitHub</attribute>
<attribute name="action">prefs.donate-github</attribute>
</item>
</submenu>
</section>
</menu>
<object class="GtkMenuButton" id="menu-button">
<property name="menu-model">main-menu</property>
<property name="icon-name">open-menu-symbolic</property>
</object>
<object class="GtkScrolledWindow" id="settings-widget">
<property name="hscrollbar-policy">never</property>
<property name="min-content-height">200</property>
@@ -570,6 +609,278 @@
</child>
<child>
<object class="GtkBox">
<property name="margin-top">30</property>
<property name="margin-bottom">10</property>
<child>
<object class="GtkLabel">
<property name="label">T-Rex Attack Options</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<style>
<class name="title-4" />
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkFrame">
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<property name="show-separators">1</property>
<style>
<class name="rich-list" />
</style>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Claw Scratch Scale</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">1</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">
<object class="GtkAdjustment" id="claw-scratch-scale">
<property name="upper">10</property>
<property name="lower">0.1</property>
<property name="step-increment">0.1</property>
<property name="page-increment">1</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-claw-scratch-scale">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Claw Scratch Count</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<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">
<object class="GtkAdjustment" id="claw-scratch-count">
<property name="upper">50</property>
<property name="lower">1</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-claw-scratch-count">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Warp Effect</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<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">
<object class="GtkAdjustment" id="claw-scratch-warp">
<property name="upper">1</property>
<property name="lower">0</property>
<property name="step-increment">0.01</property>
<property name="page-increment">0.1</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-claw-scratch-warp">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Flash Color</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkColorButton" id="claw-scratch-color">
<property name="use_alpha">1</property>
<property name="show_editor">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-claw-scratch-color">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="margin-top">30</property>
<property name="margin-bottom">10</property>
<child>
<object class="GtkLabel">
<property name="label">TV Effect Options</property>
<property name="xalign">0</property>
<property name="hexpand">1</property>
<style>
<class name="title-4" />
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkFrame">
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<property name="show-separators">1</property>
<style>
<class name="rich-list" />
</style>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Color</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkColorButton" id="tv-effect-color">
<property name="use_alpha">0</property>
<property name="show_editor">1</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-tv-effect-color">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
@@ -4,6 +4,8 @@
<enum id='org.gnome.shell.extensions.burn-my-windows.AnimationType'>
<value value='1' nick='fire' />
<value value='2' nick='matrix' />
<value value='3' nick='tv' />
<value value='4' nick='trex' />
</enum>
<schema path="/org/gnome/shell/extensions/burn-my-windows/" id="org.gnome.shell.extensions.burn-my-windows">
@@ -94,6 +96,39 @@
<description>The color matrix trails.</description>
</key>
<key name="tv-effect-color" type="s">
<default>"rgb(255, 255, 255)"</default>
<summary>TV Effect Color</summary>
<description>The color of the TV effect.</description>
</key>
<key name="claw-scratch-color" type="s">
<default>"rgb(170, 0, 0)"</default>
<summary>Claw Scratch Color</summary>
<description>The color of the claw scratches.</description>
</key>
<key name="claw-scratch-scale" type="d">
<default>1.0</default>
<summary>Claw Scratch Scale</summary>
<description>Size of the claw scratches.</description>
</key>
<key name="claw-scratch-warp" type="d">
<default>0.15</default>
<summary>Claw Scratch Warp</summary>
<description>Intensity of the claw scratch warp effect.</description>
</key>
<key name="claw-scratch-count" type="i">
<default>5</default>
<summary>Claw Scratch Count</summary>
<description>Number of claw scratches drawn on top of each other.</description>
</key>
</schema>
</schemalist>
+1 -1
View File
@@ -39,6 +39,6 @@ function debug(message) {
}
// This method simply returns true if we are currently using GTK4.
function gtk4() {
function isGTK4() {
return Gtk.get_major_version() == 4;
}
+4 -4
View File
@@ -111,10 +111,10 @@ var FireShader = GObject.registerClass({Properties: {}, Signals: {}},
// Fade at window borders.
vec2 pos = cogl_tex_coord_in[0].st * vec2(uSizeX, uSizeY);
effectMask *= clamp(pos.x / edgeFadeWidth, 0, 1);
effectMask *= clamp(pos.y / edgeFadeWidth, 0, 1);
effectMask *= clamp((uSizeX - pos.x) / edgeFadeWidth, 0, 1);
effectMask *= clamp((uSizeY - pos.y) / edgeFadeWidth, 0, 1);
effectMask *= smoothstep(0, 1, clamp(pos.x / edgeFadeWidth, 0, 1));
effectMask *= smoothstep(0, 1, clamp(pos.y / edgeFadeWidth, 0, 1));
effectMask *= smoothstep(0, 1, clamp((uSizeX - pos.x) / edgeFadeWidth, 0, 1));
effectMask *= smoothstep(0, 1, clamp((uSizeY - pos.y) / edgeFadeWidth, 0, 1));
return vec2(windowMask, effectMask);
}
+157
View File
@@ -0,0 +1,157 @@
//////////////////////////////////////////////////////////////////////////////////////////
// ) ( //
// ( /( ( ( ) ( ( ( ( )\ ) ( ( //
// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( //
// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ //
// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) //
// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< //
// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ //
// |__/ //
// Copyright (c) 2021 Simon Schneegans //
// Released under the GPLv3 or later. See LICENSE file for details. //
//////////////////////////////////////////////////////////////////////////////////////////
'use strict';
const {Clutter, GObject, GdkPixbuf, Cogl} = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const shaderSnippets = Me.imports.src.extension.shaderSnippets;
//////////////////////////////////////////////////////////////////////////////////////////
// This effect tears your windows apart with a series of violent scratches! //
// This effect is not available on GNOME 3.3x, due to the limitation described in the //
// documentation of vfunc_paint_target further down in this file. //
//////////////////////////////////////////////////////////////////////////////////////////
var TRexShader = GObject.registerClass({Properties: {}, Signals: {}},
class TRexShader extends Clutter.ShaderEffect {
_init(settings) {
super._init({shader_type: Clutter.ShaderType.FRAGMENT_SHADER});
// Load the claw texture. As the shader is re-created for each window animation, this
// texture is also re-created each time. This could be improved in the future!
// See assets/README.md for how this texture was created.
const clawData = GdkPixbuf.Pixbuf.new_from_resource('/img/claws.png');
this._clawTexture = new Clutter.Image();
this._clawTexture.set_data(
clawData.get_pixels(), Cogl.PixelFormat.RGB_888, clawData.width, clawData.height,
clawData.rowstride);
const color = Clutter.Color.from_string(settings.get_string('claw-scratch-color'))[1];
this.set_shader_source(`
// Inject some common shader snippets.
${shaderSnippets.standardUniforms()}
${shaderSnippets.noise()}
// See assets/README.md for how this texture was created.
uniform sampler2D uClawTexture;
const vec2 SEED = vec2(${Math.random()}, ${Math.random()});
const float CLAW_SIZE = ${settings.get_double('claw-scratch-scale')};
const float NUM_CLAWS = ${settings.get_int('claw-scratch-count')};
const float WARP_INTENSITY = 1.0 + ${settings.get_double('claw-scratch-warp')};
const float FLASH_INTENSITY = 0.1;
const float MAX_SPAWN_TIME = 0.5; // Scratches will only start in the first half of the animation.
const float FF_TIME = 0.5; // Relative time for the final fade to transparency.
// This method generates a grid of randomly rotated, slightly shifted and scaled
// UV squares. It returns the texture coords of the UV square at the given actor
// coordinates. If these do not fall into one of the UV grids, the coordinates of
// the closest UV grid will be clamped and returned.
vec2 getClawUV(vec2 texCoords, float gridScale, vec2 seed) {
// Shift coordinates by a random offset and make sure the have a 1:1 aspect ratio.
vec2 coords = texCoords + rand2(seed);
coords *= uSizeX < uSizeY ? vec2(1.0, 1.0 * uSizeY / uSizeX) : vec2(1.0 * uSizeX / uSizeY, 1.0);
// Apply global scale.
coords *= gridScale;
// Get grid cell coordinates in [0..1].
vec2 cellUV = mod(coords, vec2(1));
// This is unique for each cell.
vec2 cellID = coords-cellUV + vec2(362.456);
// Add random rotation, scale and offset to each grid cell.
float scale = mix(0.8, 1.0, rand(cellID*seed*134.451));
float offsetX = mix(0.0, 1.0 - scale, rand(cellID*seed*54.4129));
float offsetY = mix(0.0, 1.0 - scale, rand(cellID*seed*25.3089));
float rotation = mix(0.0, 2.0 * 3.141, rand(cellID*seed*2.99837));
cellUV -= vec2(offsetX, offsetY);
cellUV /= scale;
cellUV -= 0.5;
cellUV = vec2(cellUV.x * cos(rotation) - cellUV.y * sin(rotation),
cellUV.x * sin(rotation) + cellUV.y * cos(rotation));
cellUV += 0.5;
// Clamp resulting coordinates.
return clamp(cellUV, vec2(0), vec2(1));
}
void main() {
// Warp the texture coordinates to create a blow-up effect.
vec2 coords = cogl_tex_coord_in[0].st * 2.0 - 1.0;
float dist = length(coords);
coords = (coords/dist * pow(dist, WARP_INTENSITY)) * 0.5 + 0.5;
coords = mix(cogl_tex_coord_in[0].st, coords, uProgress);
// Accumulate several random scratches. The color in the scratch map refers to the
// relative time when the respective part will become invisible. Therefore we can
// add a value to make the scratch appear later.
float scratchMap = 1.0;
for (int i=0; i<NUM_CLAWS; ++i) {
vec2 uv = getClawUV(coords, 1.0/CLAW_SIZE, SEED*(i+1));
float delay = i/NUM_CLAWS * MAX_SPAWN_TIME;
scratchMap = min(scratchMap, clamp(texture2D(uClawTexture, uv).r + delay, 0, 1));
}
// Get the window texture. We shift the texture lookup by the local derivative of
// the claw texture in order to mimic some folding distortion.
vec2 offset = vec2(dFdx(scratchMap), dFdy(scratchMap)) * uProgress * 0.5;
cogl_color_out = texture2D(uTexture, coords + offset);
// Hide scratched out parts.
cogl_color_out *= (scratchMap > uProgress ? 1 : 0);
// Add colorful flashes.
float flashIntensity = 1.0 / FLASH_INTENSITY * (scratchMap - uProgress) + 1;
if (flashIntensity < 0 || flashIntensity >= 1) {
flashIntensity = 0;
}
vec3 flashColor = vec3(${color.red / 255},
${color.green / 255},
${color.blue / 255}) * ${color.alpha / 255};
cogl_color_out.rgb += flashIntensity * mix(flashColor, vec3(0), uProgress);
// Fade out the remaining shards.
float fade = smoothstep(0, 1, 1 - clamp((uProgress - 1.0 + FF_TIME)/FF_TIME, 0, 1));
cogl_color_out *= fade;
// These are pretty useful for understanding how this works.
// cogl_color_out = vec4(vec3(flashIntensity), 1);
// cogl_color_out = vec4(vec3(scratchMap), 1);
}
`);
};
// This is overridden to bind the claw texture for drawing. Sadly, this seems to be
// impossible under GNOME 3.3x as this.get_pipeline() is not available. It was called
// get_target() back then but this is not wrapped in GJS.
// https://gitlab.gnome.org/GNOME/mutter/-/blob/gnome-3-36/clutter/clutter/clutter-offscreen-effect.c#L598
vfunc_paint_target(node, paint_context) {
const pipeline = this.get_pipeline();
pipeline.set_layer_texture(1, this._clawTexture.get_texture());
this.set_uniform_value('uClawTexture', 1);
super.vfunc_paint_target(node, paint_context);
}
});
+90
View File
@@ -0,0 +1,90 @@
//////////////////////////////////////////////////////////////////////////////////////////
// ) ( //
// ( /( ( ( ) ( ( ( ( )\ ) ( ( //
// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( //
// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ //
// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) //
// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< //
// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ //
// |__/ //
// Copyright (c) 2021 Simon Schneegans //
// Released under the GPLv3 or later. See LICENSE file for details. //
//////////////////////////////////////////////////////////////////////////////////////////
'use strict';
const {Clutter, GObject} = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const shaderSnippets = Me.imports.src.extension.shaderSnippets;
//////////////////////////////////////////////////////////////////////////////////////////
// The TVEffectShader hides the actor by making it first transparent from top and //
// bottom towards the middle and then hiding the resulting line from left and right //
// towards the center. //
//////////////////////////////////////////////////////////////////////////////////////////
var TVEffectShader = GObject.registerClass(
{Properties: {}, Signals: {}}, class TVEffectShader extends Clutter.ShaderEffect {
_init(settings) {
super._init({shader_type: Clutter.ShaderType.FRAGMENT_SHADER});
const color =
Clutter.Color.from_string(settings.get_string('tv-effect-color'))[1];
this.set_shader_source(`
// Inject some common shader snippets.
${shaderSnippets.standardUniforms()}
const float BLUR_WIDTH = 0.01; // Width of the gradients.
const float TB_TIME = 0.7; // Relative time for the top/bottom animation.
const float LR_TIME = 0.4; // Relative time for the left/right animation.
const float LR_DELAY = 0.6; // Delay after which the left/right animation starts.
const float FF_TIME = 0.2; // Relative time for the final fade to transparency.
void main() {
// All of these are in [0..1] during the different stages of the animation.
// tb refers to the top-bottom animation.
// lr refers to the left-right animation.
// ff refers to the final fade animation.
float tbProgress = smoothstep(0, 1, clamp(uProgress/TB_TIME, 0, 1));
float lrProgress = smoothstep(0, 1, clamp((uProgress - LR_DELAY)/LR_TIME, 0, 1));
float ffProgress = smoothstep(0, 1, clamp((uProgress - 1.0 + FF_TIME)/FF_TIME, 0, 1));
// This is a top-center-bottom gradient in [0..1..0]
float tb = cogl_tex_coord_in[0].t * 2;
tb = tb < 1 ? tb : 2 - tb;
// This is a left-center-right gradient in [0..1..0]
float lr = cogl_tex_coord_in[0].s * 2;
lr = lr < 1 ? lr : 2 - lr;
// Combine the progress values with the gradients to create the alpha masks.
float tbMask = 1 - smoothstep(0, 1, clamp((tbProgress - tb) / BLUR_WIDTH, 0, 1));
float lrMask = 1 - smoothstep(0, 1, clamp((lrProgress - lr) / BLUR_WIDTH, 0, 1));
float ffMask = 1 - smoothstep(0, 1, ffProgress);
// Assemble the final alpha value.
float mask = tbMask * lrMask * ffMask;
vec4 windowColor = texture2D(uTexture, cogl_tex_coord_in[0].st);
vec4 effectColor = vec4(${color.red / 255},
${color.green / 255},
${color.blue / 255}, 1.0) * windowColor.a;
windowColor.rgb = mix(windowColor.rgb, effectColor.rgb, smoothstep(0, 1, uProgress));
cogl_color_out = windowColor * mask;
// These are pretty useful for understanding how this works.
// cogl_color_out = vec4(vec3(tbMask), 1);
// cogl_color_out = vec4(vec3(lrMask), 1);
// cogl_color_out = vec4(vec3(ffMask), 1);
// cogl_color_out = vec4(vec3(mask), 1);
}
`);
};
});