diff options
Diffstat (limited to 'raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js')
| -rw-r--r-- | raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js | 187 |
1 files changed, 165 insertions, 22 deletions
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js index 84b1d7a..f52e26f 100644 --- a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/conveniences/pipeline.js @@ -1,6 +1,9 @@ import St from 'gi://St'; +import Meta from 'gi://Meta'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as Background from 'resource:///org/gnome/shell/ui/background.js'; +import * as uniforms from './shader_uniforms.js'; +import * as utils from './utils.js'; /// A `Pipeline` object is a handy way to manage the effects attached to an actor. It only manages /// one actor at a time (so blurring multiple widgets will need multiple `Pipeline`), and is @@ -18,10 +21,11 @@ import * as Background from 'resource:///org/gnome/shell/ui/background.js'; /// - `'pipeline_id'::effect-'id'-key-updated`, handing the key that was changed and its new value /// - `'pipeline_id'::effect-'id'-key-added`, handing the key that was added and its value export const Pipeline = class Pipeline { - constructor(effects_manager, pipelines_manager, pipeline_id, actor = null) { + constructor(effects_manager, pipelines_manager, pipeline_id, actor = null, options = {}) { this.effects_manager = effects_manager; this.pipelines_manager = pipelines_manager; this.effects = []; + this.effect_overrides = options.effect_overrides ?? {}; this.set_pipeline_id(pipeline_id); this.attach_pipeline_to_actor(actor); } @@ -41,19 +45,18 @@ export const Pipeline = class Pipeline { ) { let monitor = Main.layoutManager.monitors[monitor_index]; + this.remove_pipeline_from_actor(); + // create the new actor this.actor = new St.Widget({ name: widget_name, x: use_absolute_position ? monitor.x : 0, - y: .5 + (use_absolute_position ? monitor.y : 0), // add 1 to correct z-position + y: utils.subpixel_stage_offset() + (use_absolute_position ? monitor.y : 0), z_position: 1, // seems to fix the multi-monitor glitch width: monitor.width, height: monitor.height }); - // remove the effects, wether or not we attach the pipeline to the actor: if they are fired - // while the actor has changed, this could go bad - this.remove_all_effects(); if (this.pipeline_id) this.attach_pipeline_to_actor(this.actor); @@ -64,6 +67,17 @@ export const Pipeline = class Pipeline { }); bg_manager._bms_pipeline = this; + // 'controlPosition: false' skips BackgroundManager's default layout pass, which also diables + // sibling re-ordering. + // Without it, new actors render on top while loading, causing a solid color flash through + // on the surface. + this.child_added_id = this.actor.connect( + 'child-added', (container, child) => { + if (child instanceof Meta.BackgroundActor) + container.set_child_below_sibling(child, null); + } + ); + background_managers.push(bg_manager); background_group.insert_child_at_index(this.actor, 0); @@ -104,14 +118,14 @@ export const Pipeline = class Pipeline { /// Attach a Pipeline object with `pipeline_id` already set to an actor. attach_pipeline_to_actor(actor) { - // set the actor - if (actor) - this.actor = actor; - else { + if (!actor) { this.remove_pipeline_from_actor(); return; } + this.disconnect_actor_destroy(); + this.actor = actor; + // attach the pipeline let pipeline = this.pipelines_manager.pipelines[this.pipeline_id]; if (!pipeline) { @@ -134,10 +148,23 @@ export const Pipeline = class Pipeline { remove_pipeline_from_actor() { this.remove_all_effects(); - if (this.actor && this.actor_destroy_id) + this.disconnect_actor_destroy(); + this.disconnect_child_added(); + this.actor = null; + } + + disconnect_actor_destroy() { + if (this.actor && this.actor_destroy_id) { this.actor.disconnect(this.actor_destroy_id); + } this.actor_destroy_id = null; - this.actor = null; + } + + disconnect_child_added() { + if (this.actor && this.child_added_id) { + this.actor.disconnect(this.child_added_id); + } + this.child_added_id = null; } /// Update the effects from the given pipeline object, the hard way. @@ -147,7 +174,9 @@ export const Pipeline = class Pipeline { // build the new effects to be added pipeline.effects.forEach(effect => { - if ('new_' + effect.type + '_effect' in this.effects_manager) + if (effect.type === 'pixelize') + this.build_pixelize_effect(effect); + else if ('new_' + effect.type + '_effect' in this.effects_manager) this.build_effect(effect); else this._warn(`could not add effect to actor, effect "${effect.type}" not found`); @@ -156,32 +185,143 @@ export const Pipeline = class Pipeline { // add the effects to the actor if (this.actor) - this.effects.forEach(effect => this.actor.add_effect(effect)); + this.effects.forEach(effect => { + this.actor.add_effect(effect); + uniforms.mark_dirty(effect); + }); else this._warn(`could not add effect to actor, actor does not exist anymore`); } + build_pixelize_effect(effect_infos) { + const effect_params = this.get_effect_params(effect_infos); + const effect_overrides = this.get_effect_overrides(effect_infos.type, effect_params); + const params = { + ...effect_params, + ...effect_overrides, + }; + + const downscale = this.effects_manager.new_downscale_effect({ + divider: params.factor, + downsampling_mode: params.downsampling_mode, + opacity_factor: params.opacity_factor, + }); + const upscale = this.effects_manager.new_upscale_effect({ + factor: params.factor, + opacity_factor: params.opacity_factor, + }); + + this.setup_effect(downscale, effect_infos, effect_params, 'downscale'); + this.setup_effect(upscale, effect_infos, effect_params, 'upscale'); + } + /// Given an `effect_infos` object containing the effect type, id and params, build an effect /// and append it to the effects list build_effect(effect_infos) { - let effect = this.effects_manager['new_' + effect_infos.type + '_effect'](effect_infos.params); + const effect_params = this.get_effect_params(effect_infos); + const effect_overrides = this.get_effect_overrides(effect_infos.type, effect_params); + let effect = this.effects_manager['new_' + effect_infos.type + '_effect']({ + ...effect_params, + ...effect_overrides, + }); + this.setup_effect(effect, effect_infos, effect_params); + } + + setup_effect(effect, effect_infos, effect_params, pixelize_role = null) { + effect._bms_effect_type = effect_infos.type; + effect._bms_effect_id = effect_infos.id; + effect._bms_effect_params = effect_params; + effect._bms_pixelize_role = pixelize_role; this.effects.push(effect); // connect to settings changes effect._effect_key_removed_id = this.pipelines_manager.connect( - this.pipeline_id + '::effect-' + effect_infos.id + '-key-removed', - (_, key) => effect[key] = effect.constructor.default_params[key] + this.pipeline_id + '::effect-' + effect_infos.id + '-key-removed', (_, key) => { + const default_value = this.get_effect_default_param(effect, key); + effect._bms_effect_params[key] = default_value; + if (!this.apply_effect_override(effect, key)) + this.set_effect_param(effect, key, default_value); + } ); effect._effect_key_updated_id = this.pipelines_manager.connect( - this.pipeline_id + '::effect-' + effect_infos.id + '-key-updated', - (_, key, value) => effect[key] = value + this.pipeline_id + '::effect-' + effect_infos.id + '-key-updated', (_, key, value) => { + effect._bms_effect_params[key] = value; + if (!this.apply_effect_override(effect, key)) + this.set_effect_param(effect, key, value); + } ); effect._effect_key_added_id = this.pipelines_manager.connect( - this.pipeline_id + '::effect-' + effect_infos.id + '-key-added', - (_, key, value) => effect[key] = value + this.pipeline_id + '::effect-' + effect_infos.id + '-key-added', (_, key, value) => { + effect._bms_effect_params[key] = value; + if (!this.apply_effect_override(effect, key)) + this.set_effect_param(effect, key, value); + } ); } + get_effect_params(effect_infos) { + const effect_class = this.effects_manager.SUPPORTED_EFFECTS[effect_infos.type]?.class; + return { + ...(effect_class?.default_params ?? {}), + ...(effect_infos.params ?? {}), + }; + } + + get_effect_default_param(effect, key) { + return this.effects_manager.SUPPORTED_EFFECTS[effect._bms_effect_type] + ?.class + ?.default_params + ?.[key]; + } + + get_effect_overrides(effect_type, effect_params = {}) { + const overrides = this.effect_overrides[effect_type] ?? {}; + return typeof overrides === 'function' ? overrides(effect_params) : overrides; + } + + apply_effect_override(effect, key) { + const overrides = this.get_effect_overrides(effect._bms_effect_type, effect._bms_effect_params); + if (!(key in overrides)) + return false; + + this.set_effect_param(effect, key, overrides[key]); + return true; + } + + apply_effect_overrides(effect_type = null) { + this.effects.forEach(effect => { + if (effect_type && effect._bms_effect_type !== effect_type) + return; + + const overrides = this.get_effect_overrides(effect._bms_effect_type, effect._bms_effect_params); + Object.keys(overrides).forEach(key => this.set_effect_param(effect, key, overrides[key])); + }); + } + + set_effect_param(effect, key, value) { + if (effect._bms_effect_type !== 'pixelize') { + effect[key] = value; + return; + } + + if (key === 'factor') { + if (effect._bms_pixelize_role === 'downscale') + effect.divider = value; + else if (effect._bms_pixelize_role === 'upscale') + effect.factor = value; + return; + } + + if (key === 'downsampling_mode') { + if (effect._bms_pixelize_role === 'downscale') + effect.downsampling_mode = value; + return; + } + + if (key in effect) + effect[key] = value; + } + /// Remove every effect from the actor it is attached to. Please note that they are not /// destroyed, but rather stored (thanks to the `EffectManager` class) to be reused later. remove_all_effects() { @@ -197,6 +337,10 @@ export const Pipeline = class Pipeline { delete effect._effect_key_removed_id; delete effect._effect_key_updated_id; delete effect._effect_key_added_id; + delete effect._bms_effect_type; + delete effect._bms_effect_id; + delete effect._bms_effect_params; + delete effect._bms_pixelize_role; }); this.effects = []; } @@ -211,7 +355,6 @@ export const Pipeline = class Pipeline { /// Resets the `Pipeline` object to a sane state, removing every effect and signal. /// Note: exposed to public API. destroy() { - this.remove_all_effects(); this.remove_connections(); this.remove_pipeline_from_actor(); this.pipeline_id = null; @@ -220,4 +363,4 @@ export const Pipeline = class Pipeline { _warn(str) { console.warn(`[Blur my Shell > pipeline] ${str}`); } -};
\ No newline at end of file +}; |