dotfiles/.local/share/gnome-shell/extensions/dynamic-panel-transparency@.../intellifade.js

252 lines
7.5 KiB
JavaScript

/* exported init, cleanup, asyncCheck, syncCheck, forceAsyncCheck, forceSyncCheck, get_current_maximized_window */
const GLib = imports.gi.GLib;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Settings = Me.imports.settings;
const Util = Me.imports.util;
const Transitions = Me.imports.transitions;
const Theming = Me.imports.theming;
/* Determines whether to continue the async loop checks. */
let continueCheck = false;
/* Variable for current detected maximized window... */
let maximized_window = null;
/* Run the next change regardless of the whether it is the same as the current status. */
// TODO: Find a nicer way to override optimization code.
let override_optimization = false;
/* Current ID of the async loop (0 if no loop is running) */
let timeoutId = 0;
/* How often the asynchronous loop should run in milliseconds... */
const ASYNC_UPDATE_FREQUENCY = 200; // ms
function init() {
this._wm_tracker = Shell.WindowTracker.get_default();
_updateBounds();
}
function cleanup() {
this._wm_tracker = null;
if (timeoutId > 0) {
Mainloop.source_remove(timeoutId);
}
}
function forceSyncCheck() {
override_optimization = true;
syncCheck();
}
function syncCheck() {
/* Prevent any asynchronous checks from occuring in the loop. */
continueCheck = false;
/* Stop the asynchronous loop... */
if (timeoutId > 0)
Mainloop.source_remove(timeoutId);
/* Remove the old loop ID */
timeoutId = 0;
/* Update bounds when a check is done in sync. */
_updateBounds();
/* Run a check. */
_check();
}
function forceAsyncCheck() {
override_optimization = true;
asyncCheck();
}
function asyncCheck() {
if (timeoutId <= 0) {
_check();
timeoutId = Mainloop.timeout_add(ASYNC_UPDATE_FREQUENCY, (function() {
_check();
if (continueCheck) {
continueCheck = false;
return GLib.SOURCE_CONTINUE;
} else {
timeoutId = 0;
return GLib.SOURCE_REMOVE;
}
}).bind(this));
} else {
continueCheck = true;
}
}
function _updateBounds() {
const panel = Main.panel;
this.panel_bounds = {
x: panel.get_x(),
y: panel.get_y(),
height: panel.get_height(),
width: panel.get_width(),
is_top: true
};
this.scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let [, pivot_y] = Main.layoutManager.panelBox.get_pivot_point();
// Adjust for bottom panel.
if (pivot_y < 0) {
this.panel_bounds.y = -pivot_y;
this.panel_bounds.is_top = false;
}
}
/* Main extension logic. Modified to fit Gnome Shell 3.26 design patterns. */
// TODO: Cleanup use of variable flags.
function _check() {
if (Main.overview._shown) {
return;
}
let workspace = null;
const manager = global.screen || global.workspace_manager;
if (manager) {
workspace = manager.get_active_workspace();
} else {
log('[Dynamic Panel Transparency] Error could not get active workspace.');
}
let windows = workspace.list_windows();
windows = global.display.sort_windows_by_stacking(windows);
let focused_window = global.display.get_focus_window();
maximized_window = null;
let add_transparency = true;
let force_transparency = false;
/* Handle desktop icons (they're a window too) */
if (focused_window && focused_window.get_window_type() === Meta.WindowType.DESKTOP) {
add_transparency = true;
maximized_window = focused_window;
} else {
// TODO: Always negative? Is pivot negative?
for (let i = windows.length - 1; i >= 0; i--) {
let current_window = windows[i];
if (!current_window.showing_on_its_workspace() || !current_window.is_on_primary_monitor()) {
continue;
}
/* Make sure the window is on the correct monitor, isn't minimized, isn't supposed to be excluded, and is actually maximized. */
if (!Util.is_valid(current_window)) {
continue;
}
if (current_window.maximized_vertically) {
/* Make sure the top-most window is selected */
if (maximized_window === null && !force_transparency) {
maximized_window = current_window;
}
add_transparency = false;
break;
}
let frame = current_window.get_frame_rect();
if (Main.layoutManager._rightPanelBarrier) {
let overlap = this.panel_bounds.x < frame.x + frame.width &&
this.panel_bounds.x + this.panel_bounds.width > frame.x &&
this.panel_bounds.y < frame.y + frame.height &&
this.panel_bounds.height + this.panel_bounds.y > frame.y;
if (overlap) {
force_transparency = true;
maximized_window = null;
break;
}
}
if (Settings.transition_when_windows_touch_panel()) {
let touching_panel = false;
if (this.panel_bounds.is_top) {
touching_panel = frame.y >= (this.panel_bounds.y + this.panel_bounds.height) &&
frame.y <= (this.panel_bounds.y + this.panel_bounds.height);
} else {
touching_panel = (frame.y + frame.height) >= (this.panel_bounds.y) &&
(frame.y + frame.height) <= (this.panel_bounds.y);
}
if (!force_transparency && touching_panel) {
add_transparency = false;
if (maximized_window === null && !force_transparency) {
maximized_window = current_window;
}
break;
}
}
}
}
if (force_transparency) {
Transitions.fade_out();
force_transparency = false;
/* Only change if the transparency isn't already correct or if override_optimization has been called */
} else if (Transitions.get_transparency_status().is_blank()) {
if (add_transparency) {
Transitions.minimum_fade_in();
} else {
Transitions.fade_in();
}
} else if (override_optimization || (Transitions.get_transparency_status().is_transparent() !== add_transparency)) {
override_optimization = false;
if (add_transparency) {
Transitions.fade_out();
} else {
Transitions.fade_in();
}
}
/* Reset text coloring. */
if (Settings.get_enable_text_color() && (Settings.get_enable_maximized_text_color() || Settings.get_enable_overview_text_color())) {
if (!add_transparency && Settings.get_enable_maximized_text_color()) {
Theming.remove_text_color();
Theming.set_text_color('maximized');
} else {
Theming.remove_text_color('maximized');
Theming.set_text_color();
}
}
}
/**
* Returns the current visible maximized window as understood by the events' logic.
* The maximized window is not necessarily the highest window in the z-order.
*
* @returns {Object} The current visible maximized window.
*/
function get_current_maximized_window() {
return maximized_window;
}