2011-09-28 13:16:26 +00:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
2019-01-31 14:07:06 +00:00
|
|
|
/* exported init */
|
2009-09-18 19:51:15 +00:00
|
|
|
|
2016-11-28 04:54:38 +00:00
|
|
|
const Config = imports.misc.config;
|
|
|
|
|
|
|
|
imports.gi.versions.Clutter = Config.LIBMUTTER_API_VERSION;
|
2011-04-30 14:27:36 +00:00
|
|
|
imports.gi.versions.Gio = '2.0';
|
|
|
|
imports.gi.versions.GdkPixbuf = '2.0';
|
2021-12-02 10:44:47 +00:00
|
|
|
imports.gi.versions.GnomeBluetooth = '3.0';
|
2021-11-11 19:20:39 +00:00
|
|
|
imports.gi.versions.GnomeDesktop = '3.0';
|
2011-04-30 14:27:36 +00:00
|
|
|
imports.gi.versions.Gtk = '3.0';
|
2022-01-05 02:18:08 +00:00
|
|
|
imports.gi.versions.GWeather = '4.0';
|
2021-08-03 23:35:08 +00:00
|
|
|
imports.gi.versions.Soup = '3.0';
|
2014-03-25 17:02:02 +00:00
|
|
|
imports.gi.versions.TelepathyGLib = '0.12';
|
|
|
|
imports.gi.versions.TelepathyLogger = '0.2';
|
2011-04-30 14:27:36 +00:00
|
|
|
|
2021-08-04 17:37:15 +00:00
|
|
|
try {
|
2021-08-29 12:24:42 +00:00
|
|
|
if (Config.HAVE_SOUP2)
|
|
|
|
throw new Error('Soup3 support not enabled');
|
2021-08-04 17:37:15 +00:00
|
|
|
const Soup_ = imports.gi.Soup;
|
|
|
|
} catch (e) {
|
|
|
|
imports.gi.versions.Soup = '2.4';
|
|
|
|
const { Soup } = imports.gi;
|
|
|
|
_injectSoup3Compat(Soup);
|
|
|
|
}
|
|
|
|
|
2019-12-19 19:50:37 +00:00
|
|
|
const { Clutter, Gio, GLib, GObject, Meta, Polkit, Shell, St } = imports.gi;
|
2011-04-30 14:34:51 +00:00
|
|
|
const Gettext = imports.gettext;
|
2020-02-27 21:46:44 +00:00
|
|
|
const System = imports.system;
|
|
|
|
|
2019-12-19 19:50:37 +00:00
|
|
|
Gio._promisify(Gio.DataInputStream.prototype, 'fill_async', 'fill_finish');
|
|
|
|
Gio._promisify(Gio.DataInputStream.prototype,
|
|
|
|
'read_line_async', 'read_line_finish');
|
|
|
|
Gio._promisify(Gio.DBus, 'get', 'get_finish');
|
|
|
|
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
|
|
|
|
Gio._promisify(Gio.DBusProxy, 'new', 'new_finish');
|
|
|
|
Gio._promisify(Gio.DBusProxy.prototype, 'init_async', 'init_finish');
|
|
|
|
Gio._promisify(Gio.DBusProxy.prototype,
|
|
|
|
'call_with_unix_fd_list', 'call_with_unix_fd_list_finish');
|
|
|
|
Gio._promisify(Polkit.Permission, 'new', 'new_finish');
|
|
|
|
|
2020-02-27 21:46:44 +00:00
|
|
|
let _localTimeZone = null;
|
2009-09-18 19:51:15 +00:00
|
|
|
|
2011-04-30 14:27:36 +00:00
|
|
|
// We can't import shell JS modules yet, because they may have
|
|
|
|
// variable initializations, etc, that depend on init() already having
|
|
|
|
// been run.
|
2009-09-18 19:51:15 +00:00
|
|
|
|
2009-10-04 21:30:18 +00:00
|
|
|
|
2009-09-18 19:51:15 +00:00
|
|
|
// "monkey patch" in some varargs ClutterContainer methods; we need
|
|
|
|
// to do this per-container class since there is no representation
|
|
|
|
// of interfaces in Javascript
|
|
|
|
function _patchContainerClass(containerClass) {
|
|
|
|
// This one is a straightforward mapping of the C method
|
2019-08-19 17:55:49 +00:00
|
|
|
containerClass.prototype.child_set = function (actor, props) {
|
2009-09-18 19:51:15 +00:00
|
|
|
let meta = this.get_child_meta(actor);
|
2011-02-24 17:17:05 +00:00
|
|
|
for (let prop in props)
|
2009-09-18 19:51:15 +00:00
|
|
|
meta[prop] = props[prop];
|
|
|
|
};
|
|
|
|
|
|
|
|
// clutter_container_add() actually is a an add-many-actors
|
|
|
|
// method. We conveniently, but somewhat dubiously, take the
|
|
|
|
// this opportunity to make it do something more useful.
|
2019-08-19 17:55:49 +00:00
|
|
|
containerClass.prototype.add = function (actor, props) {
|
2009-09-18 19:51:15 +00:00
|
|
|
this.add_actor(actor);
|
|
|
|
if (props)
|
|
|
|
this.child_set(actor, props);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2013-07-09 21:04:45 +00:00
|
|
|
function _patchLayoutClass(layoutClass, styleProps) {
|
2019-08-20 00:51:42 +00:00
|
|
|
if (styleProps) {
|
2019-08-19 17:55:49 +00:00
|
|
|
layoutClass.prototype.hookup_style = function (container) {
|
2017-10-31 00:38:18 +00:00
|
|
|
container.connect('style-changed', () => {
|
2013-07-09 21:04:45 +00:00
|
|
|
let node = container.get_theme_node();
|
2014-04-24 14:20:01 +00:00
|
|
|
for (let prop in styleProps) {
|
|
|
|
let [found, length] = node.lookup_length(styleProps[prop], false);
|
|
|
|
if (found)
|
|
|
|
this[prop] = length;
|
|
|
|
}
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2013-07-09 21:04:45 +00:00
|
|
|
};
|
2019-08-20 00:51:42 +00:00
|
|
|
}
|
2013-07-09 21:04:45 +00:00
|
|
|
}
|
|
|
|
|
2021-08-04 17:37:15 +00:00
|
|
|
/**
|
|
|
|
* Mimick the Soup 3 APIs we use when falling back to Soup 2.4
|
|
|
|
*
|
|
|
|
* @param {object} Soup 2.4 namespace
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
function _injectSoup3Compat(Soup) {
|
|
|
|
Soup.StatusCode = Soup.KnownStatusCode;
|
|
|
|
|
|
|
|
Soup.Message.new_from_encoded_form =
|
|
|
|
function (method, uri, form) {
|
|
|
|
const soupUri = new Soup.URI(uri);
|
|
|
|
soupUri.set_query(form);
|
|
|
|
return Soup.Message.new_from_uri(method, soupUri);
|
|
|
|
};
|
|
|
|
Soup.Message.prototype.set_request_body_from_bytes =
|
|
|
|
function (contentType, bytes) {
|
|
|
|
this.set_request(
|
|
|
|
contentType,
|
|
|
|
Soup.MemoryUse.COPY,
|
2021-08-12 14:38:57 +00:00
|
|
|
new TextDecoder().decode(bytes.get_data()));
|
2021-08-04 17:37:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Soup.Session.prototype.send_and_read_async =
|
|
|
|
function (message, prio, cancellable, callback) {
|
|
|
|
this.queue_message(message, () => callback(this, message));
|
|
|
|
};
|
|
|
|
Soup.Session.prototype.send_and_read_finish =
|
|
|
|
function (message) {
|
|
|
|
if (message.status_code !== Soup.KnownStatusCode.OK)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
return message.response_body.flatten().get_as_bytes();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-09-13 09:51:41 +00:00
|
|
|
function _makeEaseCallback(params, cleanup) {
|
2017-06-10 00:52:12 +00:00
|
|
|
let onComplete = params.onComplete;
|
|
|
|
delete params.onComplete;
|
|
|
|
|
|
|
|
let onStopped = params.onStopped;
|
|
|
|
delete params.onStopped;
|
|
|
|
|
|
|
|
return isFinished => {
|
2019-09-13 09:51:41 +00:00
|
|
|
cleanup();
|
|
|
|
|
2017-06-10 00:52:12 +00:00
|
|
|
if (onStopped)
|
|
|
|
onStopped(isFinished);
|
|
|
|
if (onComplete && isFinished)
|
|
|
|
onComplete();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-06-10 02:14:12 +00:00
|
|
|
function _getPropertyTarget(actor, propName) {
|
|
|
|
if (!propName.startsWith('@'))
|
|
|
|
return [actor, propName];
|
|
|
|
|
|
|
|
let [type, name, prop] = propName.split('.');
|
|
|
|
switch (type) {
|
|
|
|
case '@layout':
|
|
|
|
return [actor.layout_manager, name];
|
|
|
|
case '@actions':
|
|
|
|
return [actor.get_action(name), prop];
|
|
|
|
case '@constraints':
|
|
|
|
return [actor.get_constraint(name), prop];
|
2020-10-07 23:21:04 +00:00
|
|
|
case '@content':
|
|
|
|
return [actor.content, name];
|
2017-06-10 02:14:12 +00:00
|
|
|
case '@effects':
|
|
|
|
return [actor.get_effect(name), prop];
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error(`Invalid property name ${propName}`);
|
|
|
|
}
|
|
|
|
|
2017-06-10 00:52:12 +00:00
|
|
|
function _easeActor(actor, params) {
|
|
|
|
actor.save_easing_state();
|
|
|
|
|
|
|
|
if (params.duration != undefined)
|
|
|
|
actor.set_easing_duration(params.duration);
|
|
|
|
delete params.duration;
|
|
|
|
|
|
|
|
if (params.delay != undefined)
|
|
|
|
actor.set_easing_delay(params.delay);
|
|
|
|
delete params.delay;
|
|
|
|
|
2019-10-15 19:32:21 +00:00
|
|
|
let repeatCount = 0;
|
|
|
|
if (params.repeatCount != undefined)
|
|
|
|
repeatCount = params.repeatCount;
|
|
|
|
delete params.repeatCount;
|
|
|
|
|
|
|
|
let autoReverse = false;
|
|
|
|
if (params.autoReverse != undefined)
|
|
|
|
autoReverse = params.autoReverse;
|
|
|
|
delete params.autoReverse;
|
|
|
|
|
2020-02-22 15:35:32 +00:00
|
|
|
// repeatCount doesn't include the initial iteration
|
|
|
|
const numIterations = repeatCount + 1;
|
|
|
|
// whether the transition should finish where it started
|
|
|
|
const isReversed = autoReverse && numIterations % 2 === 0;
|
|
|
|
|
2017-06-10 00:52:12 +00:00
|
|
|
if (params.mode != undefined)
|
|
|
|
actor.set_easing_mode(params.mode);
|
|
|
|
delete params.mode;
|
|
|
|
|
2020-08-03 16:33:57 +00:00
|
|
|
const prepare = () => {
|
|
|
|
Meta.disable_unredirect_for_display(global.display);
|
|
|
|
global.begin_work();
|
|
|
|
};
|
|
|
|
const cleanup = () => {
|
|
|
|
Meta.enable_unredirect_for_display(global.display);
|
|
|
|
global.end_work();
|
|
|
|
};
|
2019-09-13 09:51:41 +00:00
|
|
|
let callback = _makeEaseCallback(params, cleanup);
|
2017-06-10 00:52:12 +00:00
|
|
|
|
|
|
|
// cancel overwritten transitions
|
|
|
|
let animatedProps = Object.keys(params).map(p => p.replace('_', '-', 'g'));
|
|
|
|
animatedProps.forEach(p => actor.remove_transition(p));
|
|
|
|
|
2020-02-22 15:35:32 +00:00
|
|
|
if (actor.get_easing_duration() > 0 || !isReversed)
|
|
|
|
actor.set(params);
|
2019-08-09 00:58:28 +00:00
|
|
|
actor.restore_easing_state();
|
2017-06-10 00:52:12 +00:00
|
|
|
|
2021-10-21 17:50:18 +00:00
|
|
|
const transitions = animatedProps
|
|
|
|
.map(p => actor.get_transition(p))
|
|
|
|
.filter(t => t !== null);
|
|
|
|
|
|
|
|
transitions.forEach(t => t.set({ repeatCount, autoReverse }));
|
|
|
|
|
|
|
|
const [transition] = transitions;
|
2019-09-20 00:50:36 +00:00
|
|
|
|
2019-10-14 07:47:38 +00:00
|
|
|
if (transition && transition.delay)
|
2020-08-03 16:33:57 +00:00
|
|
|
transition.connect('started', () => prepare());
|
2019-10-14 07:47:38 +00:00
|
|
|
else
|
2020-08-03 16:33:57 +00:00
|
|
|
prepare();
|
2019-10-14 07:47:38 +00:00
|
|
|
|
2021-10-21 17:50:18 +00:00
|
|
|
if (transition)
|
2019-09-13 09:51:41 +00:00
|
|
|
transition.connect('stopped', (t, finished) => callback(finished));
|
2021-10-21 17:50:18 +00:00
|
|
|
else
|
2019-09-13 09:51:41 +00:00
|
|
|
callback(true);
|
2017-06-10 00:52:12 +00:00
|
|
|
}
|
|
|
|
|
2017-06-10 02:14:12 +00:00
|
|
|
function _easeActorProperty(actor, propName, target, params) {
|
|
|
|
// Avoid pointless difference with ease()
|
|
|
|
if (params.mode)
|
|
|
|
params.progress_mode = params.mode;
|
|
|
|
delete params.mode;
|
|
|
|
|
|
|
|
if (params.duration)
|
|
|
|
params.duration = adjustAnimationTime(params.duration);
|
|
|
|
let duration = Math.floor(params.duration || 0);
|
|
|
|
|
2019-10-15 19:32:21 +00:00
|
|
|
let repeatCount = 0;
|
|
|
|
if (params.repeatCount != undefined)
|
|
|
|
repeatCount = params.repeatCount;
|
|
|
|
delete params.repeatCount;
|
|
|
|
|
|
|
|
let autoReverse = false;
|
|
|
|
if (params.autoReverse != undefined)
|
|
|
|
autoReverse = params.autoReverse;
|
|
|
|
delete params.autoReverse;
|
|
|
|
|
2020-02-22 15:35:32 +00:00
|
|
|
// repeatCount doesn't include the initial iteration
|
|
|
|
const numIterations = repeatCount + 1;
|
|
|
|
// whether the transition should finish where it started
|
|
|
|
const isReversed = autoReverse && numIterations % 2 === 0;
|
|
|
|
|
2019-09-10 13:28:42 +00:00
|
|
|
// Copy Clutter's behavior for implicit animations, see
|
|
|
|
// should_skip_implicit_transition()
|
|
|
|
if (actor instanceof Clutter.Actor && !actor.mapped)
|
|
|
|
duration = 0;
|
|
|
|
|
2020-08-03 16:33:57 +00:00
|
|
|
const prepare = () => {
|
|
|
|
Meta.disable_unredirect_for_display(global.display);
|
|
|
|
global.begin_work();
|
|
|
|
};
|
|
|
|
const cleanup = () => {
|
|
|
|
Meta.enable_unredirect_for_display(global.display);
|
|
|
|
global.end_work();
|
|
|
|
};
|
2019-09-13 09:51:41 +00:00
|
|
|
let callback = _makeEaseCallback(params, cleanup);
|
2017-06-10 02:14:12 +00:00
|
|
|
|
|
|
|
// cancel overwritten transition
|
|
|
|
actor.remove_transition(propName);
|
|
|
|
|
|
|
|
if (duration == 0) {
|
|
|
|
let [obj, prop] = _getPropertyTarget(actor, propName);
|
2020-02-22 15:35:32 +00:00
|
|
|
|
|
|
|
if (!isReversed)
|
|
|
|
obj[prop] = target;
|
2017-06-10 02:14:12 +00:00
|
|
|
|
2020-08-03 16:33:57 +00:00
|
|
|
prepare();
|
2019-09-13 09:51:41 +00:00
|
|
|
callback(true);
|
2017-06-10 02:14:12 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let pspec = actor.find_property(propName);
|
|
|
|
let transition = new Clutter.PropertyTransition(Object.assign({
|
|
|
|
property_name: propName,
|
|
|
|
interval: new Clutter.Interval({ value_type: pspec.value_type }),
|
2019-10-15 19:32:21 +00:00
|
|
|
remove_on_complete: true,
|
|
|
|
repeat_count: repeatCount,
|
|
|
|
auto_reverse: autoReverse,
|
2017-06-10 02:14:12 +00:00
|
|
|
}, params));
|
|
|
|
actor.add_transition(propName, transition);
|
|
|
|
|
|
|
|
transition.set_to(target);
|
|
|
|
|
2019-10-14 07:47:38 +00:00
|
|
|
if (transition.delay)
|
2020-08-03 16:33:57 +00:00
|
|
|
transition.connect('started', () => prepare());
|
2019-10-14 07:47:38 +00:00
|
|
|
else
|
2020-08-03 16:33:57 +00:00
|
|
|
prepare();
|
2019-10-14 07:47:38 +00:00
|
|
|
|
2019-09-13 09:51:41 +00:00
|
|
|
transition.connect('stopped', (t, finished) => callback(finished));
|
2017-06-10 02:14:12 +00:00
|
|
|
}
|
|
|
|
|
2019-02-12 11:24:30 +00:00
|
|
|
function _loggingFunc(...args) {
|
2019-01-29 01:27:05 +00:00
|
|
|
let fields = { 'MESSAGE': args.join(', ') };
|
2016-10-03 23:09:39 +00:00
|
|
|
let domain = "GNOME Shell";
|
|
|
|
|
|
|
|
// If the caller is an extension, add it as metadata
|
|
|
|
let extension = imports.misc.extensionUtils.getCurrentExtension();
|
|
|
|
if (extension != null) {
|
|
|
|
domain = extension.metadata.name;
|
|
|
|
fields['GNOME_SHELL_EXTENSION_UUID'] = extension.uuid;
|
|
|
|
fields['GNOME_SHELL_EXTENSION_NAME'] = extension.metadata.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
GLib.log_structured(domain, GLib.LogLevelFlags.LEVEL_MESSAGE, fields);
|
2012-04-29 20:41:08 +00:00
|
|
|
}
|
|
|
|
|
2009-09-18 19:51:15 +00:00
|
|
|
function init() {
|
2020-04-23 23:06:36 +00:00
|
|
|
// Add some bindings to the global JS namespace
|
|
|
|
globalThis.global = Shell.Global.get();
|
2011-03-13 00:41:23 +00:00
|
|
|
|
2020-04-23 23:06:36 +00:00
|
|
|
globalThis.log = _loggingFunc;
|
2012-04-29 20:41:08 +00:00
|
|
|
|
2020-04-23 23:06:36 +00:00
|
|
|
globalThis._ = Gettext.gettext;
|
|
|
|
globalThis.C_ = Gettext.pgettext;
|
|
|
|
globalThis.ngettext = Gettext.ngettext;
|
|
|
|
globalThis.N_ = s => s;
|
2011-04-30 13:16:13 +00:00
|
|
|
|
2019-10-28 17:44:24 +00:00
|
|
|
GObject.gtypeNameBasedOnJSPath = true;
|
|
|
|
|
2011-04-30 14:27:36 +00:00
|
|
|
// Miscellaneous monkeypatching
|
2010-03-26 20:38:03 +00:00
|
|
|
_patchContainerClass(St.BoxLayout);
|
|
|
|
|
2013-07-09 21:04:45 +00:00
|
|
|
_patchLayoutClass(Clutter.GridLayout, { row_spacing: 'spacing-rows',
|
|
|
|
column_spacing: 'spacing-columns' });
|
|
|
|
_patchLayoutClass(Clutter.BoxLayout, { spacing: 'spacing' });
|
|
|
|
|
2014-06-04 22:13:14 +00:00
|
|
|
let origSetEasingDuration = Clutter.Actor.prototype.set_easing_duration;
|
2019-08-19 17:55:49 +00:00
|
|
|
Clutter.Actor.prototype.set_easing_duration = function (msecs) {
|
2014-06-04 22:13:14 +00:00
|
|
|
origSetEasingDuration.call(this, adjustAnimationTime(msecs));
|
|
|
|
};
|
|
|
|
let origSetEasingDelay = Clutter.Actor.prototype.set_easing_delay;
|
2019-08-19 17:55:49 +00:00
|
|
|
Clutter.Actor.prototype.set_easing_delay = function (msecs) {
|
2014-06-04 22:13:14 +00:00
|
|
|
origSetEasingDelay.call(this, adjustAnimationTime(msecs));
|
|
|
|
};
|
|
|
|
|
2019-12-19 22:08:44 +00:00
|
|
|
Clutter.Actor.prototype.ease = function (props) {
|
|
|
|
_easeActor(this, props);
|
2017-06-10 00:52:12 +00:00
|
|
|
};
|
2019-08-19 17:55:49 +00:00
|
|
|
Clutter.Actor.prototype.ease_property = function (propName, target, params) {
|
2017-06-10 02:14:12 +00:00
|
|
|
_easeActorProperty(this, propName, target, params);
|
|
|
|
};
|
2019-08-19 17:55:49 +00:00
|
|
|
St.Adjustment.prototype.ease = function (target, params) {
|
2019-07-25 14:21:46 +00:00
|
|
|
// we're not an actor of course, but we implement the same
|
|
|
|
// transition API as Clutter.Actor, so this works anyway
|
|
|
|
_easeActorProperty(this, 'value', target, params);
|
|
|
|
};
|
2017-06-10 00:52:12 +00:00
|
|
|
|
2020-05-19 19:29:49 +00:00
|
|
|
Clutter.Actor.prototype[Symbol.iterator] = function* () {
|
2020-05-19 18:59:36 +00:00
|
|
|
for (let c = this.get_first_child(); c; c = c.get_next_sibling())
|
|
|
|
yield c;
|
|
|
|
};
|
|
|
|
|
2019-08-19 17:55:49 +00:00
|
|
|
Clutter.Actor.prototype.toString = function () {
|
2010-06-17 17:19:07 +00:00
|
|
|
return St.describe_actor(this);
|
|
|
|
};
|
2019-04-13 18:34:29 +00:00
|
|
|
// Deprecation warning for former JS classes turned into an actor subclass
|
|
|
|
Object.defineProperty(Clutter.Actor.prototype, 'actor', {
|
|
|
|
get() {
|
|
|
|
let klass = this.constructor.name;
|
|
|
|
let { stack } = new Error();
|
|
|
|
log(`Usage of object.actor is deprecated for ${klass}\n${stack}`);
|
|
|
|
return this;
|
2019-08-20 21:43:54 +00:00
|
|
|
},
|
2019-04-13 18:34:29 +00:00
|
|
|
});
|
2010-06-10 12:15:02 +00:00
|
|
|
|
2020-03-23 17:00:27 +00:00
|
|
|
Gio._LocalFilePrototype.touch_async = function (callback) {
|
|
|
|
Shell.util_touch_file_async(this, callback);
|
|
|
|
};
|
|
|
|
Gio._LocalFilePrototype.touch_finish = function (result) {
|
|
|
|
return Shell.util_touch_file_finish(this, result);
|
|
|
|
};
|
|
|
|
|
2019-08-19 17:55:49 +00:00
|
|
|
St.set_slow_down_factor = function (factor) {
|
2019-07-25 10:50:26 +00:00
|
|
|
let { stack } = new Error();
|
|
|
|
log(`St.set_slow_down_factor() is deprecated, use St.Settings.slow_down_factor\n${stack}`);
|
|
|
|
St.Settings.get().slow_down_factor = factor;
|
|
|
|
};
|
|
|
|
|
2011-04-06 14:40:01 +00:00
|
|
|
let origToString = Object.prototype.toString;
|
2019-08-19 17:55:49 +00:00
|
|
|
Object.prototype.toString = function () {
|
2011-04-06 14:40:01 +00:00
|
|
|
let base = origToString.call(this);
|
2012-03-05 20:15:45 +00:00
|
|
|
try {
|
|
|
|
if ('actor' in this && this.actor instanceof Clutter.Actor)
|
2019-01-30 00:18:24 +00:00
|
|
|
return base.replace(/\]$/, ` delegate for ${this.actor.toString().substring(1)}`);
|
2012-03-05 20:15:45 +00:00
|
|
|
else
|
|
|
|
return base;
|
2019-01-29 01:26:39 +00:00
|
|
|
} catch (e) {
|
2011-04-06 14:40:01 +00:00
|
|
|
return base;
|
2012-03-05 20:15:45 +00:00
|
|
|
}
|
2011-04-06 14:40:01 +00:00
|
|
|
};
|
|
|
|
|
2020-02-27 21:46:44 +00:00
|
|
|
// Override to clear our own timezone cache as well
|
|
|
|
const origClearDateCaches = System.clearDateCaches;
|
|
|
|
System.clearDateCaches = function () {
|
|
|
|
_localTimeZone = null;
|
|
|
|
origClearDateCaches();
|
|
|
|
};
|
|
|
|
|
2011-04-30 14:27:36 +00:00
|
|
|
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
|
2019-08-19 17:55:49 +00:00
|
|
|
Date.prototype.toLocaleFormat = function (format) {
|
2020-02-27 21:46:44 +00:00
|
|
|
if (_localTimeZone === null)
|
|
|
|
_localTimeZone = GLib.TimeZone.new_local();
|
|
|
|
|
|
|
|
let dt = GLib.DateTime.new(_localTimeZone,
|
2020-03-02 12:46:04 +00:00
|
|
|
this.getFullYear(),
|
2020-02-27 21:46:44 +00:00
|
|
|
this.getMonth() + 1,
|
|
|
|
this.getDate(),
|
|
|
|
this.getHours(),
|
|
|
|
this.getMinutes(),
|
|
|
|
this.getSeconds());
|
2020-08-12 18:59:01 +00:00
|
|
|
return dt?.format(format) ?? '';
|
2011-04-30 14:27:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
|
|
|
|
if (slowdownEnv) {
|
|
|
|
let factor = parseFloat(slowdownEnv);
|
|
|
|
if (!isNaN(factor) && factor > 0.0)
|
2019-07-25 10:50:26 +00:00
|
|
|
St.Settings.get().slow_down_factor = factor;
|
2011-04-30 14:27:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// OK, now things are initialized enough that we can import shell JS
|
2012-05-04 21:23:08 +00:00
|
|
|
const Format = imports.format;
|
2011-04-30 14:27:36 +00:00
|
|
|
|
|
|
|
String.prototype.format = Format.format;
|
2020-06-02 03:41:43 +00:00
|
|
|
|
|
|
|
Math.clamp = function (x, lower, upper) {
|
|
|
|
return Math.min(Math.max(x, lower), upper);
|
|
|
|
};
|
2009-09-18 19:51:15 +00:00
|
|
|
}
|
2014-06-04 22:13:14 +00:00
|
|
|
|
|
|
|
// adjustAnimationTime:
|
|
|
|
// @msecs: time in milliseconds
|
|
|
|
//
|
|
|
|
// Adjust @msecs to account for St's enable-animations
|
|
|
|
// and slow-down-factor settings
|
|
|
|
function adjustAnimationTime(msecs) {
|
|
|
|
let settings = St.Settings.get();
|
|
|
|
|
|
|
|
if (!settings.enable_animations)
|
|
|
|
return 1;
|
|
|
|
return settings.slow_down_factor * msecs;
|
|
|
|
}
|
|
|
|
|