dot/.local/share/gnome-shell/extensions/TaskBar@c0ldplasma/windows.js

186 lines
5.9 KiB
JavaScript

// GNOME Shell Extension TaskBar 2020
// Copyright (C) 2013-2018 zpydr
// Copyright (C) 2020 c0ldplasma
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
const Lang = imports.lang;
function Windows(callBackThis, callbackWindowsListChanged, callbackWindowChanged) {
this.init(callBackThis, callbackWindowsListChanged, callbackWindowChanged);
}
Windows.prototype = {
workspace: null,
windowsList: [],
callBackThis: null,
callbackWindowsListChanged: null,
callbackWindowChanged: null,
workspaceSwitchSignal: null,
windowAddedSignal: null,
windowRemovedSignal: null,
windowsSignals: [],
init: function(callBackThis, callbackWindowsListChanged, callbackWindowChanged) {
//Set User Callback
this.callBackThis = callBackThis;
this.callbackWindowsListChanged = callbackWindowsListChanged;
this.callbackWindowChanged = callbackWindowChanged;
//Init WindowsList
this.workspaceSignals = new Map();
this.buildWindowsList();
this.onWorkspaceChanged();
//Add window manager signals
this.workspaceSwitchSignal = global.workspace_manager.connect('workspace-switched', Lang.bind(this, this.buildWindowsList));
this.nWorkspacesSignal = global.workspace_manager.connect('notify::n-workspaces', Lang.bind(this, this.onWorkspaceChanged));
},
destruct: function() {
//Remove window manager signals
let numWorkspaces = global.workspace_manager.n_workspaces;
for (let i = 0; i < numWorkspaces; i++) {
let workspace = global.workspace_manager.get_workspace_by_index(i);
let signals = this.workspaceSignals.get(workspace);
this.workspaceSignals.delete(workspace);
workspace.disconnect(signals.windowAddedId);
workspace.disconnect(signals.windowRemovedId);
}
//Clean windows list
this.cleanWindowsList();
},
onWorkspaceChanged: function() {
let numWorkspaces = global.workspace_manager.n_workspaces;
for (let i = 0; i < numWorkspaces; i++) {
let workspace = global.workspace_manager.get_workspace_by_index(i);
if (this.workspaceSignals.has(workspace))
continue;
let signals = {
windowAddedId: 0,
windowRemovedId: 0
};
signals.windowAddedId = workspace.connect_after('window-added', Lang.bind(this, this.buildWindowsList));
signals.windowRemovedId = workspace.connect('window-removed', Lang.bind(this, this.buildWindowsList));
this.workspaceSignals.set(workspace, signals);
}
},
buildWindowsList: function() {
//Clean windows list
this.cleanWindowsList();
//Build windows list
let totalWorkspaces = global.workspace_manager.n_workspaces;
for (let i = 0; i < totalWorkspaces; i++) {
let activeWorkspace = global.workspace_manager.get_workspace_by_index(i);
activeWorkspace.list_windows().sort(this.sortWindowsCompareFunction).forEach(
function(window) {
this.addWindowInList(window);
},
this
);
}
//Call User Callback
this.callbackWindowsListChanged.call(this.callBackThis, this.windowsList, 0, null);
},
sortWindowsCompareFunction: function(windowA, windowB) {
return windowA.get_stable_sequence() > windowB.get_stable_sequence();
},
onWindowChanged: function(window, object, type) {
if (type === 0) { //Focus changed
if (window.appears_focused) {
this.callbackWindowChanged.call(this.callBackThis, window, 0);
}
} else if (type === 1) { //Title changed
this.callbackWindowChanged.call(this.callBackThis, window, 1);
} else if (type === 2) { //Minimized
this.callbackWindowChanged.call(this.callBackThis, window, 2);
} else if (type === 3) { //Icon
this.callbackWindowChanged.call(this.callBackThis, window, 3);
} else if (type === 4) { //Icon
this.callbackWindowChanged.call(this.callBackThis, window, 4);
}
},
searchWindowInList: function(window) {
let index = null;
for (let indexWindow in this.windowsList) {
if (this.windowsList[indexWindow] === window) {
index = indexWindow;
break;
}
}
return index;
},
addWindowInList: function(window) {
let index = this.searchWindowInList(window);
if (index === null && !window.is_skip_taskbar()) {
this.windowsList.push(window);
//Add window signals
let objectAndSignals = [
window, [
window.connect('notify::appears-focused', Lang.bind(this, this.onWindowChanged, 0)),
window.connect('notify::title', Lang.bind(this, this.onWindowChanged, 1)),
window.connect('notify::minimized', Lang.bind(this, this.onWindowChanged, 2)),
window.connect('notify::wm-class', Lang.bind(this, this.onWindowChanged, 3)),
window.connect('notify::gtk-application-id', Lang.bind(this, this.onWindowChanged, 4))
]
];
this.windowsSignals.push(objectAndSignals);
return true;
} else
return false;
},
removeWindowInList: function(window) {
let index = this.searchWindowInList(window);
if (index !== null) {
this.windowsList.splice(index, 1);
//Remove window signals
for (let indexSignal in this.windowsSignals) {
let [object, signals] = this.windowsSignals[indexSignal];
if (object === window) {
signals.forEach(
function(signal) {
object.disconnect(signal);
},
this
);
this.windowsSignals.splice(indexSignal, 1);
break;
}
}
return true;
} else
return false;
},
cleanWindowsList: function() {
for (let i = this.windowsList.length - 1; i >= 0; i--)
this.removeWindowInList(this.windowsList[i]);
}
}