252 lines
7.5 KiB
JavaScript
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;
|
|
} |