2025-05-09 09:48:24 +02:00

155 lines
4.4 KiB
JavaScript

import Clutter from 'gi://Clutter';
import Meta from 'gi://Meta';
import { Extension, gettext as _ }
from 'resource:///org/gnome/shell/extensions/extension.js';
const _grab_moving_operations = [
Meta.GrabOp.MOVING,
Meta.GrabOp.KEYBOARD_MOVING,
Meta.GrabOp.MOVING_UNCONSTRAINED
];
const _grab_resizing_operations = [
Meta.GrabOp.RESIZING_NW,
Meta.GrabOp.RESIZING_N,
Meta.GrabOp.RESIZING_NE,
Meta.GrabOp.RESIZING_E,
Meta.GrabOp.RESIZING_SW,
Meta.GrabOp.RESIZING_S,
Meta.GrabOp.RESIZING_SE,
Meta.GrabOp.RESIZING_W,
Meta.GrabOp.KEYBOARD_RESIZING_UNKNOWN,
Meta.GrabOp.KEYBOARD_RESIZING_NW,
Meta.GrabOp.KEYBOARD_RESIZING_N,
Meta.GrabOp.KEYBOARD_RESIZING_NE,
Meta.GrabOp.KEYBOARD_RESIZING_E,
Meta.GrabOp.KEYBOARD_RESIZING_SW,
Meta.GrabOp.KEYBOARD_RESIZING_S,
Meta.GrabOp.KEYBOARD_RESIZING_SE,
Meta.GrabOp.KEYBOARD_RESIZING_W
];
export default class TransparentWindowMoving extends Extension {
init_grab_operations() {
this._allowed_grab_operations = [];
if (this._settings.get_boolean('transparent-on-moving')) {
this._allowed_grab_operations.push(..._grab_moving_operations);
}
if (this._settings.get_boolean('transparent-on-resizing')) {
this._allowed_grab_operations.push(..._grab_resizing_operations);
}
}
is_grab_operation_allowed(grab_op) {
return this._allowed_grab_operations.indexOf(grab_op) > -1;
}
set_opacity(window_surfaces, target_opacity, on_complete) {
const complete_func = function() {
if (on_complete) {
on_complete();
}
};
const transition_time = this._settings.get_double('transition-time');
if (transition_time < 0.001) {
window_surfaces.forEach(surface => {
surface.opacity = target_opacity;
});
complete_func();
} else {
window_surfaces.forEach(surface => {
surface.ease({
duration: transition_time * 1000,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
opacity: target_opacity,
onComplete: complete_func
});
});
}
}
get_window_surfaces(meta_window) {
const window_actor = meta_window.get_compositor_private();
const surfaces = this.find_meta_surface_actors(window_actor);
if (surfaces.length > 0) {
return surfaces;
}
return [window_actor];
}
find_meta_surface_actors(meta_actor) {
if (meta_actor.constructor.name.indexOf('MetaSurfaceActor') > -1) {
return [meta_actor];
}
const surfaces = [];
for (const child of meta_actor.get_children()) {
const result = this.find_meta_surface_actors(child);
if (result.length > 0) {
surfaces.push(...result);
}
}
return surfaces;
}
window_grab_begin(meta_display, meta_window, meta_grab_op, gpointer) {
if (!meta_window || !this.is_grab_operation_allowed(meta_grab_op)) {
return;
}
const window_surfaces = this.get_window_surfaces(meta_window);
const pid = meta_window.get_pid();
if (!this._window_opacity[pid]) {
this._window_opacity[pid] = window_surfaces[0].opacity;
}
const opacity_value = this._settings.get_int('window-opacity');
this.set_opacity(window_surfaces, opacity_value);
}
window_grab_end(meta_display, meta_window, meta_grab_op, gpointer) {
if (!meta_window || !this.is_grab_operation_allowed(meta_grab_op)) {
return;
}
const window_surfaces = this.get_window_surfaces(meta_window);
const pid = meta_window.get_pid();
const complete_func = function() {
delete this._window_opacity[pid];
};
this.set_opacity(window_surfaces, this._window_opacity[pid], complete_func.bind(this));
}
enable() {
this._settings = this.getSettings();
this.init_grab_operations();
this._window_opacity = {};
this._on_window_grab_begin = global.display.connect('grab-op-begin', this.window_grab_begin.bind(this));
this._on_window_grab_end = global.display.connect('grab-op-end', this.window_grab_end.bind(this));
this._on_move_changed = this._settings.connect('changed::transparent-on-moving', this.init_grab_operations.bind(this));
this._on_resize_changed = this._settings.connect('changed::transparent-on-resizing', this.init_grab_operations.bind(this));
}
disable() {
global.display.disconnect(this._on_window_grab_begin);
global.display.disconnect(this._on_window_grab_end);
this._settings.disconnect(this._on_move_changed);
this._settings.disconnect(this._on_resize_changed);
delete this._window_opacity;
delete this._allowed_grab_operations;
delete this._settings;
delete this._on_window_grab_begin;
delete this._on_window_grab_end;
delete this._on_move_changed;
delete this._on_resize_changed;
}
}