147 lines
6.2 KiB
JavaScript
147 lines
6.2 KiB
JavaScript
/* DING: Desktop Icons New Generation for GNOME Shell
|
|
*
|
|
* Copyright (C) 2021 Sergio Costas (rastersoft@gmail.com)
|
|
*
|
|
* 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, version 3 of the License.
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
'use strict';
|
|
const Signals = imports.signals;
|
|
import * as Main from 'resource:///org/gnome/shell/ui/main.js'
|
|
import GLib from 'gi://GLib'
|
|
|
|
export class VisibleArea {
|
|
constructor() {
|
|
this._usableAreas = {};
|
|
this._marginsList = {};
|
|
this._refreshTimerId = null;
|
|
// This UUID allows to ensure that the object is really a DesktopIconsIntegration object
|
|
this._extensionUUID = '130cbc66-235c-4bd6-8571-98d2d8bba5e2';
|
|
}
|
|
|
|
disable() {
|
|
if (this._refreshTimerId !== null) {
|
|
GLib.source_remove(this._refreshTimerId);
|
|
this._refreshTimerId = null;
|
|
}
|
|
}
|
|
|
|
setMarginsForExtension(extensionUUID, margins) {
|
|
if (margins == null) {
|
|
if (!(extensionUUID in this._marginsList)) {
|
|
return;
|
|
}
|
|
delete this._marginsList[extensionUUID];
|
|
} else {
|
|
this._marginsList[extensionUUID] = margins;
|
|
}
|
|
if (this._refreshTimerId) {
|
|
GLib.source_remove(this._refreshTimerId);
|
|
}
|
|
this._refreshTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => {
|
|
this._refreshMargins();
|
|
this._refreshTimerId = null;
|
|
return GLib.SOURCE_REMOVE;
|
|
});
|
|
}
|
|
|
|
_refreshMargins() {
|
|
this._usableAreas = {};
|
|
for (let extensionUUID in this._marginsList) {
|
|
let margins = this._marginsList[extensionUUID];
|
|
for (let workspace in margins) {
|
|
let index = workspace;
|
|
if (workspace < 0) {
|
|
index = Main.layoutManager.primaryIndex;
|
|
}
|
|
if (!(index in this._usableAreas)) {
|
|
this._usableAreas[index] = {
|
|
top: 0,
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0,
|
|
};
|
|
}
|
|
for (let index2 of ['top', 'bottom', 'left', 'right']) {
|
|
this._usableAreas[index][index2] = Math.max(this._usableAreas[index][index2], margins[workspace][index2]);
|
|
}
|
|
}
|
|
}
|
|
this.emit('updated-usable-area');
|
|
}
|
|
|
|
/**
|
|
* Returns the margin values for an specific monitor
|
|
*
|
|
* @param {} ws A workspace (obtained with global.workspace_manager.get_workspace_by_index(0);)
|
|
* @param {*} monitorIndex The monitor number
|
|
* @returns A dictionary with the following elements:
|
|
* x: the X coordinate of the monitor area
|
|
* y: the Y coordinate of the monitor area
|
|
* width: the width of the monitor area
|
|
* height: the height of the monitor area
|
|
* scale: the scale factor for this monitor
|
|
* marginTop: the number of pixels, counting from the top of the monitor, to leave free because are used by a dynamic element
|
|
* marginBottom: the number of pixels, counting from the bottom of the monitor, to leave free because are used by a dynamic element
|
|
* marginLeft: the number of pixels, counting from the left of the monitor area, to leave free because are used by a dynamic element
|
|
* marginRight: the number of pixels, counting from the right of the monitor area, to leave free because are used by a dynamic element
|
|
*
|
|
* The inner margins so returned automatically describe the working area of the monitor (in Gnome terms) that for example the top margin will
|
|
* automatically include the height of the top panel.
|
|
*
|
|
* In addition any extra margins above that set by gnome by othe extensions in usable areas will be returned if they are bigger than the margins
|
|
* described by gnome shell for the work area
|
|
*
|
|
* Thus, a window that covers the whole monitor area should be placed at X,Y and with a size of (width, height), and
|
|
* it must have inner margins of marginTop, marginRight, marginBottom and marginLeft.
|
|
*/
|
|
|
|
getMonitorGeometry(ws, monitorIndex) {
|
|
let geometry = ws.get_display().get_monitor_geometry(monitorIndex);
|
|
let scale = ws.get_display().get_monitor_scale(monitorIndex);
|
|
let area = ws.get_work_area_for_monitor(monitorIndex);
|
|
|
|
// calculate the margins due to the difference between the monitor geometry and the work area, ie. the work area margins
|
|
let marginTop = area.y - geometry.y;
|
|
let marginLeft = area.x - geometry.x;
|
|
let marginRight = geometry.width - area.width - marginLeft;
|
|
let marginBottom = geometry.height - area.height - marginTop;
|
|
|
|
if (monitorIndex in this._usableAreas) {
|
|
// If the margins for this monitor are bigger than the margins calculated previously,
|
|
// use the higher number. This is because the margin set from the extensions are be from the monitor border,
|
|
// an can supersede the ones that actually form the work area border.
|
|
marginTop = Math.max(marginTop, this._usableAreas[monitorIndex]['top']);
|
|
marginBottom = Math.max(marginBottom, this._usableAreas[monitorIndex]['bottom']);
|
|
marginLeft = Math.max(marginLeft, this._usableAreas[monitorIndex]['left']);
|
|
marginRight = Math.max(marginRight, this._usableAreas[monitorIndex]['right']);
|
|
}
|
|
|
|
return {
|
|
x: geometry.x,
|
|
y: geometry.y,
|
|
width: geometry.width,
|
|
height: geometry.height,
|
|
scale,
|
|
marginTop,
|
|
marginBottom,
|
|
marginLeft,
|
|
marginRight,
|
|
};
|
|
}
|
|
|
|
get uuid() {
|
|
return this._extensionUUID;
|
|
}
|
|
};
|
|
Signals.addSignalMethods(VisibleArea.prototype);
|