Skip to content
Commits on Source (15)
......@@ -366,24 +366,48 @@ var AppIndicator = class AppIndicatorsAppIndicator {
delete this._nameWatcher;
}
open() {
open(x, y) {
// we can't use WindowID because we're not able to get the x11 window id from a MetaWindow
// nor can we call any X11 functions. Luckily, the Activate method usually works fine.
// parameters are "an hint to the item where to show eventual windows" [sic]
// ... and don't seem to have any effect.
this._proxy.ActivateRemote(0, 0);
this._proxy.ActivateRemote(x, y, this._cancellable, (_, e) => {
if (e && !e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
Util.Logger.critical(`${this._indicator.id}, failed to activate: ${e.message}`);
});
}
secondaryActivate() {
this._proxy.SecondaryActivateRemote(0, 0);
secondaryActivate(timestamp, x, y) {
const cancellable = this._cancellable;
this._proxy.XAyatanaSecondaryActivateRemote(timestamp, cancellable, (_, e) => {
if (e && e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD)) {
this._proxy.SecondaryActivateRemote(x, y, cancellable, (_r, error) => {
if (error && !error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
Util.Logger.critical(`${this._indicator.id}, failed to secondary activate: ${e.message}`);
});
} else if (e && !e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
Util.Logger.critical(`${this._indicator.id}, failed to secondary activate: ${e.message}`);
}
});
}
scroll(dx, dy) {
if (dx !== 0)
this._proxy.ScrollRemote(Math.floor(dx), 'horizontal');
const cancellable = this._cancellable;
if (dx !== 0) {
this._proxy.ScrollRemote(Math.floor(dx), 'horizontal', cancellable, (_, e) => {
if (e && !e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
Util.Logger.critical(`${this._indicator.id}, failed to scroll horizontally: ${e.message}`);
});
}
if (dy !== 0)
this._proxy.ScrollRemote(Math.floor(dy), 'vertical');
if (dy !== 0) {
this._proxy.ScrollRemote(Math.floor(dy), 'vertical', cancellable, (_, e) => {
if (e && !e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
Util.Logger.critical(`${this._indicator.id}, failed to scroll vertically: ${e.message}`);
});
}
}
};
Signals.addSignalMethods(AppIndicator.prototype);
......@@ -772,7 +796,7 @@ class AppIndicatorsIconActor extends St.Icon {
return gicon;
}
if (pixmap)
if (pixmap && pixmap.length)
return this._createIconFromPixmap(iconSize, pixmap, iconType);
} catch (e) {
/* We handle the error messages already */
......@@ -785,7 +809,7 @@ class AppIndicatorsIconActor extends St.Icon {
}
// updates the base icon
_updateIcon() {
async _updateIcon() {
if (this.gicon instanceof Gio.EmblemedIcon) {
let { gicon } = this.gicon;
......@@ -798,10 +822,17 @@ class AppIndicatorsIconActor extends St.Icon {
? SNIconType.ATTENTION : SNIconType.NORMAL;
this._updateIconSize();
this._updateIconByType(iconType, this._iconSize);
try {
await this._updateIconByType(iconType, this._iconSize);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED) &&
!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING))
logError(e, `${this._indicator.id}: Updating icon type ${iconType} failed`);
}
}
_updateOverlayIcon() {
async _updateOverlayIcon() {
if (this._emblem) {
let { icon } = this._emblem;
......@@ -814,7 +845,13 @@ class AppIndicatorsIconActor extends St.Icon {
// our algorithms will always pick a smaller one instead of stretching it.
let iconSize = Math.floor(this._iconSize / 1.6);
this._updateIconByType(SNIconType.OVERLAY, iconSize);
try {
await this._updateIconByType(SNIconType.OVERLAY, iconSize);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED) &&
!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING))
logError(e, `${this._indicator.id}: Updating overlay icon failed`);
}
}
// called when the icon theme changes
......
......@@ -113,7 +113,12 @@ var IconCache = class AppIndicatorsIconCache {
Util.Logger.debug('IconCache: garbage collector started');
this._gcTimeout = new PromiseUtils.TimeoutSecondsPromise(GC_INTERVAL,
GLib.PRIORITY_LOW);
await this._gcTimeout;
try {
await this._gcTimeout;
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e, 'IconCache: garbage collector');
}
} else if (cacheIsEmpty && this._gcTimeout) {
Util.Logger.debug('IconCache: garbage collector stopped');
this._gcTimeout.cancel();
......
......@@ -250,12 +250,12 @@ class AppIndicatorsIndicatorStatusIcon extends BaseStatusIcon {
// if middle mouse button clicked send SecondaryActivate dbus event and do not show appindicator menu
if (buttonEvent.button === 2) {
Main.panel.menuManager._closeMenu(true, Main.panel.menuManager.activeMenu);
this._indicator.secondaryActivate();
this._indicator.secondaryActivate(buttonEvent.time, buttonEvent.x, buttonEvent.y);
return Clutter.EVENT_STOP;
}
if (buttonEvent.button === 1 && buttonEvent.click_count === 2) {
this._indicator.open();
this._indicator.open(buttonEvent.x, buttonEvent.y);
return Clutter.EVENT_STOP;
}
......@@ -368,21 +368,22 @@ class AppIndicatorsIndicatorTrayIcon extends BaseStatusIcon {
if (!this._touchPressSlot &&
touchEvent.type === Clutter.EventType.TOUCH_BEGIN) {
const buttonEvent = this._getSimulatedButtonEvent(touchEvent);
this.add_style_pseudo_class('active');
this._touchButtonEvent = this._getSimulatedButtonEvent(touchEvent);
this._touchPressSlot = slot;
this._touchDelayPromise = new PromiseUtils.TimeoutPromise(
AppDisplay.MENU_POPUP_TIMEOUT);
this._touchDelayPromise.then(() => {
delete this._touchDelayPromise;
delete this._touchPressSlot;
buttonEvent.set_button(3);
this._icon.click(buttonEvent);
this._touchButtonEvent.set_button(3);
this._icon.click(this._touchButtonEvent);
this.remove_style_pseudo_class('active');
});
} else if (touchEvent.type === Clutter.EventType.TOUCH_END &&
this._touchPressSlot === slot) {
delete this._touchPressSlot;
delete this._touchButtonEvent;
if (this._touchDelayPromise) {
this._touchDelayPromise.cancel();
delete this._touchDelayPromise;
......@@ -393,6 +394,7 @@ class AppIndicatorsIndicatorTrayIcon extends BaseStatusIcon {
} else if (touchEvent.type === Clutter.EventType.TOUCH_UPDATE &&
this._touchPressSlot === slot) {
this.add_style_pseudo_class('active');
this._touchButtonEvent = this._getSimulatedButtonEvent(touchEvent);
}
return Clutter.EVENT_PROPAGATE;
......
......@@ -70,6 +70,10 @@
<arg name="y" type="i" direction="in"/>
</method>
<method name="XAyatanaSecondaryActivate">
<arg name="timestamp" type="u" direction="in"/>
</method>
<method name="Scroll">
<arg name="delta" type="i" direction="in"/>
<arg name="orientation" type="s" direction="in"/>
......
......@@ -4,8 +4,10 @@ hu
it
ja
nl
pl
pt_BR
ru
sk
sr@latin
sr
tr
......
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the AppIndicatorExtension package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: AppIndicatorExtension\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-27 20:43+0200\n"
"PO-Revision-Date: 2022-01-12 14:32+0000\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0\n"
"Last-Translator: HydeFromT70s\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
"Language: pl\n"
#: prefs.js:67
msgid "Opacity (min: 0, max: 255)"
msgstr "Krycie (min: 0, max: 255)"
#: prefs.js:95
msgid "Desaturation (min: 0.0, max: 1.0)"
msgstr "Desaturacja (min: 0.0, max: 1.0)"
#: prefs.js:123
msgid "Brightness (min: -1.0, max: 1.0)"
msgstr "Jasność (min: -1.0, max: 1.0)"
#: prefs.js:151
msgid "Contrast (min: -1.0, max: 1.0)"
msgstr "Kontrast (min: -1.0, max: 1.0)"
#: prefs.js:179
msgid "Icon size (min: 0, max: 96)"
msgstr "Rozmiar ikon (min: 0, max: 96)"
#: prefs.js:207
msgid "Tray horizontal alignment"
msgstr "Wyśrodkowanie tacki systemowej"
#: prefs.js:212
msgid "Center"
msgstr "Centralnie"
#: prefs.js:213
msgid "Left"
msgstr "Po lewej"
#: prefs.js:214
msgid "Right"
msgstr "Po prawej"
#: prefs.js:259
msgid "Indicator ID"
msgstr "ID"
#: prefs.js:260
msgid "Icon Name"
msgstr "Nazwa ikony"
#: prefs.js:261
msgid "Attention Icon Name"
msgstr "Nazwa ikony uwagi"
#: prefs.js:336
msgid "Preferences"
msgstr "Ustawienia"
#: prefs.js:338
msgid "Custom Icons"
msgstr "Niestandardowe ikony"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:5
msgid "Saturation"
msgstr "Nasycenie"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:9
msgid "Brightness"
msgstr "Jasność"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:13
msgid "Contrast"
msgstr "Kontrast"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:17
msgid "Opacity"
msgstr "Krycie"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:21
msgid "Icon size"
msgstr "Rozmiar ikony"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:22
msgid "Icon size in pixel"
msgstr "Rozmiar ikony w pikselach"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:26
msgid "Icon spacing"
msgstr "Odstępy ikon"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:27
msgid "Icon spacing within the tray"
msgstr "Odstępy ikon na pasku zadań"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:31
msgid "Position in tray"
msgstr "Pozycja na pasku zadań"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:32
msgid "Set where the Icon tray should appear in Gnome tray"
msgstr "Ustaw, gdzie powinny pojawić się ikony na pasku zadań"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:36
msgid "Order in tray"
msgstr "Kolejność na pasku zadań"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:37
msgid "Set where the Icon tray should appear among other trays"
msgstr "Ustaw położenie tacki z ikonami między innymi tackami"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:41
msgid "Custom icons"
msgstr "Niestandardowe ikony"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:42
msgid "Replace any icons with custom icons from themes"
msgstr "Zastąp dowolne ikony niestandardowymi ikonami z motywów"
......@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-27 20:43+0200\n"
"PO-Revision-Date: 2017-08-26 04:16+0300\n"
"Last-Translator: Alex Gluck <alexgluck@bk.ru>\n"
"PO-Revision-Date: 2022-02-08 14:04+0300\n"
"Last-Translator: Aleksandr Melman <Alexmelman88@gmail.com>\n"
"Language-Team: \n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.0.3\n"
"X-Generator: Poedit 3.0\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
......@@ -57,83 +57,77 @@ msgstr "Справа"
#: prefs.js:259
msgid "Indicator ID"
msgstr ""
msgstr "Индикатор ID"
#: prefs.js:260
msgid "Icon Name"
msgstr ""
msgstr "Имя значка"
#: prefs.js:261
msgid "Attention Icon Name"
msgstr ""
msgstr "Заменяемое имя значка"
#: prefs.js:336
msgid "Preferences"
msgstr ""
msgstr "Параметры"
#: prefs.js:338
msgid "Custom Icons"
msgstr ""
msgstr "Пользовательские значки"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:5
msgid "Saturation"
msgstr ""
msgstr "Насыщенность"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:9
msgid "Brightness"
msgstr ""
msgstr "Яркость"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:13
msgid "Contrast"
msgstr ""
msgstr "Контрастность"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:17
msgid "Opacity"
msgstr ""
msgstr "Прозрачность"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:21
msgid "Icon size"
msgstr ""
msgstr "Размер значка"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:22
#, fuzzy
msgid "Icon size in pixel"
msgstr "Размер иконок (от 0 до 96)"
msgstr "Размер иконок в пикселях"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:26
msgid "Icon spacing"
msgstr ""
msgstr "Интервал между значками"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:27
msgid "Icon spacing within the tray"
msgstr ""
msgstr "Интервал между значками в трее"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:31
msgid "Position in tray"
msgstr ""
msgstr "Положение в трее"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:32
msgid "Set where the Icon tray should appear in Gnome tray"
msgstr ""
msgstr "Установить, где должен отображаться значок в трее Gnome"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:36
msgid "Order in tray"
msgstr ""
msgstr "Порядок в трее"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:37
msgid "Set where the Icon tray should appear among other trays"
msgstr ""
"Установить, где должен отображаться трей значков среди других треев"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:41
msgid "Custom icons"
msgstr ""
msgstr "Пользовательские значки"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:42
msgid "Replace any icons with custom icons from themes"
msgstr ""
#~ msgid "Spacing between icons (min: 0, max: 20)"
#~ msgstr "Расстояние между иконками (от 0 до 20)"
#~ msgid "Tray offset"
#~ msgstr "Сдвиг относительно других расширений"
msgstr "Заменить любые значки на пользовательские значки из тем"
# Slovak translation of gnome-shell-extension-appindicator.
# Copyright (C) 2022
# This file is distributed under the same license as the AppIndicatorExtension package.
# Jose Riha <jose1711 gmail com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: AppIndicatorExtension\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-27 20:43+0200\n"
"PO-Revision-Date: 2022-02-06 11:22+0100\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0\n"
"Last-Translator: Jose Riha <jose1711@gmail.com>\n"
"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);\n"
"Language: sk\n"
#: prefs.js:67
msgid "Opacity (min: 0, max: 255)"
msgstr "Krytie (min: 0, max: 255)"
#: prefs.js:95
msgid "Desaturation (min: 0.0, max: 1.0)"
msgstr "Odfarbenie (min: 0.0, max: 1.0)"
#: prefs.js:123
msgid "Brightness (min: -1.0, max: 1.0)"
msgstr "Jas (min: -1.0, max: 1.0)"
#: prefs.js:151
msgid "Contrast (min: -1.0, max: 1.0)"
msgstr "Kontrast (min: -1.0, max: 1.0)"
#: prefs.js:179
msgid "Icon size (min: 0, max: 96)"
msgstr "Veľkosť ikon (min: 0, max: 96)"
#: prefs.js:207
msgid "Tray horizontal alignment"
msgstr "Vodorovné zarovnanie lišty"
#: prefs.js:212
msgid "Center"
msgstr "V strede"
#: prefs.js:213
msgid "Left"
msgstr "Vľavo"
#: prefs.js:214
msgid "Right"
msgstr "Vpravo"
#: prefs.js:259
msgid "Indicator ID"
msgstr "ID"
#: prefs.js:260
msgid "Icon Name"
msgstr "Názov ikony"
#: prefs.js:261
msgid "Attention Icon Name"
msgstr "Názov ikony s upozornením"
#: prefs.js:336
msgid "Preferences"
msgstr "Predvoľby"
#: prefs.js:338
msgid "Custom Icons"
msgstr "Vlastné ikony"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:5
msgid "Saturation"
msgstr "Sýtosť"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:9
msgid "Brightness"
msgstr "Jas"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:13
msgid "Contrast"
msgstr "Kontrast"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:17
msgid "Opacity"
msgstr "Krytie"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:21
msgid "Icon size"
msgstr "Veľkosť ikony"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:22
msgid "Icon size in pixel"
msgstr "Veľkosť ikony v pixeloch"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:26
msgid "Icon spacing"
msgstr "Rozstupy medzi ikonami"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:27
msgid "Icon spacing within the tray"
msgstr "Rozstupy medzi ikonami na lište"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:31
msgid "Position in tray"
msgstr "Umiestnenie na lište"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:32
msgid "Set where the Icon tray should appear in Gnome tray"
msgstr "Nastavte, kde sa majú ikony na lište zobrazovať"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:36
msgid "Order in tray"
msgstr "Poradie na lište"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:37
msgid "Set where the Icon tray should appear among other trays"
msgstr "Nastavte, kde sa majú ikony na lište zobrazovať vzhľadom na ostatné ikony"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:41
msgid "Custom icons"
msgstr "Vlastné ikony"
#: schemas/org.gnome.shell.extensions.appindicator.gschema.xml:42
msgid "Replace any icons with custom icons from themes"
msgstr "Nahradiť ľubovoľné ikony vlastnými ikonami z motívov"
project('gnome-shell-ubuntu-appindicators',
version : '41',
version : '42',
meson_version : '>= 0.53',
license: 'GPL2',
)
......
......@@ -5,7 +5,8 @@
"3.36",
"3.38",
"40",
"41"
"41",
"42"
],
"gettext-domain": "AppIndicatorExtension",
"settings-schema": "org.gnome.shell.extensions.appindicator",
......
......@@ -14,41 +14,58 @@ var CancellablePromise = class extends Promise {
if (cancellable && !(cancellable instanceof Gio.Cancellable))
throw TypeError('cancellable parameter is not a Gio.Cancellable');
const cancelled = cancellable && cancellable.is_cancelled();
let cancellationId;
let rejector;
if (cancellable && !cancelled)
cancellationId = cancellable.connect(() => this.cancel());
let resolver;
super((resolve, reject) => {
resolver = resolve;
rejector = reject;
if (cancelled) {
reject(new GLib.Error(Gio.IOErrorEnum,
Gio.IOErrorEnum.CANCELLED, 'Promise cancelled'));
} else if (cancellationId) {
rejector = (...args) => {
reject(...args);
// This must happen in an idle not to deadlock on ::cancelled
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () =>
cancellable.disconnect(cancellationId));
};
executor((...args) => {
resolve(...args);
cancellable.disconnect(cancellationId);
}, rejector);
} else {
executor(resolve, reject);
}
});
this._cancelled = cancelled;
this._rejector = rejector;
this._cancellable = cancellable || null;
this._resolver = (...args) => {
resolver(...args);
this._resolved = true;
this._cleanup();
};
this._rejector = (...args) => {
rejector(...args);
this._rejected = true;
this._cleanup();
};
if (!cancellable) {
executor(this._resolver, this._rejector);
return;
}
this._cancellable = cancellable;
this._cancelled = cancellable.is_cancelled();
if (this._cancelled) {
this._rejector(new GLib.Error(Gio.IOErrorEnum,
Gio.IOErrorEnum.CANCELLED, 'Promise cancelled'));
return;
}
this._cancellationId = cancellable.connect(() => {
const id = this._cancellationId;
this._cancellationId = 0;
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => cancellable.disconnect(id));
this.cancel();
});
executor(this._resolver, this._rejector);
}
_cleanup() {
if (this._cancellationId)
this._cancellable.disconnect(this._cancellationId);
}
get cancellable() {
return this._cancellable;
return this._chainRoot._cancellable || null;
}
get _chainRoot() {
return this._root ? this._root : this;
}
then(...args) {
......@@ -62,21 +79,25 @@ var CancellablePromise = class extends Promise {
* the same method on the root object is called during cancellation
* or any destruction method if you want this to work. */
if (ret instanceof CancellablePromise)
ret._root = this._root || this;
ret._root = this._chainRoot;
return ret;
}
resolved() {
return !this.cancelled() && !!(this._root || this)._resolved;
return !!this._chainRoot._resolved;
}
rejected() {
return !!this._chainRoot._rejected;
}
cancelled() {
return !!(this._root || this)._cancelled;
return !!this._chainRoot._cancelled;
}
pending() {
return !this.resolved() && !this.cancelled();
return !this.resolved() && !this.rejected();
}
cancel() {
......@@ -85,10 +106,10 @@ var CancellablePromise = class extends Promise {
return this;
}
if (!this._rejector)
throw new GObject.NotImplementedError();
if (!this.pending())
return this;
this._cancelled = !this._resolved;
this._cancelled = true;
this._rejector(new GLib.Error(Gio.IOErrorEnum,
Gio.IOErrorEnum.CANCELLED, 'Promise cancelled'));
......@@ -113,15 +134,23 @@ var SignalConnectionPromise = class extends CancellablePromise {
let id;
let destroyId;
super(resolve => {
id = object.connect(signal, (_obj, ...args) => {
this._resolved = !this.cancelled();
this.disconnect();
resolve(args.length === 1 ? args[0] : args);
let connectSignal;
if (object instanceof GObject.Object)
connectSignal = (sig, cb) => GObject.signal_connect(object, sig, cb);
else
connectSignal = (sig, cb) => object.connect(sig, cb);
id = connectSignal(signal, (_obj, ...args) => {
if (!args.length)
resolve();
else
resolve(args.length === 1 ? args[0] : args);
});
if (!(object instanceof GObject.Object) ||
GObject.signal_lookup('destroy', object.constructor.$gtype))
destroyId = object.connect('destroy', () => this.cancel());
if (signal !== 'destroy' &&
(!(object instanceof GObject.Object) ||
GObject.signal_lookup('destroy', object.constructor.$gtype)))
destroyId = connectSignal('destroy', () => this.cancel());
}, cancellable);
this._object = object;
......@@ -129,27 +158,29 @@ var SignalConnectionPromise = class extends CancellablePromise {
this._destroyId = destroyId;
}
disconnect() {
if (this._root) {
this._root.disconnect();
return this;
}
_cleanup() {
if (this._id) {
this._object.disconnect(this._id);
let disconnectSignal;
if (this._object instanceof GObject.Object)
disconnectSignal = id => GObject.signal_handler_disconnect(this._object, id);
else
disconnectSignal = id => this._object.disconnect(id);
disconnectSignal(this._id);
if (this._destroyId) {
this._object.disconnect(this._destroyId);
disconnectSignal(this._destroyId);
this._destroyId = 0;
}
this._object = null;
this._id = 0;
}
return this;
super._cleanup();
}
cancel() {
this.disconnect();
return super.cancel();
get object() {
return this._chainRoot._object;
}
};
......@@ -163,45 +194,39 @@ var GSourcePromise = class extends CancellablePromise {
if (gsource.constructor.$gtype !== GLib.Source.$gtype)
throw new TypeError(`gsource ${gsource} is not of type GLib.Source`);
if (!priority)
if (priority === undefined)
priority = GLib.PRIORITY_DEFAULT;
else if (!Number.isInteger(priority))
throw TypeError('Invalid priority');
super(resolve => {
gsource.set_priority(priority);
gsource.set_callback(() => {
this._resolved = !this.cancelled();
this.remove();
resolve();
return GLib.SOURCE_REMOVE;
});
gsource.set_name(`[gnome-shell] Source promise ${
new Error().stack.split('\n').filter(line =>
!line.match(/promiseUtils\.js/))[0]}`);
gsource.attach(null);
}, cancellable);
this._gsource = gsource;
this._gsource.set_name(`[gnome-shell] ${this.constructor.name} ${
new Error().stack.split('\n').filter(line =>
!line.match(/misc\/promiseUtils\.js/))[0]}`);
if (this.cancelled())
this.remove();
if (this.rejected())
this._gsource.destroy();
}
remove() {
if (this._root) {
this._root.remove();
return this;
}
get gsource() {
return this._chainRoot._gsource;
}
_cleanup() {
if (this._gsource) {
this._gsource.destroy();
this._gsource = null;
}
return this;
}
cancel() {
this.remove();
return super.cancel();
super._cleanup();
}
};
......@@ -214,8 +239,6 @@ var IdlePromise = class extends GSourcePromise {
if (priority === undefined)
priority = GLib.PRIORITY_DEFAULT_IDLE;
else if (!Number.isInteger(priority))
throw TypeError('Invalid priority');
super(GLib.idle_source_new(), priority, cancellable);
}
......@@ -264,7 +287,6 @@ var MetaLaterPromise = class extends CancellablePromise {
let id;
super(resolve => {
id = Meta.later_add(laterType, () => {
this._resolved = !this.cancelled();
this.remove();
resolve();
return GLib.SOURCE_REMOVE;
......@@ -274,22 +296,12 @@ var MetaLaterPromise = class extends CancellablePromise {
this._id = id;
}
remove() {
if (this._root) {
this._root.remove();
return this;
}
_cleanup() {
if (this._id) {
Meta.later_remove(this._id);
this._id = 0;
}
return this;
}
cancel() {
this.remove();
return super.cancel();
super._cleanup();
}
};
......@@ -313,7 +325,14 @@ _promisifySignals(GObject.Object.prototype);
var _promisify = Gio._promisify;
if (imports.system.version < 16501) {
/* This is backported from upstream gjs, so that all the features are available */
_promisify = function (proto, asyncFunc, finishFunc) {
_promisify = function (proto, asyncFunc,
finishFunc = `${asyncFunc.replace(/_(begin|async)$/, '')}_finish`) {
if (proto[asyncFunc] === undefined)
throw new Error(`${proto} has no method named ${asyncFunc}`);
if (proto[finishFunc] === undefined)
throw new Error(`${proto} has no method named ${finishFunc}`);
if (proto[`_original_${asyncFunc}`] !== undefined)
return;
proto[`_original_${asyncFunc}`] = proto[asyncFunc];
......
......@@ -142,7 +142,7 @@ var StatusNotifierWatcher = class AppIndicatorsStatusNotifierWatcher {
await new PromiseUtils.IdlePromise(GLib.PRIORITY_LOW, cancellable);
const bus = Gio.DBus.session;
const uniqueNames = await Util.getBusNames(bus, cancellable);
uniqueNames.forEach(async name => {
const introspectName = async name => {
const nodes = await Util.introspectBusObject(bus, name, cancellable);
nodes.forEach(({ nodeInfo, path }) => {
if (Util.dbusNodeImplementsInterfaces(nodeInfo, ['org.kde.StatusNotifierItem'])) {
......@@ -154,7 +154,8 @@ var StatusNotifierWatcher = class AppIndicatorsStatusNotifierWatcher {
}
}
});
});
};
await Promise.allSettled([...uniqueNames].map(n => introspectName(n)));
}
async RegisterStatusNotifierItemAsync(params, invocation) {
......