mirror of
https://gitlab.com/thebiblelover7/dotfiles.git
synced 2025-12-13 19:53:49 +00:00
initial commit
This commit is contained in:
@@ -0,0 +1,416 @@
|
||||
|
||||
const Gi = imports._gi;
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const Docking = Me.imports.docking;
|
||||
|
||||
var SignalsHandlerFlags = {
|
||||
NONE: 0,
|
||||
CONNECT_AFTER: 1
|
||||
};
|
||||
|
||||
/**
|
||||
* Simplify global signals and function injections handling
|
||||
* abstract class
|
||||
*/
|
||||
const BasicHandler = class DashToDock_BasicHandler {
|
||||
|
||||
constructor(parentObject) {
|
||||
this._storage = new Object();
|
||||
|
||||
if (parentObject) {
|
||||
if (!(parentObject.connect instanceof Function))
|
||||
throw new TypeError('Not a valid parent object');
|
||||
|
||||
if (!(parentObject instanceof GObject.Object) ||
|
||||
GObject.signal_lookup('destroy', parentObject.constructor.$gtype)) {
|
||||
this._parentObject = parentObject;
|
||||
this._destroyId = parentObject.connect('destroy', () => this.destroy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add(...args) {
|
||||
// Convert arguments object to array, concatenate with generic
|
||||
// Call addWithLabel with ags as if they were passed arguments
|
||||
this.addWithLabel('generic', ...args);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._parentObject?.disconnect(this._destroyId);
|
||||
this._parentObject = null;
|
||||
|
||||
for( let label in this._storage )
|
||||
this.removeWithLabel(label);
|
||||
}
|
||||
|
||||
addWithLabel(label, ...args) {
|
||||
let argsArray = [...args];
|
||||
if (argsArray.every(arg => !Array.isArray(arg)))
|
||||
argsArray = [argsArray];
|
||||
|
||||
if (this._storage[label] == undefined)
|
||||
this._storage[label] = new Array();
|
||||
|
||||
// Skip first element of the arguments
|
||||
for (const argArray of argsArray) {
|
||||
if (argArray.length < 3)
|
||||
throw new Error('Unexpected number of arguments');
|
||||
let item = this._storage[label];
|
||||
try {
|
||||
item.push(this._create(...argArray));
|
||||
} catch (e) {
|
||||
logError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeWithLabel(label) {
|
||||
if (this._storage[label]) {
|
||||
for (let i = 0; i < this._storage[label].length; i++)
|
||||
this._remove(this._storage[label][i]);
|
||||
|
||||
delete this._storage[label];
|
||||
}
|
||||
}
|
||||
|
||||
// Virtual methods to be implemented by subclass
|
||||
|
||||
/**
|
||||
* Create single element to be stored in the storage structure
|
||||
*/
|
||||
_create(_object, _element, _callback) {
|
||||
throw new GObject.NotImplementedError(`_create in ${this.constructor.name}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Correctly delete single element
|
||||
*/
|
||||
_remove(_item) {
|
||||
throw new GObject.NotImplementedError(`_remove in ${this.constructor.name}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Manage global signals
|
||||
*/
|
||||
var GlobalSignalsHandler = class DashToDock_GlobalSignalHandler extends BasicHandler {
|
||||
|
||||
_create(object, event, callback, flags = SignalsHandlerFlags.NONE) {
|
||||
if (!object)
|
||||
throw new Error('Impossible to connect to an invalid object');
|
||||
|
||||
let after = flags == SignalsHandlerFlags.CONNECT_AFTER;
|
||||
let connector = after ? object.connect_after : object.connect;
|
||||
|
||||
if (!connector) {
|
||||
throw new Error(`Requested to connect to signal '${event}', ` +
|
||||
`but no implementation for 'connect${after ? '_after' : ''}' `+
|
||||
`found in ${object.constructor.name}`);
|
||||
}
|
||||
|
||||
let id = connector.call(object, event, callback);
|
||||
|
||||
return [object, id];
|
||||
}
|
||||
|
||||
_remove(item) {
|
||||
const [object, id] = item;
|
||||
object.disconnect(id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Color manipulation utilities
|
||||
*/
|
||||
var ColorUtils = class DashToDock_ColorUtils {
|
||||
|
||||
// Darken or brigthen color by a fraction dlum
|
||||
// Each rgb value is modified by the same fraction.
|
||||
// Return "#rrggbb" string
|
||||
static ColorLuminance(r, g, b, dlum) {
|
||||
let rgbString = '#';
|
||||
|
||||
rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(r*(1+dlum), 0), 255)), 2);
|
||||
rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(g*(1+dlum), 0), 255)), 2);
|
||||
rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(b*(1+dlum), 0), 255)), 2);
|
||||
|
||||
return rgbString;
|
||||
}
|
||||
|
||||
// Convert decimal to an hexadecimal string adding the desired padding
|
||||
static _decimalToHex(d, padding) {
|
||||
let hex = d.toString(16);
|
||||
while (hex.length < padding)
|
||||
hex = '0'+ hex;
|
||||
return hex;
|
||||
}
|
||||
|
||||
// Convert hsv ([0-1, 0-1, 0-1]) to rgb ([0-255, 0-255, 0-255]).
|
||||
// Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV
|
||||
// here with h = [0,1] instead of [0, 360]
|
||||
// Accept either (h,s,v) independently or {h:h, s:s, v:v} object.
|
||||
// Return {r:r, g:g, b:b} object.
|
||||
static HSVtoRGB(h, s, v) {
|
||||
if (arguments.length === 1) {
|
||||
s = h.s;
|
||||
v = h.v;
|
||||
h = h.h;
|
||||
}
|
||||
|
||||
let r,g,b;
|
||||
let c = v*s;
|
||||
let h1 = h*6;
|
||||
let x = c*(1 - Math.abs(h1 % 2 - 1));
|
||||
let m = v - c;
|
||||
|
||||
if (h1 <=1)
|
||||
r = c + m, g = x + m, b = m;
|
||||
else if (h1 <=2)
|
||||
r = x + m, g = c + m, b = m;
|
||||
else if (h1 <=3)
|
||||
r = m, g = c + m, b = x + m;
|
||||
else if (h1 <=4)
|
||||
r = m, g = x + m, b = c + m;
|
||||
else if (h1 <=5)
|
||||
r = x + m, g = m, b = c + m;
|
||||
else
|
||||
r = c + m, g = m, b = x + m;
|
||||
|
||||
return {
|
||||
r: Math.round(r * 255),
|
||||
g: Math.round(g * 255),
|
||||
b: Math.round(b * 255)
|
||||
};
|
||||
}
|
||||
|
||||
// Convert rgb ([0-255, 0-255, 0-255]) to hsv ([0-1, 0-1, 0-1]).
|
||||
// Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV
|
||||
// here with h = [0,1] instead of [0, 360]
|
||||
// Accept either (r,g,b) independently or {r:r, g:g, b:b} object.
|
||||
// Return {h:h, s:s, v:v} object.
|
||||
static RGBtoHSV(r, g, b) {
|
||||
if (arguments.length === 1) {
|
||||
r = r.r;
|
||||
g = r.g;
|
||||
b = r.b;
|
||||
}
|
||||
|
||||
let h,s,v;
|
||||
|
||||
let M = Math.max(r, g, b);
|
||||
let m = Math.min(r, g, b);
|
||||
let c = M - m;
|
||||
|
||||
if (c == 0)
|
||||
h = 0;
|
||||
else if (M == r)
|
||||
h = ((g-b)/c) % 6;
|
||||
else if (M == g)
|
||||
h = (b-r)/c + 2;
|
||||
else
|
||||
h = (r-g)/c + 4;
|
||||
|
||||
h = h/6;
|
||||
v = M/255;
|
||||
if (M !== 0)
|
||||
s = c/M;
|
||||
else
|
||||
s = 0;
|
||||
|
||||
return {
|
||||
h: h,
|
||||
s: s,
|
||||
v: v
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Manage function injection: both instances and prototype can be overridden
|
||||
* and restored
|
||||
*/
|
||||
var InjectionsHandler = class DashToDock_InjectionsHandler extends BasicHandler {
|
||||
|
||||
_create(object, name, injectedFunction) {
|
||||
let original = object[name];
|
||||
|
||||
if (!(original instanceof Function))
|
||||
throw new Error(`Virtual function ${name} is not available for ${prototype}`);
|
||||
|
||||
object[name] = function(...args) { return injectedFunction.call(this, original, ...args) };
|
||||
return [object, name, original];
|
||||
}
|
||||
|
||||
_remove(item) {
|
||||
const [object, name, original] = item;
|
||||
object[name] = original;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Manage vfunction injection: both instances and prototype can be overridden
|
||||
* and restored
|
||||
*/
|
||||
var VFuncInjectionsHandler = class DashToDock_VFuncInjectionsHandler extends BasicHandler {
|
||||
|
||||
_create(prototype, name, injectedFunction) {
|
||||
const original = prototype[`vfunc_${name}`];
|
||||
if (!(original instanceof Function))
|
||||
throw new Error(`Virtual function ${name} is not available for ${prototype}`);
|
||||
prototype[Gi.hook_up_vfunc_symbol](name, injectedFunction);
|
||||
return [prototype, name];
|
||||
}
|
||||
|
||||
_remove(item) {
|
||||
const [prototype, name] = item;
|
||||
const originalVFunc = prototype[`vfunc_${name}`];
|
||||
try {
|
||||
// This may fail if trying to reset to a never-overridden vfunc
|
||||
// as gjs doesn't consider it a function, even if it's true that
|
||||
// originalVFunc instanceof Function.
|
||||
prototype[Gi.hook_up_vfunc_symbol](name, originalVFunc);
|
||||
} catch {
|
||||
try {
|
||||
prototype[Gi.hook_up_vfunc_symbol](name, function (...args) {
|
||||
return originalVFunc.call(this, ...args);
|
||||
});
|
||||
} catch (e) {
|
||||
logError(e, `Removing vfunc_${name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Manage properties injection: both instances and prototype can be overridden
|
||||
* and restored
|
||||
*/
|
||||
var PropertyInjectionsHandler = class DashToDock_PropertyInjectionsHandler extends BasicHandler {
|
||||
|
||||
_create(instance, name, injectedPropertyDescriptor) {
|
||||
if (!(name in instance))
|
||||
throw new Error(`Object ${instance} has no '${name}' property`);
|
||||
|
||||
const prototype = instance.constructor.prototype;
|
||||
const originalPropertyDescriptor = Object.getOwnPropertyDescriptor(prototype, name) ??
|
||||
Object.getOwnPropertyDescriptor(instance, name);
|
||||
|
||||
Object.defineProperty(instance, name, {
|
||||
...originalPropertyDescriptor,
|
||||
...injectedPropertyDescriptor,
|
||||
...{ configurable: true },
|
||||
});
|
||||
return [instance, name, originalPropertyDescriptor];
|
||||
}
|
||||
|
||||
_remove(item) {
|
||||
const [instance, name, originalPropertyDescriptor] = item;
|
||||
if (originalPropertyDescriptor)
|
||||
Object.defineProperty(instance, name, originalPropertyDescriptor);
|
||||
else
|
||||
delete instance[name];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the actual position reverseing left and right in rtl
|
||||
*/
|
||||
function getPosition() {
|
||||
let position = Docking.DockManager.settings.get_enum('dock-position');
|
||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
|
||||
if (position == St.Side.LEFT)
|
||||
position = St.Side.RIGHT;
|
||||
else if (position == St.Side.RIGHT)
|
||||
position = St.Side.LEFT;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
function getPreviewScale() {
|
||||
return Docking.DockManager.settings.get_double('preview-size-scale');
|
||||
}
|
||||
|
||||
function drawRoundedLine(cr, x, y, width, height, isRoundLeft, isRoundRight, stroke, fill) {
|
||||
if (height > width) {
|
||||
y += Math.floor((height - width) / 2.0);
|
||||
height = width;
|
||||
}
|
||||
|
||||
height = 2.0 * Math.floor(height / 2.0);
|
||||
|
||||
var leftRadius = isRoundLeft ? height / 2.0 : 0.0;
|
||||
var rightRadius = isRoundRight ? height / 2.0 : 0.0;
|
||||
|
||||
cr.moveTo(x + width - rightRadius, y);
|
||||
cr.lineTo(x + leftRadius, y);
|
||||
if (isRoundLeft)
|
||||
cr.arcNegative(x + leftRadius, y + leftRadius, leftRadius, -Math.PI/2, Math.PI/2);
|
||||
else
|
||||
cr.lineTo(x, y + height);
|
||||
cr.lineTo(x + width - rightRadius, y + height);
|
||||
if (isRoundRight)
|
||||
cr.arcNegative(x + width - rightRadius, y + rightRadius, rightRadius, Math.PI/2, -Math.PI/2);
|
||||
else
|
||||
cr.lineTo(x + width, y);
|
||||
cr.closePath();
|
||||
|
||||
if (fill != null) {
|
||||
cr.setSource(fill);
|
||||
cr.fillPreserve();
|
||||
}
|
||||
if (stroke != null)
|
||||
cr.setSource(stroke);
|
||||
cr.stroke();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a signal handler with n value parameters (that is, excluding the
|
||||
* signal source parameter) to an array of n handlers that are each responsible
|
||||
* for receiving one of the n values and calling the original handler with the
|
||||
* most up-to-date arguments.
|
||||
*/
|
||||
function splitHandler(handler) {
|
||||
if (handler.length > 30) {
|
||||
throw new Error("too many parameters");
|
||||
}
|
||||
const count = handler.length - 1;
|
||||
let missingValueBits = (1 << count) - 1;
|
||||
const values = Array.from({ length: count });
|
||||
return values.map((_ignored, i) => {
|
||||
const mask = ~(1 << i);
|
||||
return (obj, value) => {
|
||||
values[i] = value;
|
||||
missingValueBits &= mask;
|
||||
if (missingValueBits === 0) {
|
||||
handler(obj, ...values);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
var IconTheme = class DashToDockIconTheme {
|
||||
constructor() {
|
||||
const settings = St.Settings.get();
|
||||
this._iconTheme = new Gtk.IconTheme();
|
||||
this._iconTheme.set_custom_theme(settings.gtkIconTheme);
|
||||
this._changesId = settings.connect('notify::gtk-icon-theme', () => {
|
||||
this._iconTheme.set_custom_theme(settings.gtkIconTheme);
|
||||
});
|
||||
}
|
||||
|
||||
get iconTheme() {
|
||||
return this._iconTheme;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
St.Settings.get().disconnect(this._changesId);
|
||||
this._iconTheme = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user