Files
dash-to-panel/desktopIconsIntegration.js
Charles Gagnon d04104ff8a Format code
2025-01-31 11:49:22 -05:00

172 lines
6.1 KiB
JavaScript

/*
* The code in this file is distributed under a "1-clause BSD license",
* which makes it compatible with GPLv2 and GPLv3 too, and others.
*
* License text:
*
* Copyright (C) 2021 Sergio Costas (rastersoft@gmail.com)
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*******************************************************************************
* Integration class
*
* This class must be added to other extensions in order to integrate
* them with Desktop Icons NG. It allows an extension to notify how much margin
* it uses in each side of each monitor.
*
* DON'T SEND PATCHES TO THIS FILE TO THE EXTENSION MAINTAINER. SEND THEM TO
* DESKTOP ICONS NG MAINTAINER: https://gitlab.com/rastersoft/desktop-icons-ng
*
* In the *enable()* function, create a *DesktopIconsUsableAreaClass()*
* object with
*
* new DesktopIconsIntegration.DesktopIconsUsableAreaClass(object);
*
* Now, in the *disable()* function just call to the *destroy()* method before
* nullifying the pointer. You must create a new object in enable() the next
* time the extension is enabled.
*
* In your code, every time you change the margins, you should call first to
* *resetMargins()* method to clear the current margins, and then call to
* *setMargins(...)* method as many times as you need to set the margins in each
* monitor. You don't need to call it for all the monitors, only for those where
* you are painting something. If you don't set values for a monitor, they will
* be considered zero.
*
* The margins values are relative to the monitor border.
*
*******************************************************************************/
import GLib from 'gi://GLib'
import * as Main from 'resource:///org/gnome/shell/ui/main.js'
import * as ExtensionUtils from 'resource:///org/gnome/shell/misc/extensionUtils.js'
import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'
const IDENTIFIER_UUID = '130cbc66-235c-4bd6-8571-98d2d8bba5e2'
export class DesktopIconsUsableAreaClass {
_checkIfExtensionIsEnabled(extension) {
return (
extension?.state === ExtensionUtils.ExtensionState.ENABLED ||
extension?.state === ExtensionUtils.ExtensionState.ACTIVE
)
}
constructor() {
const Me = Extension.lookupByURL(import.meta.url)
this._UUID = Me.uuid
this._extensionManager = Main.extensionManager
this._timedMarginsID = 0
this._margins = {}
this._emID = this._extensionManager.connect(
'extension-state-changed',
(_obj, extension) => {
if (!extension) return
// If an extension is being enabled and lacks the DesktopIconsUsableArea object, we can avoid launching a refresh
if (this._checkIfExtensionIsEnabled(extension)) {
this._sendMarginsToExtension(extension)
return
}
// if the extension is being disabled, we must do a full refresh, because if there were other extensions originally
// loaded after that extension, those extensions will be disabled and enabled again without notification
this._changedMargins()
},
)
}
/**
* Sets or updates the top, bottom, left and right margins for a
* monitor. Values are measured from the monitor border (and NOT from
* the workspace border).
*
* @param {int} monitor Monitor number to which set the margins.
* A negative value means "the primary monitor".
* @param {int} top Top margin in pixels
* @param {int} bottom Bottom margin in pixels
* @param {int} left Left margin in pixels
* @param {int} right Right margin in pixels
*/
setMargins(monitor, top, bottom, left, right) {
this._margins[monitor] = {
top: top,
bottom: bottom,
left: left,
right: right,
}
this._changedMargins()
}
/**
* Clears the current margins. Must be called before configuring the monitors
* margins with setMargins().
*/
resetMargins() {
this._margins = {}
this._changedMargins()
}
/**
* Disconnects all the signals and removes the margins.
*/
destroy() {
if (this._emID) {
this._extensionManager.disconnect(this._emID)
this._emID = 0
}
if (this._timedMarginsID) {
GLib.source_remove(this._timedMarginsID)
this._timedMarginsID = 0
}
this._margins = null
this._changedMargins()
}
_changedMargins() {
if (this._timedMarginsID) {
GLib.source_remove(this._timedMarginsID)
}
this._timedMarginsID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => {
this._sendMarginsToAll()
this._timedMarginsID = 0
return GLib.SOURCE_REMOVE
})
}
_sendMarginsToAll() {
this._extensionManager
.getUuids()
.forEach((uuid) =>
this._sendMarginsToExtension(this._extensionManager.lookup(uuid)),
)
}
_sendMarginsToExtension(extension) {
// check that the extension is an extension that has the logic to accept
// working margins
if (!this._checkIfExtensionIsEnabled(extension)) return
const usableArea = extension?.stateObj?.DesktopIconsUsableArea
if (usableArea?.uuid === IDENTIFIER_UUID)
usableArea.setMarginsForExtension(this._UUID, this._margins)
}
}