From 9d5be1660d8f74038ebed3d74fdbc809e43787ae Mon Sep 17 00:00:00 2001 From: Nippy Date: Fri, 9 Oct 2026 17:23:53 +0200 Subject: gnome fix --- .../blur-my-shell@aunetx/effects/refraction.js | 849 +++++++++++++++++++++ 1 file changed, 849 insertions(+) create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.js (limited to 'raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.js') diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.js new file mode 100644 index 0000000..27fdcc0 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/refraction.js @@ -0,0 +1,849 @@ +import GObject from 'gi://GObject'; +import GLib from 'gi://GLib'; + +import * as utils from '../conveniences/utils.js'; +import * as uniforms from '../conveniences/shader_uniforms.js'; +const St = await utils.import_in_shell_only('gi://St'); +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'refraction.glsl'; +const SHADER_SOURCE = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); +const CLIP_STABILIZE_EPSILON = 1.0; +const MAX_BLUR_RADIUS = 48.0; + +const DEFAULT_PARAMS = { + strength: 0.42, + blur_radius: 10, + edge_size: 22, + falloff: 2.4, + corner_radius: 22, + rim_width: 4.8, + rgb_fringing: 0.08, + gloss: 0.55, + webcam_gloss: false, + webcam_device: '', + tint: 0.18, + tint_color: [1.0, 1.0, 1.0, 1.0], + backdrop_zoom: 1.0, + shadow: 0.28, + texture_repeat: 0, + blur_direction: 0, + private_pass: 0, + chained_effect: null, + width: 0, + height: 0, + opacity_factor: 1.0, + clip: [0, 0, -1, -1] +}; + +const REFRACTION_EFFECT_META = { + GTypeName: "RefractionEffect", + Properties: { + 'strength': GObject.ParamSpec.double( + `strength`, + `Strength`, + `Refraction strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.42, + ), + 'edge_size': GObject.ParamSpec.double( + `edge_size`, + `Edge Size`, + `Refraction edge size`, + GObject.ParamFlags.READWRITE, + 1.0, 200.0, + 22.0, + ), + 'blur_radius': GObject.ParamSpec.double( + `blur_radius`, + `Blur Radius`, + `Internal glass blur radius`, + GObject.ParamFlags.READWRITE, + 0.0, MAX_BLUR_RADIUS, + 10.0, + ), + 'falloff': GObject.ParamSpec.double( + `falloff`, + `Falloff`, + `Refraction falloff`, + GObject.ParamFlags.READWRITE, + 0.25, 8.0, + 2.4, + ), + 'corner_radius': GObject.ParamSpec.double( + `corner_radius`, + `Corner Radius`, + `Refraction corner radius`, + GObject.ParamFlags.READWRITE, + 0.0, 200.0, + 22.0, + ), + 'rim_width': GObject.ParamSpec.double( + `rim_width`, + `Rim Width`, + `Refraction rim width`, + GObject.ParamFlags.READWRITE, + 1.0, 6.5, + 4.8, + ), + 'rgb_fringing': GObject.ParamSpec.double( + `rgb_fringing`, + `RGB Fringing`, + `Chromatic offset strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.08, + ), + 'gloss': GObject.ParamSpec.double( + `gloss`, + `Gloss`, + `Specular highlight strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.55, + ), + 'webcam_gloss': GObject.ParamSpec.boolean( + `webcam_gloss`, + `Deprecated Webcam Gloss`, + `Deprecated compatibility property`, + GObject.ParamFlags.READWRITE, + false, + ), + 'webcam_device': GObject.ParamSpec.string( + `webcam_device`, + `Deprecated Webcam Device`, + `Deprecated compatibility property`, + GObject.ParamFlags.READWRITE, + '', + ), + 'tint': GObject.ParamSpec.double( + `tint`, + `Tint`, + `Glass tint strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.18, + ), + 'tint_red': GObject.ParamSpec.double( + `tint_red`, + `Tint Red`, + `Glass tint color red`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + 'tint_green': GObject.ParamSpec.double( + `tint_green`, + `Tint Green`, + `Glass tint color green`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + 'tint_blue': GObject.ParamSpec.double( + `tint_blue`, + `Tint Blue`, + `Glass tint color blue`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + 'tint_alpha': GObject.ParamSpec.double( + `tint_alpha`, + `Tint Alpha`, + `Glass tint color alpha`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + 'backdrop_zoom': GObject.ParamSpec.double( + `backdrop_zoom`, + `Backdrop Zoom`, + `Zoom level of the refracted backdrop`, + GObject.ParamFlags.READWRITE, + 0.1, 4.0, + 1.0, + ), + 'shadow': GObject.ParamSpec.double( + `shadow`, + `Shadow`, + `Inner shadow strength`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.28, + ), + 'texture_repeat': GObject.ParamSpec.int( + `texture_repeat`, + `Texture Repeat`, + `Texture repeat behavior`, + GObject.ParamFlags.READWRITE, + 0, 1, + 0, + ), + 'blur_direction': GObject.ParamSpec.int( + `blur_direction`, + `Blur Direction`, + `Private Gaussian blur direction`, + GObject.ParamFlags.READWRITE, + 0, 1, + 0, + ), + 'private_pass': GObject.ParamSpec.int( + `private_pass`, + `Private Pass`, + `Private Gaussian blur pass`, + GObject.ParamFlags.READWRITE, + 0, 1, + 0, + ), + 'chained_effect': GObject.ParamSpec.object( + `chained_effect`, + `Chained Effect`, + `Private chained blur effect`, + GObject.ParamFlags.READWRITE, + GObject.Object, + ), + 'width': GObject.ParamSpec.double( + `width`, + `Width`, + `Width`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'height': GObject.ParamSpec.double( + `height`, + `Height`, + `Height`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + // See corner.js: this is backed by an array setter, but represented + // as a dummy property so pipeline parameter assignment can reach it. + 'clip': GObject.ParamSpec.double( + `clip`, + `Clip`, + `Clip`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'opacity_factor': GObject.ParamSpec.double( + `opacity_factor`, + `Opacity factor`, + `Opacity factor`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 1.0, + ), + } +}; + +const RefractionEffectClass = utils.IS_IN_PREFERENCES ? null : class RefractionEffect extends Clutter.ShaderEffect { + + constructor(params) { + const { + webcam_gloss: _webcam_gloss, + webcam_device: _webcam_device, + tint_color: _tint_color, + ...parent_params + } = params; + super({ ...parent_params }); + utils.initialize_shader_effect(this, SHADER_SOURCE); + + this._clip_x0 = null; + this._clip_y0 = null; + this._clip_width = null; + this._clip_height = null; + this._stable_clip_x0 = null; + this._stable_clip_y0 = null; + this._stable_clip_width = null; + this._stable_clip_height = null; + this._stabilize_clip_x = false; + this._stabilize_clip_y = false; + this._clip_settle_timeout_id = null; + + utils.setup_params(this, params); + + this._theme_context = St.ThemeContext.get_for_stage(global.stage); + this._theme_context.connectObject( + 'notify::scale-factor', + _ => this.update_scaled_uniforms(), + this + ); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get strength() { + return this._strength; + } + + set strength(value) { + if (this._strength !== value) { + this._strength = value; + + this.set_uniform_value('strength', parseFloat(this._strength - 1e-6)); + this.set_enabled(this.strength > 0.); + } + } + + get edge_size() { + return this._edge_size; + } + + set edge_size(value) { + if (this._edge_size !== value) { + this._edge_size = value; + + this.update_scaled_uniforms(); + + if (this.chained_effect) + this.chained_effect.edge_size = value; + } + } + + get blur_radius() { + return this._blur_radius; + } + + set blur_radius(value) { + if (this._blur_radius !== value) { + this._blur_radius = Math.min(value, MAX_BLUR_RADIUS); + + this.update_scaled_uniforms(); + + if (this.chained_effect) + this.chained_effect.blur_radius = this._blur_radius; + } + } + + get falloff() { + return this._falloff; + } + + set falloff(value) { + if (this._falloff !== value) { + this._falloff = value; + + this.set_uniform_value('falloff', parseFloat(this._falloff - 1e-6)); + + if (this.chained_effect) + this.chained_effect.falloff = value; + } + } + + get corner_radius() { + return this._corner_radius; + } + + set corner_radius(value) { + if (this._corner_radius !== value) { + this._corner_radius = value; + + this.update_scaled_uniforms(); + + if (this.chained_effect) + this.chained_effect.corner_radius = value; + } + } + + get rim_width() { + return this._rim_width; + } + + set rim_width(value) { + const rim_width = Math.max(1.0, Math.min(value, 6.5)); + if (this._rim_width !== rim_width) { + this._rim_width = rim_width; + + this.set_uniform_value('rim_width', parseFloat(this._rim_width - 1e-6)); + + if (this.chained_effect) + this.chained_effect.rim_width = rim_width; + } + } + + get rgb_fringing() { + return this._rgb_fringing; + } + + set rgb_fringing(value) { + if (this._rgb_fringing !== value) { + this._rgb_fringing = value; + + this.set_uniform_value('rgb_fringing', parseFloat(this._rgb_fringing - 1e-6)); + } + } + + get gloss() { + return this._gloss; + } + + set gloss(value) { + if (this._gloss !== value) { + this._gloss = value; + + this.set_uniform_value('gloss', parseFloat(this._gloss - 1e-6)); + } + } + + // Deprecated no-op compatibility properties for old saved pipelines. + get webcam_gloss() { + return this._webcam_gloss; + } + + set webcam_gloss(value) { + this._webcam_gloss = value; + } + + get webcam_device() { + return this._webcam_device; + } + + set webcam_device(value) { + this._webcam_device = value ?? ''; + } + + get tint() { + return this._tint; + } + + set tint(value) { + if (this._tint !== value) { + this._tint = value; + + this.set_uniform_value('tint', parseFloat(this._tint - 1e-6)); + } + } + + get tint_red() { + return this._tint_red; + } + + set tint_red(value) { + if (this._tint_red !== value) { + this._tint_red = value; + + this.set_uniform_value('tint_r', parseFloat(this._tint_red - 1e-6)); + } + } + + get tint_green() { + return this._tint_green; + } + + set tint_green(value) { + if (this._tint_green !== value) { + this._tint_green = value; + + this.set_uniform_value('tint_g', parseFloat(this._tint_green - 1e-6)); + } + } + + get tint_blue() { + return this._tint_blue; + } + + set tint_blue(value) { + if (this._tint_blue !== value) { + this._tint_blue = value; + + this.set_uniform_value('tint_b', parseFloat(this._tint_blue - 1e-6)); + } + } + + get tint_alpha() { + return this._tint_alpha; + } + + set tint_alpha(value) { + if (this._tint_alpha !== value) { + this._tint_alpha = value; + + this.set_uniform_value('tint_a', parseFloat(this._tint_alpha - 1e-6)); + } + } + + get tint_color() { + return [this.tint_red, this.tint_green, this.tint_blue, this.tint_alpha]; + } + + set tint_color(rgba) { + const [r, g, b, a] = rgba; + this.tint_red = r; + this.tint_green = g; + this.tint_blue = b; + this.tint_alpha = a ?? 1.0; + } + + get backdrop_zoom() { + return this._backdrop_zoom; + } + + set backdrop_zoom(value) { + if (this._backdrop_zoom !== value) { + this._backdrop_zoom = value; + + this.set_uniform_value('backdrop_zoom', parseFloat(this._backdrop_zoom - 1e-6)); + } + } + + get shadow() { + return this._shadow; + } + + set shadow(value) { + if (this._shadow !== value) { + this._shadow = value; + + this.set_uniform_value('shadow', parseFloat(this._shadow - 1e-6)); + } + } + + get texture_repeat() { + return this._texture_repeat; + } + + set texture_repeat(value) { + if (this._texture_repeat !== value) { + this._texture_repeat = value; + + this.set_uniform_value('texture_repeat', this._texture_repeat); + + if (this.chained_effect) + this.chained_effect.texture_repeat = value; + } + } + + get blur_direction() { + return this._blur_direction; + } + + set blur_direction(value) { + if (this._blur_direction !== value) { + this._blur_direction = value; + + this.set_uniform_value('blur_direction', this._blur_direction); + } + } + + get private_pass() { + return this._private_pass; + } + + set private_pass(value) { + if (this._private_pass !== value) { + this._private_pass = value; + + this.set_uniform_value('private_pass', this._private_pass); + if (this._private_pass === 1) + this.set_enabled(this.blur_radius > 0.01); + } + } + + get chained_effect() { + return this._chained_effect; + } + + set chained_effect(value) { + this._chained_effect = value; + } + + set(params) { + utils.setup_params(this, params); + } + + get width() { + return this._width; + } + + set width(value) { + if (this._width !== value) { + this._width = value; + + this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); + this.update_scaled_uniforms(); + + if (this.chained_effect) + this.chained_effect.width = value; + } + } + + get height() { + return this._height; + } + + set height(value) { + if (this._height !== value) { + this._height = value; + + this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); + this.update_scaled_uniforms(); + + if (this.chained_effect) + this.chained_effect.height = value; + } + } + + get clip() { + return [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height]; + } + + set clip(value) { + const previous_clip = this.clip; + [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height] = value; + + let shader_clip = this._stabilized_clip(previous_clip); + + this.set_uniform_value('clip_x0', parseFloat(shader_clip[0] - 1e-6)); + this.set_uniform_value('clip_y0', parseFloat(shader_clip[1] - 1e-6)); + this.set_uniform_value('clip_width', parseFloat(shader_clip[2] + 3.0 - 1e-6)); + this.set_uniform_value('clip_height', parseFloat(shader_clip[3] + 3.0 - 1e-6)); + this.update_scaled_uniforms(); + } + + get opacity_factor() { + return this._opacity_factor; + } + + set opacity_factor(value) { + if (this._opacity_factor !== value) { + this._opacity_factor = value; + + uniforms.set_uniform(this, 'opacity_factor', parseFloat(this._opacity_factor)); + + if (this.chained_effect) + this.chained_effect.opacity_factor = value; + } + } + + _stabilized_clip(previous_clip) { + if (this._clip_width < 0 || this._clip_height < 0) { + this._stable_clip_x0 = null; + this._stable_clip_y0 = null; + this._stable_clip_width = null; + this._stable_clip_height = null; + this._stabilize_clip_x = false; + this._stabilize_clip_y = false; + if (this._clip_settle_timeout_id) { + GLib.Source.remove(this._clip_settle_timeout_id); + this._clip_settle_timeout_id = null; + } + return [ + this._clip_x0, + this._clip_y0, + this._clip_width, + this._clip_height + ]; + } + + const [previous_x0, previous_y0, previous_width, previous_height] = previous_clip; + + [this._stable_clip_x0, this._stable_clip_width, this._stabilize_clip_x] = + this._stabilized_clip_axis( + this._clip_x0, + this._clip_width, + previous_x0, + previous_width, + this._stable_clip_x0, + this._stable_clip_width, + this._stabilize_clip_x + ); + [this._stable_clip_y0, this._stable_clip_height, this._stabilize_clip_y] = + this._stabilized_clip_axis( + this._clip_y0, + this._clip_height, + previous_y0, + previous_height, + this._stable_clip_y0, + this._stable_clip_height, + this._stabilize_clip_y + ); + + if (this._clip_settle_timeout_id) + GLib.Source.remove(this._clip_settle_timeout_id); + + if (!this._stabilize_clip_x && !this._stabilize_clip_y) { + this._clip_settle_timeout_id = null; + return [ + this._stable_clip_x0, + this._stable_clip_y0, + this._stable_clip_width, + this._stable_clip_height + ]; + } + + this._clip_settle_timeout_id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 220, () => { + this._stable_clip_x0 = this._clip_x0; + this._stable_clip_y0 = this._clip_y0; + this._stable_clip_width = this._clip_width; + this._stable_clip_height = this._clip_height; + this._stabilize_clip_x = false; + this._stabilize_clip_y = false; + this._clip_settle_timeout_id = null; + this.clip = [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height]; + this.queue_repaint(); + return GLib.SOURCE_REMOVE; + }); + + return [ + this._stable_clip_x0, + this._stable_clip_y0, + this._stable_clip_width, + this._stable_clip_height + ]; + } + + _stabilized_clip_axis( + start, + size, + previous_start, + previous_size, + stable_start, + stable_size, + stabilizing + ) { + const size_changed = + previous_size !== null && + previous_size >= 0 && + Math.abs(size - previous_size) > CLIP_STABILIZE_EPSILON; + + if (!stabilizing && !size_changed) + return [start, size, false]; + + const end = start + size; + const resolved_stable_start = stable_start ?? previous_start ?? start; + const resolved_stable_size = stable_size ?? previous_size ?? size; + const stable_end = resolved_stable_start + resolved_stable_size; + const resolved_start = Math.min(resolved_stable_start, start); + const resolved_end = Math.max(stable_end, end); + + return [resolved_start, resolved_end - resolved_start, true]; + } + + update_scaled_uniforms() { + const scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; + const rect_width = + this._stable_clip_width ?? (this._clip_width >= 0 ? this._clip_width : this.width); + const rect_height = + this._stable_clip_height ?? (this._clip_height >= 0 ? this._clip_height : this.height); + const max_edge = Math.max(1, Math.min(rect_width, rect_height) / 2); + const edge_size = Math.min(this.edge_size * scale_factor, max_edge); + const corner_radius = Math.min(this.corner_radius * scale_factor, max_edge); + + this.set_uniform_value('edge_size', parseFloat(edge_size - 1e-6)); + this.set_uniform_value('corner_radius', parseFloat(corner_radius - 1e-6)); + const blur_radius = Math.min(this.blur_radius, MAX_BLUR_RADIUS) * scale_factor; + this.set_uniform_value('blur_radius', parseFloat(blur_radius - 1e-6)); + if (this.private_pass === 1) + this.set_enabled(blur_radius > 0.01); + } + + vfunc_set_actor(actor) { + if (this.chained_effect) + this.chained_effect.get_actor()?.remove_effect(this.chained_effect); + + if (this._actor_connection_size_id) { + let old_actor = this.get_actor(); + old_actor?.disconnect(this._actor_connection_size_id); + } + if (this._actor_connection_clip_rect_id) { + let old_actor = this.get_actor(); + old_actor?.disconnect(this._actor_connection_clip_rect_id); + } + if (this._clip_settle_timeout_id) { + GLib.Source.remove(this._clip_settle_timeout_id); + this._clip_settle_timeout_id = null; + } + if (actor) { + this.width = actor.width; + this.height = actor.height; + this._actor_connection_size_id = actor.connect('notify::size', _ => { + this.width = actor.width; + this.height = actor.height; + }); + + this.clip = actor.has_clip ? actor.get_clip() : [0, 0, -10, -10]; + this._actor_connection_clip_rect_id = actor.connect('notify::clip-rect', _ => { + this.clip = actor.has_clip ? actor.get_clip() : [0, 0, -10, -10]; + }); + } + else { + this._actor_connection_size_id = null; + this._actor_connection_clip_rect_id = null; + this._stable_clip_x0 = null; + this._stable_clip_y0 = null; + this._stable_clip_width = null; + this._stable_clip_height = null; + this._stabilize_clip_x = false; + this._stabilize_clip_y = false; + } + + super.vfunc_set_actor(actor); + + if (this.private_pass === 0) { + if (!this.chained_effect) { + const chained_params = { + strength: this.strength, + blur_radius: this.blur_radius, + edge_size: this.edge_size, + falloff: this.falloff, + corner_radius: this.corner_radius, + rim_width: this.rim_width, + rgb_fringing: this.rgb_fringing, + gloss: this.gloss, + tint: this.tint, + shadow: this.shadow, + texture_repeat: this.texture_repeat, + width: this.width, + height: this.height, + clip: this.clip, + blur_direction: 1, + private_pass: 1, + opacity_factor: this._opacity_factor + }; + + this.chained_effect = new RefractionEffect(chained_params); + } + + if (actor !== null) + actor.add_effect(this.chained_effect); + } + } + + vfunc_paint_target(paint_node, paint_context) { + uniforms.upload_uniforms(this); + this.set_uniform_value('blur_direction', this.blur_direction); + this.set_uniform_value('private_pass', this.private_pass); + + super.vfunc_paint_target(paint_node, paint_context); + } + + vfunc_dispose() { + if (this._clip_settle_timeout_id) { + GLib.Source.remove(this._clip_settle_timeout_id); + this._clip_settle_timeout_id = null; + } + + if (this.chained_effect) { + this.chained_effect.get_actor()?.remove_effect(this.chained_effect); + this.chained_effect = null; + } + + this._theme_context?.disconnectObject(this); + this._theme_context = null; + + if (super.vfunc_dispose) + super.vfunc_dispose(); + } +}; + +export const RefractionEffect = utils.IS_IN_PREFERENCES + ? { default_params: DEFAULT_PARAMS } + : utils.register_shader_effect(REFRACTION_EFFECT_META, RefractionEffectClass, SHADER_SOURCE); -- cgit v1.3