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
|
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
export const IS_IN_PREFERENCES = typeof global === 'undefined';
// Taken from https://github.com/Schneegans/Burn-My-Windows/blob/main/src/utils.js
// This method can be used to import a module in the GNOME Shell process only. This
// is useful if you want to use a module in extension.js, but not in the preferences
// process. This method returns null if it is called in the preferences process.
export async function import_in_shell_only(module) {
if (IS_IN_PREFERENCES)
return null;
try {
const imported = await import(module);
return imported.default ?? imported;
} catch (e) {
return null;
}
}
const Clutter = await import_in_shell_only('gi://Clutter');
const Cogl = await import_in_shell_only('gi://Cogl');
const USES_SHADER_SNIPPET_API =
typeof Clutter?.ShaderEffect?.new_with_snippet === 'function';
export function is_usable_blur_module(ns) {
if (!ns)
return false;
try {
const { BlurEffect } = ns;
if (typeof BlurEffect !== 'function' || !BlurEffect.$gtype)
return false;
GObject.type_name(BlurEffect.$gtype);
return true;
} catch (e) {
return false;
}
}
// In use for the effects, to prevent boilerplate code
export function setup_params(outer_this, params) {
// setup each parameter, either with the given or the default value
for (const params_name in outer_this.constructor.default_params) {
outer_this["_" + params_name] = null;
outer_this[params_name] = params_name in params ?
params[params_name] :
outer_this.constructor.default_params[params_name];
}
};
export const get_shader_source = (Shell, shader_filename, self_uri) => {
if (!Shell)
return;
const shader_path = GLib.filename_from_uri(
GLib.uri_resolve_relative(self_uri, shader_filename, GLib.UriFlags.NONE)
)[0];
try {
return Shell.get_file_contents_utf8_sync(shader_path);
} catch (e) {
console.warn(`[Blur my Shell > effect] error loading shader from ${shader_path}: ${e}`);
return null;
}
};
export function subpixel_stage_offset() {
return USES_SHADER_SNIPPET_API ? 0 : 0.5;
}
export function static_blur_clip_inset() {
return USES_SHADER_SNIPPET_API ? 1 : 0;
}
export function register_shader_effect(meta, effect_class, source) {
if (USES_SHADER_SNIPPET_API) {
Object.defineProperty(effect_class.prototype, 'vfunc_get_static_snippet', {
value() {
return create_fragment_shader_snippet(source);
},
});
}
return GObject.registerClass(meta, effect_class);
}
function split_fragment_shader(source) {
const main_index = source.search(/void\s+main\s*(?:\(\s*(?:void)?\s*\))?\s*\{/);
if (main_index < 0)
return null;
const declarations = source.slice(0, main_index).trim();
const brace_index = source.indexOf('{', main_index);
if (brace_index < 0)
return null;
let depth = 0;
for (let i = brace_index; i < source.length; i++) {
if (source[i] === '{')
depth++;
else if (source[i] === '}') {
depth--;
if (depth === 0) {
return {
declarations,
body: source.slice(brace_index + 1, i).trim(),
};
}
}
}
return null;
}
function create_fragment_shader_snippet(source) {
if (!Cogl || !source)
return null;
const parts = split_fragment_shader(source);
if (!parts) {
console.warn('[Blur my Shell > effect] could not split shader source');
return null;
}
try {
const snippet = Cogl.Snippet.new(
Cogl.SnippetHook.FRAGMENT,
parts.declarations,
null
);
snippet.set_replace(parts.body);
return snippet;
} catch (e) {
console.warn(`[Blur my Shell > effect] could not create shader snippet: ${e}`);
return null;
}
}
export function initialize_shader_effect(effect, source) {
if (!source || !effect || USES_SHADER_SNIPPET_API)
return;
try {
effect.set_shader_source(source);
} catch (e) {
console.warn(`[Blur my Shell > effect] set_shader_source failed: ${e}`);
}
}
|