summaryrefslogtreecommitdiff
path: root/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/components/popup/surface_fade.js
blob: 2a0b9a59dc949b98d2f569f0726e8e163935c670 (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
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import { has_style_class } from './targets.js';

export const PopupBlurSurfaceFade = class PopupBlurSurfaceFade {
    constructor(actor, target, root_actor, parent) {
        this.actor = actor;
        this.target = target;
        this.root_actor = root_actor;
        this.parent = parent;
    }

    get_opacity() {
        let opacity = 255;
        const visited = new WeakSet();
        let actor = this.target;

        while (actor && actor !== this.parent) {
            opacity = this.apply_actor_opacity(opacity, actor, visited);
            actor = actor.get_parent();
        }

        opacity = this.apply_actor_opacity(opacity, this.root_actor, visited);

        [
            this.target,
            this.root_actor,
        ].forEach(actor => {
            const paint_opacity = this.get_paint_opacity(actor);
            if (paint_opacity !== null)
                opacity = Math.min(opacity, paint_opacity);
        });

        if (this.is_notification_banner()) {
            opacity = Math.round(opacity * this.get_banner_position_alpha());
        }

        return opacity;
    }

    is_notification_banner() {
        if (has_style_class(this.target, 'notification-banner'))
            return true;
        if (this.root_actor?.name === 'notification-container')
            return true;
        let a = this.target;
        while (a && a !== this.parent) {
            if (has_style_class(a, 'notification-banner'))
                return true;
            a = a.get_parent();
        }
        return false;
    }

    get_banner_position_alpha() {
        try {
            const [, stage_y] = this.target.get_transformed_position();

            if (!Main.panel)
                return 1;

            const monitor = Main.layoutManager.findMonitorForActor(Main.panel)
                ?? Main.layoutManager.primaryMonitor;

            if (!monitor)
                return 1;

            const [, panel_y] = Main.panel.get_transformed_position();
            const panel_width = Main.panel.width || Main.panel.get_width() || 0;
            const panel_height = Main.panel.height || Main.panel.get_height() || 36;

            // Must be a horizontal panel anchored at the monitor's top edge
            const is_horizontal = panel_width > panel_height;
            const is_at_monitor_top = Math.abs(panel_y - monitor.y) <= 5;

            if (!is_horizontal || !is_at_monitor_top)
                return 1;

            const panel_bottom = panel_y + panel_height;
            const threshold = panel_bottom + 5;

            if (stage_y <= panel_y)
                return 0;
            if (stage_y >= threshold)
                return 1;

            return Math.clamp((stage_y - panel_y) / (threshold - panel_y), 0, 1);
        } catch (e) {
            return 1;
        }
    }

    set_opacity(opacity) {
        this.actor.opacity = opacity;
    }

    apply_actor_opacity(opacity, actor, visited) {
        if (!actor || visited.has(actor))
            return opacity;

        visited.add(actor);

        let visible = actor.visible;
        let mapped = actor.mapped;
        if (!visible && this.is_keyboard_actor(actor)) {
            const parent = actor.get_parent();
            visible = parent?.visible && parent?.mapped;
            mapped = parent?.mapped;
        }
        if (!visible || !mapped)
            return 0;

        return Math.round(opacity * (actor.opacity ?? 255) / 255);
    }

    is_keyboard_actor(actor) {
        return (
            has_style_class(actor, 'bms-keyboard-surface')
        );
    }

    get_paint_opacity(actor) {
        if (this.is_keyboard_actor(actor) && (!actor.visible || !actor.mapped)) {
            const parent = actor.get_parent();
            if (parent?.visible && parent?.mapped)
                return null;
        }
        if (actor?.get_paint_opacity)
            return actor.get_paint_opacity();

        return null;
    }
};