summaryrefslogtreecommitdiff
path: root/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/window_list.js
blob: 6ab0644f8404eca7df8c55c5d68270f725062c0a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import * as Main from 'resource:///org/gnome/shell/ui/main.js';

import { PaintSignals } from '../conveniences/paint_signals.js';
import { DummyPipeline } from '../conveniences/dummy_pipeline.js';


export const WindowListBlur = class WindowListBlur {
    constructor(connections, settings, effects_manager) {
        this.connections = connections;
        this.settings = settings;
        this.paint_signals = new PaintSignals(connections);
        this.effects_manager = effects_manager;
        this.pipelines = [];
    }

    enable() {
        this._log("blurring window list");

        // blur if window-list is found
        Main.layoutManager.uiGroup.get_children().forEach(
            child => this.try_blur(child)
        );

        // listen to new actors in `Main.layoutManager.uiGroup` and blur it if
        // if is window-list
        this.connections.connect(
            Main.layoutManager.uiGroup,
            'child-added',
            (_, child) => this.try_blur(child)
        );

        // connect to overview
        this.connections.connect(Main.overview, 'showing', _ => {
            this.hide();
        });
        this.connections.connect(Main.overview, 'hidden', _ => {
            this.show();
        });
    }

    try_blur(actor) {
        if (
            actor.constructor.name === "WindowList" &&
            actor.style !== "background:transparent;"
        ) {
            this._log("found window list to blur");

            const pipeline = new DummyPipeline(
                this.effects_manager, this.settings.window_list
            );
            pipeline.attach_effect_to_actor(actor);
            this.pipelines.push(pipeline);

            actor.set_style("background:transparent;");

            actor._windowList.get_children().forEach(
                window => this.style_window_button(window)
            );

            this.connections.connect(
                actor._windowList,
                'child-added',
                (_, window) => this.style_window_button(window)
            );

            this.connections.connect(
                actor,
                'destroy',
                _ => this.destroy_blur(pipeline, true)
            );


            // HACK
            //
            //`Shell.BlurEffect` does not repaint when shadows are under it. [1]
            //
            // This does not entirely fix this bug (shadows caused by windows
            // still cause artifacts), but it prevents the shadows of the panel
            // buttons to cause artifacts on the panel itself
            //
            // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857

            if (this.settings.HACKS_LEVEL === 1) {
                this._log("window list hack level 1");

                this.paint_signals.disconnect_all_for_actor(actor);
                this.paint_signals.connect(actor, pipeline.effect);
            } else {
                this.paint_signals.disconnect_all_for_actor(actor);
            }
        }
    }

    style_window_button(window) {
        window.get_child_at_index(0).set_style(
            "box-shadow:none; background-color:rgba(0,0,0,0.2); border-radius:5px;"
        );
    }

    // IMPORTANT: do never call this in a mutable `this.pipelines.forEach`
    destroy_blur(pipeline, actor_destroyed = false) {
        if (!actor_destroyed) {
            this.remove_style(pipeline.actor);
            this.paint_signals.disconnect_all_for_actor(pipeline.actor);
        }

        pipeline.destroy();

        let index = this.pipelines.indexOf(pipeline);
        if (index >= 0)
            this.pipelines.splice(pipeline, 1);
    }

    remove_style(actor) {
        if (
            actor.constructor.name === "WindowList" &&
            actor.style === "background:transparent;"
        ) {
            actor.style = null;
            actor._windowList.get_children().forEach(
                child => child.get_child_at_index(0).set_style(null)
            );
        }
    }

    hide() {
        this.pipelines.forEach(pipeline => pipeline.effect?.set_enabled(false));
    }

    show() {
        this.pipelines.forEach(pipeline => pipeline.effect?.set_enabled(true));
    }

    disable() {
        this._log("removing blur from window list");

        const immutable_pipelines_list = [...this.pipelines];
        immutable_pipelines_list.forEach(pipeline => this.destroy_blur(pipeline));

        this.pipelines = [];
        this.connections.disconnect_all();
    }

    _log(str) {
        if (this.settings.DEBUG)
            console.log(`[Blur my Shell > window list]  ${str}`);
    }
};